From 7015578ff4fc4e2db354e86d06d51cf1cd0855ec Mon Sep 17 00:00:00 2001 From: Pirun Lee Date: Tue, 10 Jan 2023 09:52:57 +0800 Subject: [PATCH] sample: bluetooth: OTS sample add checksum central_otc: read checksum after object data read. peripheral_ots: add checksum calculate cb. Signed-off-by: Pirun Lee --- samples/bluetooth/central_otc/README.rst | 2 +- samples/bluetooth/central_otc/src/main.c | 65 ++++++++++++++++----- samples/bluetooth/peripheral_ots/prj.conf | 2 +- samples/bluetooth/peripheral_ots/src/main.c | 25 ++++++-- 4 files changed, 75 insertions(+), 19 deletions(-) diff --git a/samples/bluetooth/central_otc/README.rst b/samples/bluetooth/central_otc/README.rst index 31e512132b6..29de983005b 100644 --- a/samples/bluetooth/central_otc/README.rst +++ b/samples/bluetooth/central_otc/README.rst @@ -9,7 +9,7 @@ Overview Similar to the :ref:`Central ` sample, except that this application specifically looks for the OTS (Object Transfer) GATT Service. And this sample is to select object sequentially, to read metadata, to write data, -to read data of selected ojects. +to read data, and to calculate checksum of selected ojects. Requirements ************ diff --git a/samples/bluetooth/central_otc/src/main.c b/samples/bluetooth/central_otc/src/main.c index fab4f84bcfd..dd1b980e708 100644 --- a/samples/bluetooth/central_otc/src/main.c +++ b/samples/bluetooth/central_otc/src/main.c @@ -33,6 +33,7 @@ static struct bt_gatt_discover_params discover_params; static struct bt_gatt_subscribe_params *oacp_sub_params; static struct bt_gatt_subscribe_params *olcp_sub_params; static unsigned char obj_data_buf[OBJ_MAX_SIZE]; +static uint32_t last_checksum; static bool first_selected; static void on_obj_selected(struct bt_ots_client *ots_inst, struct bt_conn *conn, int err); @@ -81,19 +82,25 @@ static void print_hex_number(const uint8_t *num, size_t len) #error "Unsupported board: This sample need 4 buttons to run" #endif -static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0}); +static const struct gpio_dt_spec button0 = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0}); static const struct gpio_dt_spec button1 = GPIO_DT_SPEC_GET_OR(SW1_NODE, gpios, {0}); static const struct gpio_dt_spec button2 = GPIO_DT_SPEC_GET_OR(SW2_NODE, gpios, {0}); static const struct gpio_dt_spec button3 = GPIO_DT_SPEC_GET_OR(SW3_NODE, gpios, {0}); #define BTN_COUNT 4 -static const struct gpio_dt_spec btns[BTN_COUNT] = {button, button1, button2, button3}; +static const struct gpio_dt_spec btns[BTN_COUNT] = {button0, button1, button2, button3}; static struct gpio_callback button_cb_data; struct otc_btn_work_info { struct k_work_delayable work; uint32_t pins; } otc_btn_work; +struct otc_checksum_work_info { + struct k_work_delayable work; + off_t offset; + size_t len; +} otc_checksum_work; + static void otc_btn_work_fn(struct k_work *work) { struct k_work_delayable *dwork = k_work_delayable_from_work(work); @@ -101,7 +108,7 @@ static void otc_btn_work_fn(struct k_work *work) int err; size_t size_to_write; - if (btn_work->pins == BIT(button.pin)) { + if (btn_work->pins == BIT(button0.pin)) { if (!first_selected) { err = bt_ots_client_select_id(&otc, default_conn, BT_OTS_OBJ_ID_MIN); first_selected = true; @@ -111,8 +118,7 @@ static void otc_btn_work_fn(struct k_work *work) } if (err != 0) { - printk("Failed to select object\n"); - return; + printk("Failed to select object (err %d)\n", err); } printk("Selecting object succeeded\n"); @@ -121,8 +127,7 @@ static void otc_btn_work_fn(struct k_work *work) err = bt_ots_client_read_object_metadata(&otc, default_conn, BT_OTS_METADATA_REQ_ALL); if (err != 0) { - printk("Failed to read object metadata\n"); - return; + printk("Failed to read object metadata (err %d)\n", err); } } else if (btn_work->pins == BIT(button2.pin)) { @@ -134,12 +139,13 @@ static void otc_btn_work_fn(struct k_work *work) obj_data_buf[idx] = UINT8_MAX - (idx % UINT8_MAX); } + last_checksum = bt_ots_client_calc_checksum(obj_data_buf, size_to_write); + printk("Data sent checksum 0x%08x\n", last_checksum); err = bt_ots_client_write_object_data(&otc, default_conn, obj_data_buf, - size_to_write, 0, - BT_OTS_OACP_WRITE_OP_MODE_NONE); + size_to_write, 0, + BT_OTS_OACP_WRITE_OP_MODE_NONE); if (err != 0) { - printk("Failed to write object (%d)\n", err); - return; + printk("Failed to write object (err %d)\n", err); } } else { printk("This OBJ does not support WRITE OP\n"); @@ -151,7 +157,6 @@ static void otc_btn_work_fn(struct k_work *work) err = bt_ots_client_read_object_data(&otc, default_conn); if (err != 0) { printk("Failed to read object %d\n", err); - return; } } else { printk("This OBJ does not support READ OP\n"); @@ -159,6 +164,20 @@ static void otc_btn_work_fn(struct k_work *work) } } +static void otc_checksum_work_fn(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct otc_checksum_work_info *checksum_work = + CONTAINER_OF(dwork, struct otc_checksum_work_info, work); + int err; + + err = bt_ots_client_get_object_checksum(&otc, default_conn, checksum_work->offset, + checksum_work->len); + if (err != 0) { + printk("bt_ots_client_get_object_checksum failed (%d)\n", err); + } +} + static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { otc_btn_work.pins = pins; @@ -538,7 +557,7 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { static void on_obj_selected(struct bt_ots_client *ots_inst, struct bt_conn *conn, int err) { - printk("Current object selected cb %d\n", err); + printk("Current object selected cb OLCP result (%d)\n", err); if (err == BT_GATT_OTS_OLCP_RES_OPERATION_FAILED) { printk("BT_GATT_OTS_OLCP_RES_OPERATION_FAILED %d\n", err); @@ -568,6 +587,9 @@ static int on_obj_data_read(struct bt_ots_client *ots_inst, struct bt_conn *conn printk("Object total received %d\n", len + offset); print_hex_number(obj_data_buf, len + offset); (void)memset(obj_data_buf, 0, OBJ_MAX_SIZE); + otc_checksum_work.offset = 0; + otc_checksum_work.len = otc.cur_object.size.cur; + k_work_schedule(&otc_checksum_work.work, K_NO_WAIT); return BT_OTS_STOP; } @@ -589,7 +611,22 @@ static void on_obj_metadata_read(struct bt_ots_client *ots_inst, struct bt_conn } static void on_obj_data_written(struct bt_ots_client *ots_inst, struct bt_conn *conn, size_t len) { + int err; + printk("Object been written %d\n", len); + /* Update object size after write done*/ + err = bt_ots_client_read_object_metadata(&otc, default_conn, + BT_OTS_METADATA_REQ_ALL); + if (err != 0) { + printk("Failed to read object metadata (err %d)\n", err); + } +} + +void on_obj_checksum_calculated(struct bt_ots_client *ots_inst, + struct bt_conn *conn, int err, uint32_t checksum) +{ + printk("Object Calculate checksum OACP result (%d)\nChecksum 0x%08x last sent 0x%08x %s\n", + err, checksum, last_checksum, (checksum == last_checksum) ? "match" : "not match"); } static void bt_otc_init(void) @@ -598,6 +635,7 @@ static void bt_otc_init(void) otc_cb.obj_selected = on_obj_selected; otc_cb.obj_metadata_read = on_obj_metadata_read; otc_cb.obj_data_written = on_obj_data_written; + otc_cb.obj_checksum_calculated = on_obj_checksum_calculated; otc.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; otc.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; printk("Current object selected callback: %p\n", otc_cb.obj_selected); @@ -614,6 +652,7 @@ void main(void) first_selected = false; discovery_state = ATOMIC_INIT(0); k_work_init_delayable(&otc_btn_work.work, otc_btn_work_fn); + k_work_init_delayable(&otc_checksum_work.work, otc_checksum_work_fn); configure_buttons(); err = bt_enable(NULL); diff --git a/samples/bluetooth/peripheral_ots/prj.conf b/samples/bluetooth/peripheral_ots/prj.conf index dc88dcbd2ba..b110a750dc3 100644 --- a/samples/bluetooth/peripheral_ots/prj.conf +++ b/samples/bluetooth/peripheral_ots/prj.conf @@ -8,7 +8,7 @@ CONFIG_BT_OTS_OACP_WRITE_SUPPORT=y CONFIG_BT_OTS_OACP_PATCH_SUPPORT=y CONFIG_BT_OTS_OACP_CREATE_SUPPORT=y CONFIG_BT_OTS_OACP_DELETE_SUPPORT=y - +CONFIG_BT_OTS_OACP_CHECKSUM_SUPPORT=y CONFIG_LOG=y CONFIG_ASSERT=y # This sample needs more memory on BT_RX_THREAD diff --git a/samples/bluetooth/peripheral_ots/src/main.c b/samples/bluetooth/peripheral_ots/src/main.c index 6d47c056102..daa14eafb0f 100644 --- a/samples/bluetooth/peripheral_ots/src/main.c +++ b/samples/bluetooth/peripheral_ots/src/main.c @@ -43,6 +43,8 @@ struct object_creation_data { uint32_t props; }; +#define OTS_OBJ_ID_TO_OBJ_IDX(id) (((id) - BT_OTS_OBJ_ID_MIN) % ARRAY_SIZE(objects)) + static struct object_creation_data *object_being_created; static void connected(struct bt_conn *conn, uint8_t err) @@ -133,11 +135,12 @@ static void ots_obj_selected(struct bt_ots *ots, struct bt_conn *conn, } static ssize_t ots_obj_read(struct bt_ots *ots, struct bt_conn *conn, - uint64_t id, void **data, size_t len, - off_t offset) + uint64_t id, void **data, size_t len, + off_t offset) { char id_str[BT_OTS_OBJ_ID_STR_LEN]; - uint32_t obj_index = ((id - BT_OTS_OBJ_ID_MIN) % ARRAY_SIZE(objects)); + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + bt_ots_obj_id_to_str(id, id_str, sizeof(id_str)); if (!data) { @@ -168,7 +171,7 @@ static ssize_t ots_obj_write(struct bt_ots *ots, struct bt_conn *conn, off_t offset, size_t rem) { char id_str[BT_OTS_OBJ_ID_STR_LEN]; - uint32_t obj_index = ((id - BT_OTS_OBJ_ID_MIN) % ARRAY_SIZE(objects)); + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); bt_ots_obj_id_to_str(id, id_str, sizeof(id_str)); @@ -192,6 +195,19 @@ static void ots_obj_name_written(struct bt_ots *ots, struct bt_conn *conn, id_str, cur_name, new_name); } +static int ots_obj_cal_checksum(struct bt_ots *ots, struct bt_conn *conn, uint64_t id, + off_t offset, size_t len, void **data) +{ + uint32_t obj_index = OTS_OBJ_ID_TO_OBJ_IDX(id); + + if (obj_index >= OBJ_POOL_SIZE) { + return -ENOENT; + } + + *data = &objects[obj_index].data[offset]; + return 0; +} + static struct bt_ots_cb ots_callbacks = { .obj_created = ots_obj_created, .obj_deleted = ots_obj_deleted, @@ -199,6 +215,7 @@ static struct bt_ots_cb ots_callbacks = { .obj_read = ots_obj_read, .obj_write = ots_obj_write, .obj_name_written = ots_obj_name_written, + .obj_cal_checksum = ots_obj_cal_checksum, }; static int ots_init(void)