From 21b630e23fdcc7d401402f1135e3cdffccf59164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 18 Aug 2023 07:38:29 +0200 Subject: [PATCH] apps/btshell: add support for sending Multiple handle Notifications Added commands for queueing notifications to be sent using Multiple Handle Notification, sending them and clearing pending queue. --- apps/btshell/src/btshell.h | 6 +++ apps/btshell/src/cmd.c | 58 +++++++++++++++++++++ apps/btshell/src/cmd_gatt.c | 72 ++++++++++++++++++++++++++ apps/btshell/src/cmd_gatt.h | 3 ++ apps/btshell/src/main.c | 78 +++++++++++++++++++++++++++++ nimble/host/include/host/ble_gatt.h | 4 +- nimble/host/src/ble_gattc.c | 4 +- 7 files changed, 221 insertions(+), 4 deletions(-) diff --git a/apps/btshell/src/btshell.h b/apps/btshell/src/btshell.h index 021f54c88d..20cb95f077 100644 --- a/apps/btshell/src/btshell.h +++ b/apps/btshell/src/btshell.h @@ -124,6 +124,12 @@ int btshell_write_long(uint16_t conn_handle, uint16_t attr_handle, uint16_t offset, struct os_mbuf *om); int btshell_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs, int num_attrs); +#if MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) +int btshell_enqueue_notif(uint16_t handle, uint16_t len, uint8_t *value); +int btshell_send_pending_notif(uint16_t conn_handle); +int btshell_clear_pending_notif(void); +#endif + #if MYNEWT_VAL(BLE_EXT_ADV) int btshell_ext_adv_configure(uint8_t instance, const struct ble_gap_ext_adv_params *params, diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c index 1bdd48e89d..60972635dc 100644 --- a/apps/btshell/src/cmd.c +++ b/apps/btshell/src/cmd.c @@ -3497,6 +3497,43 @@ static const struct shell_cmd_help gatt_write_help = { .usage = NULL, .params = gatt_write_params, }; + +/***************************************************************************** + * $gatt-enqueue-notify * + *****************************************************************************/ + +static const struct shell_param gatt_enqueue_notif_params[] = { + {"handle", "characteristic handle, usage: ="}, + {"value", "usage: ="}, + {NULL, NULL} +}; + +static const struct shell_cmd_help gatt_enqueue_notif_help = { + .summary = "enqueue notification to be sent", + .usage = NULL, + .params = gatt_enqueue_notif_params, +}; + +/***************************************************************************** + * $gatt-send-pending-notify * + *****************************************************************************/ + +static const struct shell_param gatt_send_pending_notif_params[] = { + {"conn", "connection handle, usage: ="}, + {NULL, NULL} +}; + +static const struct shell_cmd_help gatt_send_pending_notif_help = { + .summary = "send pending notifications", + .usage = NULL, + .params = gatt_send_pending_notif_params, +}; + +static const struct shell_cmd_help gatt_clear_pending_notif_help = { + .summary = "clear pending notifications", + .usage = NULL, + .params = NULL, +}; #endif #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) @@ -4417,6 +4454,27 @@ static const struct shell_cmd btshell_commands[] = { .sc_cmd_func = cmd_gatt_write, #if MYNEWT_VAL(SHELL_CMD_HELP) .help = &gatt_write_help, +#endif + }, + { + .sc_cmd = "gatt-enqueue-notif", + .sc_cmd_func = cmd_gatt_enqueue_notif, +#if MYNEWT_VAL(SHELL_CMD_HELP) + .help = &gatt_enqueue_notif_help, +#endif + }, + { + .sc_cmd = "gatt-send-queued-notif", + .sc_cmd_func = cmd_gatt_send_pending_notif, +#if MYNEWT_VAL(SHELL_CMD_HELP) + .help = &gatt_send_pending_notif_help, +#endif + }, + { + .sc_cmd = "gatt-clear-queued-notif", + .sc_cmd_func = cmd_gatt_clear_pending_notif, +#if MYNEWT_VAL(SHELL_CMD_HELP) + .help = &gatt_clear_pending_notif_help, #endif }, #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) diff --git a/apps/btshell/src/cmd_gatt.c b/apps/btshell/src/cmd_gatt.c index 734b100476..3011dd9cab 100644 --- a/apps/btshell/src/cmd_gatt.c +++ b/apps/btshell/src/cmd_gatt.c @@ -592,3 +592,75 @@ cmd_gatt_write(int argc, char **argv) return rc; } + +int +cmd_gatt_enqueue_notif(int argc, char **argv) +{ +#if MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) + int rc; + uint16_t handle; + unsigned int len; + uint8_t value[BLE_ATT_ATTR_MAX_LEN]; + + rc = parse_arg_init(argc - 1, argv + 1); + if (rc != 0) { + return rc; + } + + handle = parse_arg_uint16("handle", &rc); + if (rc != 0) { + console_printf("invalid 'handle' parameter\n"); + return rc; + } + + if (argc > 1) { + rc = parse_arg_byte_stream("value", BLE_ATT_ATTR_MAX_LEN, value, &len); + if (rc != 0) { + console_printf("invalid 'value' parameter\n"); + return rc; + } + return btshell_enqueue_notif(handle, len, value); + } else { + return btshell_enqueue_notif(handle, 0, NULL); + } +#else + console_printf("To enable this features set BLE_GATT_NOTIFY_MULTIPLE\n"); + return ENOTSUP; +#endif +} + +int +cmd_gatt_send_pending_notif(int argc, char **argv) +{ +#if MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) + uint16_t conn_handle; + int rc; + + rc = parse_arg_init(argc - 1, argv + 1); + if (rc != 0) { + return rc; + } + + conn_handle = parse_arg_uint16("conn", &rc); + if (rc != 0) { + console_printf("invalid 'conn' parameter\n"); + return rc; + } + + return btshell_send_pending_notif(conn_handle); +#else + console_printf("To enable this features set BLE_GATT_NOTIFY_MULTIPLE\n"); + return ENOTSUP; +#endif +} + +int +cmd_gatt_clear_pending_notif(int argc, char **argv) +{ +#if MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) + return btshell_clear_pending_notif(); +#else + console_printf("To enable this features set BLE_GATT_NOTIFY_MULTIPLE\n"); + return ENOTSUP; +#endif +} diff --git a/apps/btshell/src/cmd_gatt.h b/apps/btshell/src/cmd_gatt.h index 70536d03ce..ae517f9a1c 100644 --- a/apps/btshell/src/cmd_gatt.h +++ b/apps/btshell/src/cmd_gatt.h @@ -35,5 +35,8 @@ int cmd_gatt_service_visibility(int argc, char **argv); int cmd_gatt_show(int argc, char **argv); int cmd_gatt_show_local(int argc, char **argv); int cmd_gatt_write(int argc, char **argv); +int cmd_gatt_enqueue_notif(int argc, char **argv); +int cmd_gatt_send_pending_notif(int argc, char **argv); +int cmd_gatt_clear_pending_notif(int argc, char **argv); #endif diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c index aaa423ea8b..69ecf9231a 100644 --- a/apps/btshell/src/main.c +++ b/apps/btshell/src/main.c @@ -107,6 +107,11 @@ struct os_mbuf_pool sdu_os_mbuf_pool; static struct os_mempool sdu_coc_mbuf_mempool; #endif +#if MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) +static struct ble_gatt_notif pending_notif[BTSHELL_MAX_CHRS]; +static size_t pending_notif_cnt; +#endif + static struct os_callout btshell_tx_timer; struct btshell_tx_data_s { @@ -1761,6 +1766,79 @@ btshell_write_reliable(uint16_t conn_handle, return rc; } +#if MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) +int +btshell_enqueue_notif(uint16_t handle, uint16_t len, uint8_t *value) +{ + struct ble_gatt_notif *notify = NULL; + struct os_mbuf *val_ptr; + int i; + + for (i = 0; i < BTSHELL_MAX_CHRS; i++) { + if (pending_notif[i].handle == 0) { + notify = &pending_notif[i]; + break; + } + } + + if (notify == NULL) { + return ENOMEM; + } + + notify->handle = handle; + if (value != NULL) { + notify->value = os_msys_get(0, 0); + + val_ptr = os_mbuf_extend(notify->value, len); + if (val_ptr == NULL) { + return ENOMEM; + } + memcpy(val_ptr, value, len); + } + + pending_notif_cnt++; + + return 0; +} + +int +btshell_send_pending_notif(uint16_t conn_handle) +{ + int rc = 0; + int i; + + if (pending_notif_cnt == 0) { + return EALREADY; + } + + rc = ble_gatts_notify_multiple_custom(conn_handle, pending_notif_cnt, + pending_notif); + for (i = 0; i < pending_notif_cnt; i++) { + pending_notif[i].handle = 0; + pending_notif[i].value = NULL; + } + + pending_notif_cnt = 0; + + return rc; +} + +int +btshell_clear_pending_notif(void) +{ + int i; + + for (i = 0; i < pending_notif_cnt; i++) { + pending_notif[i].handle = 0; + pending_notif[i].value = NULL; + } + + pending_notif_cnt = 0; + + return 0; +} +#endif + #if MYNEWT_VAL(BLE_EXT_ADV) int btshell_ext_adv_configure(uint8_t instance, diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index b4501a85bc..956a232463 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -668,7 +668,7 @@ int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t att_handle, * @return 0 on success; nonzero on failure. */ int ble_gatts_notify_multiple_custom(uint16_t conn_handle, - uint16_t chr_count, + size_t chr_count, struct ble_gatt_notif *tuples); /** @@ -719,7 +719,7 @@ int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle); * @return 0 on success; nonzero on failure. */ int ble_gatts_notify_multiple(uint16_t conn_handle, - uint8_t num_handles, + size_t num_handles, const uint16_t *chr_val_handles); /** diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 22598d60b4..ae383f9df2 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -4415,7 +4415,7 @@ ble_gatts_notify(uint16_t conn_handle, uint16_t chr_val_handle) int ble_gatts_notify_multiple_custom(uint16_t conn_handle, - uint16_t chr_count, + size_t chr_count, struct ble_gatt_notif *tuples) { #if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) @@ -4500,7 +4500,7 @@ ble_gatts_notify_multiple_custom(uint16_t conn_handle, int ble_gatts_notify_multiple(uint16_t conn_handle, - uint8_t num_handles, + size_t num_handles, const uint16_t *chr_val_handles) { #if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE)