From a5b0c09bdfe35945ba6d6665a94c55239311082d Mon Sep 17 00:00:00 2001 From: Roshan Bangar Date: Wed, 28 Jun 2023 15:14:35 +0530 Subject: [PATCH] added periodic adv feature updates in ble 5.3 --- apps/btshell/src/cmd.c | 6 +- apps/bttester/src/btp_gap.c | 4 +- apps/ext_advertiser/src/main.c | 4 +- nimble/host/include/host/ble_gap.h | 62 ++++++++++++++- nimble/host/src/ble_gap.c | 120 +++++++++++++++++++++++++++-- 5 files changed, 178 insertions(+), 18 deletions(-) diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c index e0fc57acaa..1bdd48e89d 100644 --- a/apps/btshell/src/cmd.c +++ b/apps/btshell/src/cmd.c @@ -1845,7 +1845,7 @@ cmd_set_adv_data_or_scan_rsp(int argc, char **argv, bool scan_rsp, rc = ble_gap_ext_adv_rsp_set_data(instance, adv_data); #if MYNEWT_VAL(BLE_PERIODIC_ADV) } else if (periodic) { - rc = ble_gap_periodic_adv_set_data(instance, adv_data); + rc = ble_gap_periodic_adv_set_data(instance, adv_data, NULL); #endif } else { rc = ble_gap_ext_adv_set_data(instance, adv_data); @@ -3701,7 +3701,7 @@ cmd_periodic_start(int argc, char **argv) return rc; } - rc = ble_gap_periodic_adv_start(instance); + rc = ble_gap_periodic_adv_start(instance, NULL); if (rc) { console_printf("failed to start periodic advertising\n"); return rc; @@ -3924,7 +3924,7 @@ cmd_sync_reporting(int argc, char **argv) return rc; } - rc = ble_gap_periodic_adv_sync_reporting(sync_handle, enable); + rc = ble_gap_periodic_adv_sync_reporting(sync_handle, enable, NULL); if (rc) { console_printf("Failed to %s reporting (%d)\n", enable ? "enable" : "disable", rc); diff --git a/apps/bttester/src/btp_gap.c b/apps/bttester/src/btp_gap.c index 4af463e1bf..0b2239149b 100644 --- a/apps/bttester/src/btp_gap.c +++ b/apps/bttester/src/btp_gap.c @@ -2015,7 +2015,7 @@ periodic_adv_start(const void *cmd, uint16_t cmd_len, return BTP_STATUS_FAILED; } - rc = ble_gap_periodic_adv_start(1); + rc = ble_gap_periodic_adv_start(1, NULL); if (rc) { SYS_LOG_ERR("Failed to start periodic advertiser; rc=%d", rc); return BTP_STATUS_FAILED; @@ -2044,7 +2044,7 @@ periodic_adv_set_data(const void *cmd, uint16_t cmd_len, return BTP_STATUS_FAILED; } - rc = ble_gap_periodic_adv_set_data(1, adv_data); + rc = ble_gap_periodic_adv_set_data(1, adv_data, NULL); if (rc) { SYS_LOG_ERR("Failed to set periodic advertiser data; rc=%d", rc); return BTP_STATUS_FAILED; diff --git a/apps/ext_advertiser/src/main.c b/apps/ext_advertiser/src/main.c index ca450b1441..13c8955834 100644 --- a/apps/ext_advertiser/src/main.c +++ b/apps/ext_advertiser/src/main.c @@ -475,11 +475,11 @@ static void start_periodic(void) rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); - rc = ble_gap_periodic_adv_set_data(instance, data); + rc = ble_gap_periodic_adv_set_data(instance, data, NULL); assert (rc == 0); /* start periodic advertising */ - rc = ble_gap_periodic_adv_start(instance); + rc = ble_gap_periodic_adv_start(instance, NULL); assert (rc == 0); /* start advertising */ diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index af0defa9fc..fd70b94afb 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -1713,6 +1713,30 @@ struct ble_gap_periodic_adv_params { uint16_t itvl_max; }; +/** @brief Periodic advertising enable parameters */ +struct ble_gap_periodic_adv_start_params { +#if MYNEWT_VAL(BLE_VERSION) >= 53 + /** If include adi in aux_sync_ind PDU */ + unsigned int include_adi : 1; +#endif +}; + +/** @brief Periodic advertising sync reporting parameters */ +struct ble_gap_periodic_adv_sync_reporting_params { +#if MYNEWT_VAL(BLE_VERSION) >= 53 + /** If filter duplicates */ + unsigned int filter_duplicates : 1; +#endif +}; + +/** @brief Periodic adv set data parameters */ +struct ble_gap_periodic_adv_set_data_params { +#if MYNEWT_VAL(BLE_VERSION) >= 53 + /** If include adi in aux_sync_ind PDU */ + unsigned int update_did : 1; +#endif +}; + /** @brief Periodic sync parameters */ struct ble_gap_periodic_sync_params { /** The maximum number of periodic advertising events that controller can @@ -1725,7 +1749,13 @@ struct ble_gap_periodic_sync_params { uint16_t sync_timeout; /** If reports should be initially disabled when sync is created */ - unsigned int reports_disabled:1; + unsigned int reports_disabled : 1; + +#if MYNEWT_VAL(BLE_VERSION) >= 53 + /** If duplicate filtering should be should be initially enabled when sync is + created */ + unsigned int filter_duplicates : 1; +#endif }; /** @@ -1747,10 +1777,15 @@ int ble_gap_periodic_adv_configure(uint8_t instance, * Start periodic advertising for specified advertising instance. * * @param instance Instance ID + * @param params Additional arguments specifying the particulars + * of periodic advertising. * * @return 0 on success, error code on failure. */ -int ble_gap_periodic_adv_start(uint8_t instance); +int +ble_gap_periodic_adv_start(uint8_t instance, + const struct ble_gap_periodic_adv_start_params *params); + /** * Stop periodic advertising for specified advertising instance. @@ -1767,10 +1802,14 @@ int ble_gap_periodic_adv_stop(uint8_t instance); * * @param instance Instance ID * @param data Chain containing the periodic advertising data. + * @param params Additional arguments specifying the particulars + of periodic advertising data. * * @return 0 on success or error code on failure. */ -int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data); +int ble_gap_periodic_adv_set_data(uint8_t instance, + struct os_mbuf *data, + const struct ble_gap_periodic_adv_set_data_params *params); /** * Performs the Synchronization procedure with periodic advertiser. @@ -1814,10 +1853,14 @@ int ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle); * * @param sync_handle Handle identifying synchronization. * @param enable If reports should be enabled. + * @param params Additional arguments specifying the particulars + * of periodic reports. * * @return 0 on success; nonzero on failure. */ -int ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable); +int ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, + bool enable, + const struct ble_gap_periodic_adv_sync_reporting_params *params); /** * Initialize sync transfer procedure for specified handles. @@ -1849,6 +1892,17 @@ int ble_gap_periodic_adv_sync_set_info(uint8_t instance, uint16_t conn_handle, uint16_t service_data); +/** + * Set the default periodic sync transfer params. + * + * + * @param conn_handle Handle identifying connection. + * @param params Default Parameters for periodic sync transfer. + * + * @return 0 on success; nonzero on failure. + */ +int periodic_adv_set_default_sync_params(const struct ble_gap_periodic_sync_params *params); + /** * Enables or disables sync transfer reception on specified connection. * When sync transfer arrives, BLE_GAP_EVENT_PERIODIC_TRANSFER is sent to the user. diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 807796dd52..015a70d877 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -41,6 +41,8 @@ #define bssnz_t #endif +#define SET_BIT(t, n) (t |= 1UL << (n)) + /** * GAP - Generic Access Profile. * @@ -3668,7 +3670,7 @@ ble_gap_periodic_adv_configure(uint8_t instance, } int -ble_gap_periodic_adv_start(uint8_t instance) +ble_gap_periodic_adv_start(uint8_t instance, const struct ble_gap_periodic_adv_start_params *params) { struct ble_hci_le_set_periodic_adv_enable_cp cmd; uint16_t opcode; @@ -3693,6 +3695,12 @@ ble_gap_periodic_adv_start(uint8_t instance) opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE); cmd.enable = 0x01; + +#if MYNEWT_VAL(BLE_VERSION) >= 53 + if (params && params->include_adi) { + SET_BIT(cmd.enable, 1); + } +#endif cmd.adv_handle = instance; rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); @@ -3707,6 +3715,27 @@ ble_gap_periodic_adv_start(uint8_t instance) return 0; } +#if MYNEWT_VAL(BLE_VERSION) >= 53 +static int +ble_gap_periodic_adv_update_did(uint8_t instance) +{ + static uint8_t buf[sizeof(struct ble_hci_le_set_periodic_adv_data_cp)]; + struct ble_hci_le_set_periodic_adv_data_cp *cmd = (void *) buf; + uint16_t opcode; + + memset(buf, 0, sizeof(buf)); + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA); + + cmd->adv_handle = instance; + cmd->operation = BLE_HCI_LE_SET_DATA_OPER_UNCHANGED; + cmd->adv_data_len = 0; + + return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len, + NULL, 0); +} +#endif + static int ble_gap_periodic_adv_set(uint8_t instance, struct os_mbuf **data) { @@ -3835,7 +3864,9 @@ ble_gap_periodic_adv_set_data_validate(uint8_t instance, } int -ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data) +ble_gap_periodic_adv_set_data(uint8_t instance, + struct os_mbuf *data, + const struct ble_gap_periodic_adv_set_data_params *params) { int rc; if (instance >= BLE_ADV_INSTANCES) { @@ -3848,6 +3879,14 @@ ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data) goto done; } +#if MYNEWT_VAL(BLE_VERSION) >= 53 + /* update_did and data cannot be set at the same time */ + if (params && params->update_did && data) { + rc = BLE_HS_EINVAL; + goto done; + } +#endif + ble_hs_lock(); rc = ble_gap_periodic_adv_set_data_validate(instance, data); @@ -3856,7 +3895,15 @@ ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data) goto done; } +#if MYNEWT_VAL(BLE_VERSION) >= 53 + if (params && params->update_did) { + rc = ble_gap_periodic_adv_update_did(instance); + } else { + rc = ble_gap_periodic_adv_set(instance, &data); + } +#else rc = ble_gap_periodic_adv_set(instance, &data); +#endif ble_hs_unlock(); @@ -3993,6 +4040,15 @@ ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid, memcpy(cmd.peer_addr, BLE_ADDR_ANY->val, BLE_DEV_ADDR_LEN); } +#if MYNEWT_VAL(BLE_VERSION) >= 53 + /* LE Periodic Advertising Create Sync command */ + if (params->reports_disabled) { + SET_BIT(cmd.options, 1); + } + if (params->filter_duplicates) { + SET_BIT(cmd.options, 2); + } +#endif cmd.sid = adv_sid; cmd.skip = params->skip; cmd.sync_timeout = htole16(params->sync_timeout); @@ -4090,8 +4146,11 @@ ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle) return rc; } #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) +/* LE Set Periodic Advertising Receive Enable command */ int -ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable) +ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, + bool enable, + const struct ble_gap_periodic_adv_sync_reporting_params *params) { struct ble_hci_le_periodic_adv_receive_enable_cp cmd; struct ble_hs_periodic_sync *psync; @@ -4119,6 +4178,11 @@ ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable) cmd.sync_handle = htole16(sync_handle); cmd.enable = enable ? 0x01 : 0x00; +#if MYNEWT_VAL(BLE_VERSION) >= 53 + if (params && params->filter_duplicates) { + SET_BIT(cmd.enable, 1); + } +#endif rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); @@ -4230,11 +4294,22 @@ periodic_adv_transfer_enable(uint16_t conn_handle, opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS); + memset(&cmd, 0, sizeof(cmd)); cmd.conn_handle = htole16(conn_handle); - cmd.sync_cte_type = 0x00; - cmd.mode = params->reports_disabled ? 0x01 : 0x02; - cmd.skip = htole16(params->skip); - cmd.sync_timeout = htole16(params->sync_timeout); + + if (params != NULL) { + cmd.sync_cte_type = 0x00; + cmd.mode = params->reports_disabled ? 0x01 : 0x02; + +#if MYNEWT_VAL(BLE_VERSION) >= 53 + if (!params->reports_disabled && params->filter_duplicates) { + cmd.mode = 0x03; + } +#endif + + cmd.skip = htole16(params->skip); + cmd.sync_timeout = htole16(params->sync_timeout); + } rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (!rc) { @@ -4244,6 +4319,37 @@ periodic_adv_transfer_enable(uint16_t conn_handle, return rc; } +int +periodic_adv_set_default_sync_params(const struct ble_gap_periodic_sync_params *params) +{ + struct ble_hci_le_set_default_periodic_sync_transfer_params_cp cmd; + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DEFAULT_SYNC_TRANSFER_PARAMS); + + memset(&cmd, 0, sizeof(cmd)); + + if (params != NULL) { + cmd.sync_cte_type = 0x00; + cmd.mode = params->reports_disabled ? 0x01 : 0x02; + +#if MYNEWT_VAL(BLE_VERSION) >= 53 + if (!params->reports_disabled && params->filter_duplicates) { + cmd.mode = 0x03; + } +#endif + + cmd.skip = htole16(params->skip); + cmd.sync_timeout = htole16(params->sync_timeout); + } + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); +} + int ble_gap_periodic_adv_sync_receive(uint16_t conn_handle, const struct ble_gap_periodic_sync_params *params,