mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-10 16:27:22 +00:00
fix(nimble): Add separate helper functions to register notification/indication
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user