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 <pirun.lee@nordicsemi.no>
This commit is contained in:
Pirun Lee 2023-01-10 09:52:57 +08:00 committed by Carles Cufí
commit 7015578ff4
4 changed files with 75 additions and 19 deletions

View file

@ -9,7 +9,7 @@ Overview
Similar to the :ref:`Central <bluetooth_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
************

View file

@ -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);

View file

@ -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

View file

@ -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)