fix(nimble): Add separate helper functions to register notification/indication

This commit is contained in:
Rahul Tank
2026-08-18 07:35:59 +05:30
parent 5f235bdf6f
commit 3e30c9f70b
2 changed files with 116 additions and 28 deletions
+58 -4
View File
@@ -953,15 +953,54 @@ int ble_gatts_notify(uint16_t conn_handle, uint16_t chr_val_handle);
int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle);
/**
* Unregisters for notifications on a specified characteristic by writing to its
* Client Characteristic Configuration Descriptor (CCCD).
* Sends a multiple handle variable length characteristic notification. The
* content of the message is read from the specified characteristics.
* Notifications are sent in order of supplied handles. Function tries to
* send minimum amount of PDUs. If PDU can't contain all of the
* characteristic values, multiple notifications are sent. If only one
* handle-value pair fits into PDU, or only one characteristic remains in the
* list, regular characteristic notification is sent.
*
* If GATT client doesn't support receiving multiple handle notifications,
* this will use GATT notification for each characteristic, separately.
*
* @param conn_handle The connection over which to execute the
* procedure.
* @param num_handles The number of entries in the "chr_val_handles"
* array.
* @param chr_val_handles Array of attribute handles of the
* characteristics to include in the outgoing
* notification.
*
* @return 0 on success; nonzero on failure.
*/
int ble_gatts_notify_multiple(uint16_t conn_handle,
size_t num_handles,
const uint16_t *chr_val_handles);
/**
* Unregisters for notifications and indications on a specified characteristic
* by writing to its Client Characteristic Configuration Descriptor (CCCD).
*
* This function initiates discovery of all descriptors associated with the given
* characteristic value handle (`char_val_handle`). If a CCCD is found, it writes
* a value to disable notifications.
* zero to disable both notifications and indications.
*
* @param conn_handle The handle of the connection with the peer device.
* @param char_val_handle The value handle of the characteristic to unregister from notification.
* @param char_val_handle The value handle of the characteristic to unregister
* from notifications and indications.
*
* @return 0 on success, non-zero error code on failure.
*/
int ble_gattc_unregister_notif_indicate(uint16_t conn_handle,
uint16_t char_val_handle);
/**
* Deprecated. Use ble_gattc_unregister_notif_indicate instead.
*
* @param conn_handle The handle of the connection with the peer device.
* @param char_val_handle The value handle of the characteristic to unregister
* from notifications and indications.
*
* @return 0 on success, non-zero error code on failure.
*/
@@ -982,6 +1021,21 @@ int ble_gattc_unregister_for_notification(uint16_t conn_handle, uint16_t char_va
*/
int ble_gattc_register_for_notification(uint16_t conn_handle, uint16_t char_val_handle);
/**
* Registers for indications on a specified characteristic by writing to its
* Client Characteristic Configuration Descriptor (CCCD).
*
* This function initiates discovery of all descriptors associated with the given
* characteristic value handle (`char_val_handle`). If a CCCD is found, it writes
* the appropriate value to enable indications.
*
* @param conn_handle The handle of the connection with the peer device.
* @param char_val_handle The value handle of the characteristic to register for indication.
*
* @return 0 on success, non-zero error code on failure.
*/
int ble_gattc_register_for_indication(uint16_t conn_handle, uint16_t char_val_handle);
/**
* Sends a "free-form" characteristic indication. The provided mbuf contains
* the indication payload. This function consumes the supplied mbuf regardless
+58 -24
View File
@@ -5718,6 +5718,11 @@ ble_gattc_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle,
#if MYNEWT_VAL(BLE_GATTC)
#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS)
struct ble_gattc_cccd_reg_arg {
bool active;
uint16_t value;
};
static int
ble_gattc_cccd_write_complete_cb(uint16_t conn_handle,
const struct ble_gatt_error *error,
@@ -5737,44 +5742,47 @@ static int ble_gattc_cccd_register_cb(uint16_t conn_handle, const struct ble_gat
void *arg)
{
int rc = error->status;
bool *cccd_reg_flag = (bool *)arg;
struct ble_gattc_cccd_reg_arg *reg_arg = arg;
if (error->status == BLE_HS_EDONE) {
/* GATT procedure completed reset active flag */
gatt_proc_active = false;
if (cccd_reg_flag) {
nimble_platform_mem_free(cccd_reg_flag);
if (reg_arg) {
nimble_platform_mem_free(reg_arg);
}
} else if (error->status == 0) {
if (cccd_reg_flag && *cccd_reg_flag &&
if (reg_arg && reg_arg->active &&
(ble_uuid_cmp(&dsc->uuid.u, BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16)) == 0)) {
/* Prevent duplicate CCCD writes */
*cccd_reg_flag = false;
/* Enable notification */
uint8_t cccd_val[2] = {0x01, 0x00};
reg_arg->active = false;
uint8_t cccd_val[2] = {
reg_arg->value & 0xff,
(reg_arg->value >> 8) & 0xff,
};
/* write to CCCD to enable notifications */
rc = ble_gattc_write_flat(conn_handle,
dsc->handle,
cccd_val, sizeof(cccd_val),
ble_gattc_cccd_write_complete_cb, NULL);
ble_gattc_cccd_write_complete_cb, reg_arg);
if (rc != 0) {
BLE_HS_LOG(WARN, "Failed to Register for Notification, status = %d", rc);
rc = 0;
BLE_HS_LOG(WARN, "Failed to register for CCCD, status = %d", rc);
return 0;
}
}
} else {
BLE_HS_LOG(WARN, "GATT descriptor discovery failed with status = %d", error->status);
gatt_proc_active = false;
if (cccd_reg_flag) {
nimble_platform_mem_free(cccd_reg_flag);
if (reg_arg) {
nimble_platform_mem_free(reg_arg);
}
}
return rc;
}
int ble_gattc_register_for_notification(uint16_t conn_handle, uint16_t char_val_handle)
static int
ble_gattc_register_for_cccd(uint16_t conn_handle, uint16_t char_val_handle,
uint16_t cccd_value)
{
/* Check if a GATT procedure is already active */
if (gatt_proc_active) {
@@ -5783,26 +5791,42 @@ int ble_gattc_register_for_notification(uint16_t conn_handle, uint16_t char_val_
return BLE_HS_EBUSY;
}
bool *cccd_reg_flag = (bool *)nimble_platform_mem_calloc(1,sizeof(bool));
if (!cccd_reg_flag) {
BLE_HS_LOG(ERROR, "Failed to allocate memory for CCCD Reg Flag.");
struct ble_gattc_cccd_reg_arg *reg_arg =
nimble_platform_mem_calloc(1, sizeof(*reg_arg));
if (!reg_arg) {
BLE_HS_LOG(ERROR, "Failed to allocate memory for CCCD registration.");
return BLE_HS_ENOMEM;
}
*cccd_reg_flag = true;
reg_arg->active = true;
reg_arg->value = cccd_value;
/* Mark that a GATT procedure is now active */
gatt_proc_active = true;
int rc = ble_gattc_disc_all_dscs(conn_handle, char_val_handle, 0xffff,
ble_gattc_cccd_register_cb, cccd_reg_flag);
ble_gattc_cccd_register_cb, reg_arg);
if (rc != 0) {
gatt_proc_active = false;
nimble_platform_mem_free(cccd_reg_flag);
nimble_platform_mem_free(reg_arg);
}
return rc;
}
int
ble_gattc_register_for_notification(uint16_t conn_handle, uint16_t char_val_handle)
{
return ble_gattc_register_for_cccd(conn_handle, char_val_handle,
BLE_GATTS_CLT_CFG_F_NOTIFY);
}
int
ble_gattc_register_for_indication(uint16_t conn_handle, uint16_t char_val_handle)
{
return ble_gattc_register_for_cccd(conn_handle, char_val_handle,
BLE_GATTS_CLT_CFG_F_INDICATE);
}
static int ble_gattc_cccd_unregister_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
void *arg)
@@ -5824,14 +5848,16 @@ static int ble_gattc_cccd_unregister_cb(uint16_t conn_handle, const struct ble_g
/* Disable notification or indication */
uint8_t cccd_val[2] = {0x00, 0x00};
/* write to CCCD to disable notifications or indication */
/* Write to CCCD to disable notifications and indications. */
rc = ble_gattc_write_flat(conn_handle,
dsc->handle,
cccd_val, sizeof(cccd_val),
ble_gattc_cccd_write_complete_cb, NULL);
if (rc != 0) {
BLE_HS_LOG(WARN, "Failed to Unregister for Notification, status = %d", rc);
rc = 0;
BLE_HS_LOG(WARN,
"Failed to unregister for notifications or indications, status = %d",
rc);
return 0;
}
}
} else {
@@ -5846,7 +5872,9 @@ static int ble_gattc_cccd_unregister_cb(uint16_t conn_handle, const struct ble_g
}
int ble_gattc_unregister_for_notification(uint16_t conn_handle, uint16_t char_val_handle)
int
ble_gattc_unregister_notif_indicate(uint16_t conn_handle,
uint16_t char_val_handle)
{
if (gatt_proc_active) {
BLE_HS_LOG(WARN, "Gatt procedure active; cannot start new process");
@@ -5874,6 +5902,12 @@ int ble_gattc_unregister_for_notification(uint16_t conn_handle, uint16_t char_va
return rc;
}
int
ble_gattc_unregister_for_notification(uint16_t conn_handle, uint16_t char_val_handle)
{
return ble_gattc_unregister_notif_indicate(conn_handle, char_val_handle);
}
#endif //MYNEWT_VAL(BLE_STORE_MAX_CCCDS)
#endif //MYNEWT_VAL(BLE_GATTC)