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:
parent
1e6f36cca7
commit
7015578ff4
4 changed files with 75 additions and 19 deletions
|
@ -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
|
||||
************
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue