From 2e1ba1c8c617f48b713dd7aa31f4e2505a03c77e Mon Sep 17 00:00:00 2001 From: h2zero Date: Mon, 10 Jun 2024 14:59:03 -0600 Subject: [PATCH] Update nimble core to esp-nimble commit #e3cbdc0 * Commit #3fa3334 support hci log for nimble removed --- .../esp_port/port/include/esp_nimble_cfg.h | 4 + .../nimble/host/include/host/ble_esp_gap.h | 22 ++ src/nimble/nimble/host/include/host/ble_gap.h | 27 +- .../nimble/host/include/host/ble_gatt.h | 17 +- .../nimble/host/include/host/ble_hs_pvcy.h | 1 + .../nimble/host/include/host/ble_store.h | 1 + .../gatt/include/services/gatt/ble_svc_gatt.h | 8 +- src/nimble/nimble/host/src/ble_att.c | 1 + src/nimble/nimble/host/src/ble_att_clt.c | 46 ++- src/nimble/nimble/host/src/ble_att_priv.h | 3 +- src/nimble/nimble/host/src/ble_att_svr.c | 27 +- src/nimble/nimble/host/src/ble_gap.c | 353 +++++++++++++----- src/nimble/nimble/host/src/ble_gap_priv.h | 2 + src/nimble/nimble/host/src/ble_gatt_priv.h | 2 +- src/nimble/nimble/host/src/ble_gattc.c | 144 ++++++- src/nimble/nimble/host/src/ble_gatts.c | 9 +- src/nimble/nimble/host/src/ble_hs_conn.c | 111 +++--- src/nimble/nimble/host/src/ble_hs_hci_evt.c | 124 +++--- src/nimble/nimble/host/src/ble_hs_pvcy.c | 29 +- .../nimble/host/src/ble_hs_resolv_priv.h | 1 + src/nimble/nimble/host/src/ble_sm_priv.h | 1 - .../host/store/config/src/ble_store_config.c | 126 ++++++- .../store/config/src/ble_store_config_priv.h | 4 + .../host/store/config/src/ble_store_nvs.c | 31 ++ src/nimble/nimble/include/nimble/hci_common.h | 5 + .../nimble/include/nimble/nimble_opt_auto.h | 4 + .../porting/nimble/include/syscfg/syscfg.h | 4 + src/nimble/porting/nimble/src/nimble_port.c | 21 +- .../npl/freertos/src/npl_os_freertos.c | 4 +- 29 files changed, 843 insertions(+), 289 deletions(-) diff --git a/src/nimble/esp_port/port/include/esp_nimble_cfg.h b/src/nimble/esp_port/port/include/esp_nimble_cfg.h index 3b4ca098..e4198010 100644 --- a/src/nimble/esp_port/port/include/esp_nimble_cfg.h +++ b/src/nimble/esp_port/port/include/esp_nimble_cfg.h @@ -420,6 +420,10 @@ #define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif +#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR +#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ_UUID #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/src/nimble/nimble/host/include/host/ble_esp_gap.h b/src/nimble/nimble/host/include/host/ble_esp_gap.h index e0977f48..10fd59b3 100644 --- a/src/nimble/nimble/host/include/host/ble_esp_gap.h +++ b/src/nimble/nimble/host/include/host/ble_esp_gap.h @@ -112,6 +112,28 @@ int ble_gap_wl_read_size(uint8_t *size); */ int ble_gap_host_check_status(void); +/** + * This API is called to get local used address and address type. + * + * @param addr On success, locally used address will be stored here. + * + * @return 0 on success; nonzero on failure. +*/ +int ble_gap_get_local_used_addr(ble_addr_t *addr); + +/** + * This API is called to get ADV data for a specific type. + + * + * @param adv_data Pointer of ADV data (unsigned 8 bit integer) which to be resolved. + * @param adv_type Finding ADV data type. + * @param adv_data_len Total length of Advertising data. + * @param length Return the length of ADV data not including type. + * + * @return Pointer (unsigned 8 bit integer) of type specific ADV data. + */ +uint8_t* ble_resolve_adv_data(const uint8_t *adv_data, uint8_t adv_type, uint8_t adv_data_len , uint8_t * length); + #if MYNEWT_VAL(BLE_HCI_VS) #if MYNEWT_VAL(BLE_POWER_CONTROL) diff --git a/src/nimble/nimble/host/include/host/ble_gap.h b/src/nimble/nimble/host/include/host/ble_gap.h index 7731fbcd..8af8c949 100644 --- a/src/nimble/nimble/host/include/host/ble_gap.h +++ b/src/nimble/nimble/host/include/host/ble_gap.h @@ -158,7 +158,7 @@ struct hci_conn_update; #define BLE_GAP_EVENT_REATTEMPT_COUNT 29 #define BLE_GAP_EVENT_AUTHORIZE 30 #define BLE_GAP_EVENT_TEST_UPDATE 31 - +#define BLE_GAP_EVENT_DATA_LEN_CHG 32 /* DTM events */ #define BLE_GAP_DTM_TX_START_EVT 0 @@ -1174,8 +1174,31 @@ struct ble_gap_event { * Valid only for BLE_GAP_DTM_END_EVT * shall be 0 for a transmitter. */ - uint8_t num_pkt; + uint16_t num_pkt; } dtm_state; + + /** + * Represent an event for LE Data length change + * + * Valid for the following event types: + * o BLE_GAP_EVENT_DATA_LEN_CHG + */ + struct { + /* Connection handle */ + uint16_t conn_handle; + + /* Max Tx Payload octotes */ + uint16_t max_tx_octets; + + /* Max Tx Time */ + uint16_t max_tx_time; + + /* Max Rx payload octet */ + uint16_t max_rx_octets; + + /* Max Rx Time */ + uint16_t max_rx_time; + } data_len_chg; }; }; diff --git a/src/nimble/nimble/host/include/host/ble_gatt.h b/src/nimble/nimble/host/include/host/ble_gatt.h index 56ff604d..99c52f00 100644 --- a/src/nimble/nimble/host/include/host/ble_gatt.h +++ b/src/nimble/nimble/host/include/host/ble_gatt.h @@ -329,6 +329,17 @@ typedef int ble_gatt_attr_fn(uint16_t conn_handle, struct ble_gatt_attr *attr, void *arg); +/** + * The host will free the attribute mbuf automatically after the callback is + * executed. The application can take ownership of the mbuf and prevent it + * from being freed by assigning NULL to attr->om. + */ +typedef int ble_gatt_attr_mult_fn(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attrs, + uint8_t num_attrs, + void *arg); + /** * The host will free the attribute mbufs automatically after the callback is * executed. The application can take ownership of the mbufs and prevent them @@ -545,6 +556,10 @@ int ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, uint8_t num_handles, ble_gatt_attr_fn *cb, void *cb_arg); +int ble_gattc_read_mult_var(uint16_t conn_handle, const uint16_t *handles, + uint8_t num_handles, ble_gatt_attr_mult_fn *cb, + void *cb_arg); + /** * Initiates GATT procedure: Write Without Response. This function consumes * the supplied mbuf regardless of the outcome. @@ -882,7 +897,7 @@ struct ble_gatt_cpfd { uint16_t unit; /** The name space of the description. */ - uint8_t namespace_; + uint8_t name_space; /** The description of this characteristic. Depends on name space. */ uint16_t description; diff --git a/src/nimble/nimble/host/include/host/ble_hs_pvcy.h b/src/nimble/nimble/host/include/host/ble_hs_pvcy.h index 0943524a..5c54d94d 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_pvcy.h +++ b/src/nimble/nimble/host/include/host/ble_hs_pvcy.h @@ -69,6 +69,7 @@ void ble_hs_resolv_deinit(void); #endif int ble_hs_pvcy_set_resolve_enabled(int enable); +void ble_hs_set_rpa_timeout(uint16_t timeout); #ifdef __cplusplus } diff --git a/src/nimble/nimble/host/include/host/ble_store.h b/src/nimble/nimble/host/include/host/ble_store.h index aa1fb8d5..325dbb3e 100644 --- a/src/nimble/nimble/host/include/host/ble_store.h +++ b/src/nimble/nimble/host/include/host/ble_store.h @@ -77,6 +77,7 @@ struct ble_store_key_sec { */ struct ble_store_value_sec { ble_addr_t peer_addr; + uint16_t bond_count; uint8_t key_size; uint16_t ediv; diff --git a/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h b/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h index f936bdae..d2e85eb4 100644 --- a/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h +++ b/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h @@ -36,10 +36,10 @@ struct ble_hs_cfg; #if MYNEWT_VAL(BLE_GATT_CACHING) #define BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16 0x2b2a -uint16_t ble_svc_gatt_changed_handle(); -uint16_t ble_svc_gatt_hash_handle(); -uint16_t ble_svc_gatt_csf_handle(); -uint8_t ble_svc_gatt_get_csfs(); +uint16_t ble_svc_gatt_changed_handle(void); +uint16_t ble_svc_gatt_hash_handle(void); +uint16_t ble_svc_gatt_csf_handle(void); +uint8_t ble_svc_gatt_get_csfs(void); #endif uint8_t ble_svc_gatt_get_local_cl_supported_feat(void); diff --git a/src/nimble/nimble/host/src/ble_att.c b/src/nimble/nimble/host/src/ble_att.c index 97271b68..ffe4c324 100644 --- a/src/nimble/nimble/host/src/ble_att.c +++ b/src/nimble/nimble/host/src/ble_att.c @@ -70,6 +70,7 @@ static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = { { BLE_ATT_OP_INDICATE_REQ, ble_att_svr_rx_indicate }, { BLE_ATT_OP_INDICATE_RSP, ble_att_clt_rx_indicate }, { BLE_ATT_OP_READ_MULT_VAR_REQ, ble_att_svr_rx_read_mult_var }, + { BLE_ATT_OP_READ_MULT_VAR_RSP, ble_att_clt_rx_read_mult_var }, { BLE_ATT_OP_WRITE_CMD, ble_att_svr_rx_write_no_rsp }, #ifdef ESP_PLATFORM { BLE_ATT_OP_SIGNED_WRITE_CMD, ble_att_svr_rx_signed_write }, diff --git a/src/nimble/nimble/host/src/ble_att_clt.c b/src/nimble/nimble/host/src/ble_att_clt.c index 9232f4af..89078078 100644 --- a/src/nimble/nimble/host/src/ble_att_clt.c +++ b/src/nimble/nimble/host/src/ble_att_clt.c @@ -537,7 +537,7 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, - int num_handles) + int num_handles, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; @@ -546,12 +546,15 @@ ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, struct ble_att_read_mult_req *req; struct os_mbuf *txom; int i; + uint8_t op; if (num_handles < 1) { return BLE_HS_EINVAL; } - req = ble_att_cmd_get(BLE_ATT_OP_READ_MULT_REQ, + op = variable ? BLE_ATT_OP_READ_MULT_VAR_REQ : BLE_ATT_OP_READ_MULT_REQ; + + req = ble_att_cmd_get(op, sizeof(req->handles[0]) * num_handles, &txom); if (req == NULL) { @@ -573,7 +576,19 @@ ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, false); + return 0; +} + +int +ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) +{ +#if !NIMBLE_BLE_ATT_CLT_READ_MULT_VAR + return BLE_HS_ENOTSUP; +#endif + + /* Pass the Attribute Value field to GATT. */ + ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, true); return 0; } @@ -765,6 +780,7 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * struct os_mbuf *txom2; uint8_t cmac[16]; uint8_t *message = NULL; + uint8_t len; int rc; int i; @@ -781,27 +797,37 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * } cmd->handle = htole16(handle); - /* Message to be signed is message||sign_counter, + /* Message to be signed is opcode||handle||message||sign_counter, * where || represents concatenation */ - message = nimble_platform_mem_malloc(OS_MBUF_PKTLEN(txom) + sizeof(counter)); - rc = os_mbuf_copydata(txom, 0, OS_MBUF_PKTLEN(txom), message); + len = BLE_ATT_SIGNED_WRITE_DATA_OFFSET + OS_MBUF_PKTLEN(txom) + sizeof(counter); + message = nimble_platform_mem_malloc(len); + + /** Copying opcode and handle */ + rc = os_mbuf_copydata(txom2, 0, BLE_ATT_SIGNED_WRITE_DATA_OFFSET, message); + if (rc != 0) { + goto err; + } + + /** Copying message */ + rc = os_mbuf_copydata(txom, 0, OS_MBUF_PKTLEN(txom), &message[BLE_ATT_SIGNED_WRITE_DATA_OFFSET]); if (rc != 0) { goto err; } - memcpy(&message[OS_MBUF_PKTLEN(txom)], &counter, sizeof(counter)); + /** Copying sign counter */ + memcpy(&message[BLE_ATT_SIGNED_WRITE_DATA_OFFSET + OS_MBUF_PKTLEN(txom)], &counter, sizeof(counter)); + /* ble_sm_alg_aes_cmac takes data in little-endian format, * so converting it to LE. */ - swap_in_place(message, OS_MBUF_PKTLEN(txom) + sizeof(counter)); + swap_in_place(message, len); /* Getting the CMAC (Cipher-based Message Authentication Code) * for the message using our CSRK for this connection. */ memset(cmac, 0, sizeof cmac); - rc = ble_sm_alg_aes_cmac(csrk, message, - OS_MBUF_PKTLEN(txom) + sizeof(counter), cmac); + rc = ble_sm_alg_aes_cmac(csrk, message, len, cmac); if (rc != 0) { goto err; } diff --git a/src/nimble/nimble/host/src/ble_att_priv.h b/src/nimble/nimble/host/src/ble_att_priv.h index 76660f51..3b58d56c 100644 --- a/src/nimble/nimble/host/src/ble_att_priv.h +++ b/src/nimble/nimble/host/src/ble_att_priv.h @@ -275,8 +275,9 @@ int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset); int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); int ble_att_clt_tx_read_mult(uint16_t conn_handle, - const uint16_t *handles, int num_handles); + const uint16_t *handles, int num_handles, bool variable); int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom); int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid); int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); diff --git a/src/nimble/nimble/host/src/ble_att_svr.c b/src/nimble/nimble/host/src/ble_att_svr.c index da04370d..c35c966e 100644 --- a/src/nimble/nimble/host/src/ble_att_svr.c +++ b/src/nimble/nimble/host/src/ble_att_svr.c @@ -1852,7 +1852,7 @@ ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) { -#if (!MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) || (MYNEWT_VAL(BLE_VERSION) < 52)) +#if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) return BLE_HS_ENOTSUP; #endif @@ -2358,7 +2358,9 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) uint16_t handle; uint8_t sign[12]; uint8_t cmac[16]; + uint8_t csrk[16]; uint8_t *message = NULL; + uint16_t len; int rc; rc = ble_gap_conn_find(conn_handle, &desc); @@ -2388,9 +2390,6 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) handle = le16toh(req->handle); - /* Strip the request base from the front of the mbuf. */ - os_mbuf_adj(*rxom, sizeof(*req)); - os_mbuf_copydata(*rxom, OS_MBUF_PKTLEN(*rxom) - (BLE_ATT_SIGNED_WRITE_CMD_BASE_SZ - BLE_ATT_SIGNED_WRITE_DATA_OFFSET), BLE_ATT_SIGNED_WRITE_CMD_BASE_SZ - BLE_ATT_SIGNED_WRITE_DATA_OFFSET, @@ -2400,16 +2399,22 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) os_mbuf_adj(*rxom, -(BLE_ATT_SIGNED_WRITE_CMD_BASE_SZ - BLE_ATT_SIGNED_WRITE_DATA_OFFSET)); /* Authentication procedure */ - message = nimble_platform_mem_malloc(OS_MBUF_PKTLEN(*rxom) + sizeof(value_sec.sign_counter)); - os_mbuf_copydata(*rxom, 0, OS_MBUF_PKTLEN(*rxom), message); - memcpy(&message[OS_MBUF_PKTLEN(*rxom)], &value_sec.sign_counter, sizeof(value_sec.sign_counter)); + len = OS_MBUF_PKTLEN(*rxom) + sizeof(value_sec.sign_counter) + 1; + message = nimble_platform_mem_malloc(len); + + message[0] = BLE_ATT_OP_SIGNED_WRITE_CMD; + os_mbuf_copydata(*rxom, 0, OS_MBUF_PKTLEN(*rxom), &message[1]); + memcpy(&message[1 + OS_MBUF_PKTLEN(*rxom)], &value_sec.sign_counter, sizeof(value_sec.sign_counter)); /* Converting message into little endian format */ - swap_in_place(message, OS_MBUF_PKTLEN(*rxom) + sizeof(value_sec.sign_counter)); + swap_in_place(message, len); + + /* Converting CSRK into little endian format */ + swap_buf(csrk, value_sec.csrk, 16); /* Using AES-CMAC to get the CMAC from the message and CSRK of this device */ memset(cmac, 0, sizeof cmac); - rc = ble_sm_alg_aes_cmac(value_sec.csrk, message, OS_MBUF_PKTLEN(*rxom) + sizeof(value_sec.sign_counter), cmac); + rc = ble_sm_alg_aes_cmac(csrk, message, len, cmac); if (rc != 0) { goto err; } @@ -2435,6 +2440,9 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) goto err; } + /* Strip the request base from the front of the mbuf. */ + os_mbuf_adj(*rxom, sizeof(*req)); + rc = ble_att_svr_write_handle(conn_handle, handle, 0, rxom, &att_err); if (rc != 0) { goto err; @@ -2444,7 +2452,6 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) return 0; err: if(message != NULL) nimble_platform_mem_free(message); - ble_gap_terminate(conn_handle, BLE_ERR_AUTH_FAIL); return rc; } #endif diff --git a/src/nimble/nimble/host/src/ble_gap.c b/src/nimble/nimble/host/src/ble_gap.c index a0714819..f4fd5eb9 100644 --- a/src/nimble/nimble/host/src/ble_gap.c +++ b/src/nimble/nimble/host/src/ble_gap.c @@ -134,13 +134,31 @@ struct ble_gap_connect_reattempt_ctxt { struct ble_gap_conn_params conn_params; ble_gap_event_fn *cb; void *cb_arg; -}; +}ble_conn_reattempt; -static struct ble_gap_connect_reattempt_ctxt ble_conn_reattempt[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; -#if MYNEWT_VAL(BLE_ROLE_CENTRAL) -static uint16_t reattempt_idx; +struct ble_gap_adv_reattempt_ctxt { + uint8_t type; + + struct ble_hs_adv_fields fields; + uint8_t own_addr_type; + ble_addr_t direct_addr; + uint8_t direct_addr_present:1 ; + int32_t duration_ms; + struct ble_gap_adv_params adv_params; + +#if MYNEWT_VAL(BLE_EXT_ADV) + uint8_t instance; + struct ble_gap_ext_adv_params params; + int8_t selected_tx_power; + uint8_t selected_tx_power_present:1; + struct os_mbuf *data; + int duration; + int max_events; #endif -static bool conn_cookie_enabled; + + ble_gap_event_fn *cb; + void *cb_arg; +}ble_adv_reattempt; #endif @@ -764,6 +782,44 @@ ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask, #endif } +int ble_gap_get_local_used_addr(ble_addr_t *addr) +{ + uint8_t own_addr_type = 0; + const uint8_t *out_id_addr; + int rc; + + if (addr == NULL) { + return BLE_HS_EINVAL; + } + + own_addr_type = ble_gap_slave[0].our_addr_type; + + rc = ble_hs_id_addr(own_addr_type, &out_id_addr,NULL); + + if (rc == 0) { + addr->type = own_addr_type; + memcpy(addr->val, out_id_addr, BLE_DEV_ADDR_LEN); + } + + return rc; +} + +uint8_t* ble_resolve_adv_data(const uint8_t *adv_data, uint8_t adv_type, uint8_t adv_data_len , uint8_t * length) +{ + int rc = 0; + const struct ble_hs_adv_field *fields; + const uint8_t *data; + + rc = ble_hs_adv_find_field(adv_type, adv_data, adv_data_len, &fields); /*Fill adv field*/ + + if (rc == 0) { + *length = fields->length -1 ; /* minus length of type*/ + data = fields->value; /* Type specific adv data*/ + return (uint8_t*)data; + } + + return NULL; +} /***************************************************************************** * $misc * *****************************************************************************/ @@ -981,27 +1037,12 @@ ble_gap_master_connect_cancelled(void) static void ble_gap_update_notify(uint16_t conn_handle, int status); -static int -ble_gap_find_retry_conn_param(const struct ble_gap_conn_desc *conn_desc) -{ - int i; - - for(i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { - if (ble_conn_reattempt[i].peer_addr_present == 1 && memcmp(&ble_conn_reattempt[i].peer_addr, &conn_desc->peer_ota_addr, sizeof(ble_addr_t)) == 0) { - return i; - } - } - /* No matching entry found. Return invalid index */ - return MYNEWT_VAL(BLE_MAX_CONNECTIONS); -} - int ble_gap_master_connect_reattempt(uint16_t conn_handle) { struct ble_gap_snapshot snap; struct ble_gap_conn_desc conn; struct ble_gap_update_entry *entry; - int idx; int rc = BLE_HS_EUNKNOWN; snap.desc = &conn; @@ -1011,14 +1052,6 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) } if (conn.role == BLE_GAP_ROLE_MASTER) { - idx = ble_gap_find_retry_conn_param(&conn); - if (idx >= MYNEWT_VAL(BLE_MAX_CONNECTIONS)) { - return BLE_HS_EINVAL; - } - - /* XXX Connection state in host needs to be removed and cleaned - * up to validate the connection when re-attempting. */ - /* If there was a connection update in progress, indicate to the * application that it did not complete. */ @@ -1042,14 +1075,11 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) return rc; } - /* Utilize cookie to get the index updated correctly for re-attempt */ - conn_cookie_enabled = true; - - rc = ble_gap_connect(ble_conn_reattempt[idx].own_addr_type, - (ble_conn_reattempt[idx].peer_addr_present == 1 ? &ble_conn_reattempt[idx].peer_addr : NULL), - ble_conn_reattempt[idx].duration_ms, - &ble_conn_reattempt[idx].conn_params, - ble_conn_reattempt[idx].cb, + rc = ble_gap_connect(ble_conn_reattempt.own_addr_type, + (ble_conn_reattempt.peer_addr_present == 1 ? &ble_conn_reattempt.peer_addr : NULL), + ble_conn_reattempt.duration_ms, + &ble_conn_reattempt.conn_params, + ble_conn_reattempt.cb, &conn); if (rc != 0) { return rc; @@ -1071,8 +1101,63 @@ void ble_gap_reattempt_count(uint16_t conn_handle, uint8_t count) event.reattempt_cnt.count = count; event.reattempt_cnt.conn_handle = le16toh(conn_handle); + ble_gap_event_listener_call(&event); ble_gap_call_conn_event_cb(&event, handle); } + +int ble_gap_slave_adv_reattempt(void) +{ + int rc = 0; + + switch (ble_adv_reattempt.type) { + case 0: + ble_gap_adv_stop(); + + rc = ble_gap_adv_set_fields(&ble_adv_reattempt.fields); + if (rc != 0) { + return rc; + } + + rc = ble_gap_adv_start(ble_adv_reattempt.own_addr_type, + (ble_adv_reattempt.direct_addr_present == 1 ? &ble_adv_reattempt.direct_addr: NULL), + ble_adv_reattempt.duration_ms, &ble_adv_reattempt.adv_params, + ble_adv_reattempt.cb, ble_adv_reattempt.cb_arg); + if (rc != 0) { + return rc; + } + break; + + case 1: +#if MYNEWT_VAL(BLE_EXT_ADV) + ble_gap_ext_adv_stop(ble_adv_reattempt.instance); + + rc = ble_gap_ext_adv_configure(ble_adv_reattempt.instance, &ble_adv_reattempt.params, + (ble_adv_reattempt.selected_tx_power_present == 1 ? &ble_adv_reattempt.selected_tx_power : NULL), + ble_adv_reattempt.cb, ble_adv_reattempt.cb_arg); + if (rc != 0) { + return rc; + } + + rc = ble_gap_ext_adv_set_data(ble_adv_reattempt.instance, ble_adv_reattempt.data); + + if (rc != 0) { + return rc; + } + + rc = ble_gap_ext_adv_start(ble_adv_reattempt.instance, ble_adv_reattempt.duration, + ble_adv_reattempt.max_events); + if (rc != 0) + return rc; +#endif + break; + + default: + break; + } + + return rc; + +} #endif #endif @@ -1695,6 +1780,18 @@ ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminate ble_gap_adv_finished(ev->adv_handle, reason, conn_handle, ev->num_events); } +static void +ble_gap_slave_get_cb(uint8_t instance, + ble_gap_event_fn **out_cb, void **out_cb_arg) +{ + ble_hs_lock(); + + *out_cb = ble_gap_slave[instance].cb; + *out_cb_arg = ble_gap_slave[instance].cb_arg; + + ble_hs_unlock(); +} + void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev) { @@ -1702,7 +1799,7 @@ ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev) ble_gap_event_fn *cb; void *cb_arg; - ble_gap_slave_extract_cb(ev->adv_handle, &cb, &cb_arg); + ble_gap_slave_get_cb(ev->adv_handle, &cb, &cb_arg); if (cb != NULL) { memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_SCAN_REQ_RCVD; @@ -2236,6 +2333,25 @@ ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_compl #endif } +void +ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev) +{ +#if NIMBLE_BLE_CONNECT + struct ble_gap_event event; + uint16_t conn_handle = le16toh(ev->conn_handle); + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_DATA_LEN_CHG; + event.data_len_chg.max_tx_octets = le16toh(ev->max_tx_octets); + event.data_len_chg.max_rx_octets = le16toh(ev->max_rx_octets); + event.data_len_chg.max_tx_time = le16toh(ev->max_tx_time); + event.data_len_chg.max_rx_time = le16toh(ev->max_rx_time); + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} + static int32_t ble_gap_master_timer(void) { @@ -2831,6 +2947,23 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr, return BLE_HS_EDISABLED; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + ble_adv_reattempt.type = 0; + ble_adv_reattempt.own_addr_type = own_addr_type; + + if (direct_addr) { + memcpy(&ble_adv_reattempt.direct_addr, direct_addr, sizeof(ble_addr_t)); + ble_adv_reattempt.direct_addr_present = 1; + } else { + ble_adv_reattempt.direct_addr_present = 0; + } + + ble_adv_reattempt.duration_ms = duration_ms; + memcpy(&ble_adv_reattempt.adv_params , adv_params, sizeof(struct ble_gap_adv_params)); + ble_adv_reattempt.cb = cb; + ble_adv_reattempt.cb_arg = cb_arg; +#endif + ble_hs_lock(); rc = ble_gap_adv_validate(own_addr_type, direct_addr, adv_params); @@ -2971,6 +3104,9 @@ ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields) if (!ble_hs_is_enabled()) { return BLE_HS_EDISABLED; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + memcpy(&ble_adv_reattempt.fields, adv_fields, sizeof( struct ble_hs_adv_fields)); +#endif rc = ble_hs_adv_set_fields(adv_fields, buf, &buf_sz, sizeof buf); if (rc != 0) { @@ -3203,6 +3339,23 @@ ble_gap_ext_adv_configure(uint8_t instance, return rc; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + ble_adv_reattempt.instance = instance; + + memcpy(&ble_adv_reattempt.params, params, sizeof(struct ble_gap_ext_adv_params)); + + if (selected_tx_power) { + ble_adv_reattempt.selected_tx_power = *selected_tx_power; + ble_adv_reattempt.selected_tx_power_present = 1 ; + } else { + ble_adv_reattempt.selected_tx_power_present = 0 ; + } + + ble_adv_reattempt.cb = cb; + + ble_adv_reattempt.cb_arg = cb_arg; +#endif + ble_hs_lock(); if (ble_gap_adv_active_instance(instance)) { @@ -3320,6 +3473,13 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events) return BLE_HS_EDISABLED; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + ble_adv_reattempt.type = 1; + ble_adv_reattempt.instance = instance; + ble_adv_reattempt.duration = duration; + ble_adv_reattempt.max_events = max_events; +#endif + ble_hs_lock(); if (!ble_gap_slave[instance].configured) { ble_hs_unlock(); @@ -3606,6 +3766,23 @@ ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data) goto done; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + uint16_t len = OS_MBUF_PKTLEN(data); + ble_adv_reattempt.type = 1; + ble_adv_reattempt.instance = instance; + + // Allocate if NULL + if (ble_adv_reattempt.data == NULL) { + ble_adv_reattempt.data = os_msys_get_pkthdr(len , 0); + } + + if (ble_adv_reattempt.data && (ble_adv_reattempt.data != data)) { + os_mbuf_adj(ble_adv_reattempt.data, len); + rc = os_mbuf_appendfrom(ble_adv_reattempt.data, data, 0, len); + assert (rc == 0); + } +#endif + ble_hs_lock(); rc = ble_gap_ext_adv_set_data_validate(instance, data); if (rc != 0) { @@ -3618,7 +3795,15 @@ ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data) ble_hs_unlock(); done: +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + if (ble_adv_reattempt.data != data) { + os_mbuf_free_chain(data); + data = NULL; + } +#else os_mbuf_free_chain(data); + data = NULL; +#endif return rc; } @@ -5626,51 +5811,38 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, ble_gap_master.op = BLE_GAP_OP_M_CONN; #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - /* ble_gap_connect_reattempt save the connection parameters */ - if ((cb_arg != NULL) && conn_cookie_enabled) { - struct ble_gap_conn_desc *conn_desc = cb_arg; - struct ble_gap_conn_desc *curr_conn_desc=NULL; - /* reattempt_idx is set to that index where corresponding conn_handle entry was made */ - for (int i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { - curr_conn_desc = ble_conn_reattempt[i].cb_arg; - if (curr_conn_desc && (conn_desc->conn_handle == curr_conn_desc->conn_handle)) { - reattempt_idx = i; - break; - } - } - /* Reset cookie_enabled flag, it will be set again by reattempt call */ - conn_cookie_enabled = false; + ble_conn_reattempt.own_addr_type = own_addr_type; + + if (peer_addr != NULL) { + ble_conn_reattempt.peer_addr_present = 1; + memcpy(&ble_conn_reattempt.peer_addr, peer_addr, sizeof(ble_addr_t)); + } else { + ble_conn_reattempt.peer_addr_present = 0; + memset(&ble_conn_reattempt.peer_addr, 0, sizeof(ble_addr_t)); } - ble_conn_reattempt[reattempt_idx].own_addr_type = own_addr_type; - memcpy(&ble_conn_reattempt[reattempt_idx].peer_addr, peer_addr, - sizeof(ble_addr_t)); - ble_conn_reattempt[reattempt_idx].duration_ms = duration_ms; + ble_conn_reattempt.duration_ms = duration_ms; if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) { - memcpy(&ble_conn_reattempt[reattempt_idx].conn_params, + memcpy(&ble_conn_reattempt.conn_params, phy_1m_conn_params, sizeof(struct ble_gap_conn_params)); } if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) { - memcpy(&ble_conn_reattempt[reattempt_idx].conn_params, + memcpy(&ble_conn_reattempt.conn_params, phy_2m_conn_params, sizeof(struct ble_gap_conn_params)); } if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) { - memcpy(&ble_conn_reattempt[reattempt_idx].conn_params, + memcpy(&ble_conn_reattempt.conn_params, phy_coded_conn_params, sizeof(struct ble_gap_conn_params)); } - ble_conn_reattempt[reattempt_idx].cb = cb; - ble_conn_reattempt[reattempt_idx].cb_arg = cb_arg; - /* reattempt_idx need to be within limits. This may end up being unnecessary - * operation. However, it is better to be sure as it can get tricky with - * multiple connections and client + server roles XXX*/ - reattempt_idx = (reattempt_idx + 1) % MYNEWT_VAL(BLE_MAX_CONNECTIONS); + ble_conn_reattempt.cb = cb; + ble_conn_reattempt.cb_arg = cb_arg; #endif @@ -5812,56 +5984,39 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, memcpy(bhc_peer_addr.val, peer_addr->val, BLE_DEV_ADDR_LEN); #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) + if (ble_host_rpa_enabled()) + { struct ble_hs_resolv_entry *rl = NULL; rl = ble_hs_resolv_list_find(bhc_peer_addr.val); - if (rl != NULL) { + if (rl != NULL && rl->rl_isrpa) { memcpy(bhc_peer_addr.val, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN); bhc_peer_addr.type = rl->rl_addr_type; } + } #endif } else { memset(&bhc_peer_addr, 0, sizeof bhc_peer_addr); } #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - /* ble_gap_connect_reattempt save the connection parameters */ - if ((cb_arg != NULL) && conn_cookie_enabled) { - struct ble_gap_conn_desc *conn_desc = cb_arg; - struct ble_gap_conn_desc *curr_conn_desc=NULL; - /* reattempt_idx is set to that index where corresponding conn_handle entry was made */ - for (int i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { - curr_conn_desc = ble_conn_reattempt[i].cb_arg; - if (curr_conn_desc && (conn_desc->conn_handle == curr_conn_desc->conn_handle)) { - reattempt_idx = i; - break; - } - } - /* Reset cookie_enabled flag, it will be set again by reattempt call */ - conn_cookie_enabled = false; - } - - ble_conn_reattempt[reattempt_idx].own_addr_type = own_addr_type; + ble_conn_reattempt.own_addr_type = own_addr_type; if (peer_addr != NULL) { - ble_conn_reattempt[reattempt_idx].peer_addr_present = 1; - memcpy(&ble_conn_reattempt[reattempt_idx].peer_addr, &bhc_peer_addr, + ble_conn_reattempt.peer_addr_present = 1; + memcpy(&ble_conn_reattempt.peer_addr, &bhc_peer_addr, sizeof(ble_addr_t)); } else { - ble_conn_reattempt[reattempt_idx].peer_addr_present = 0; - memset(&ble_conn_reattempt[reattempt_idx].peer_addr, 0, + ble_conn_reattempt.peer_addr_present = 0; + memset(&ble_conn_reattempt.peer_addr, 0, sizeof(ble_addr_t)); } - ble_conn_reattempt[reattempt_idx].duration_ms = duration_ms; - memcpy(&ble_conn_reattempt[reattempt_idx].conn_params, + + ble_conn_reattempt.duration_ms = duration_ms; + memcpy(&ble_conn_reattempt.conn_params, conn_params, sizeof(struct ble_gap_conn_params)); - ble_conn_reattempt[reattempt_idx].cb = cb; - ble_conn_reattempt[reattempt_idx].cb_arg = cb_arg; - - /* reattempt_idx need to be within limits. This may end up being unnecessary - * operation. However, it is better to be sure as it can get tricky with - * multiple connections and client + server roles XXX*/ - reattempt_idx = (reattempt_idx + 1) % MYNEWT_VAL(BLE_MAX_CONNECTIONS); + ble_conn_reattempt.cb = cb; + ble_conn_reattempt.cb_arg = cb_arg; #endif if (peer_addr != NULL) { @@ -6746,15 +6901,15 @@ ble_gap_unpair(const ble_addr_t *peer_addr) irk_rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type, key.sec.peer_addr.val); if (irk_rc != 0) { - BLE_HS_LOG(ERROR, "Error while removing IRK\n"); + BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",irk_rc); } } - if (value.sec.ltk_present || value.sec.irk_present) { + if (value.sec.ltk_present || value.sec.irk_present || value.sec.csrk_present) { // Delete the Peer record from store as LTK is present ltk_rc = ble_store_util_delete_peer(&key.sec.peer_addr); if (ltk_rc != 0) { - BLE_HS_LOG(ERROR, "Error while removing LTK\n"); + BLE_HS_LOG(ERROR, "Error while removing LTK , rc = %x\n",ltk_rc); } } } @@ -6764,7 +6919,7 @@ ble_gap_unpair(const ble_addr_t *peer_addr) ble_store_util_delete_peer(&key.sec.peer_addr); } else { - BLE_HS_LOG(ERROR,"No record found for the given address in ble store"); + BLE_HS_LOG(ERROR,"No record found for the given address in ble store , rc = %x\n",rc); return rc; } diff --git a/src/nimble/nimble/host/src/ble_gap_priv.h b/src/nimble/nimble/host/src/ble_gap_priv.h index f8874b1b..31964aee 100644 --- a/src/nimble/nimble/host/src/ble_gap_priv.h +++ b/src/nimble/nimble/host/src/ble_gap_priv.h @@ -161,6 +161,8 @@ int ble_gap_dbg_update_active(uint16_t conn_handle); void ble_gap_reattempt_count(uint16_t conn_handle, uint8_t count); #endif +void ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev); + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/src/ble_gatt_priv.h b/src/nimble/nimble/host/src/ble_gatt_priv.h index af97f7c2..f21f26b6 100644 --- a/src/nimble/nimble/host/src/ble_gatt_priv.h +++ b/src/nimble/nimble/host/src/ble_gatt_priv.h @@ -137,7 +137,7 @@ void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, struct os_mbuf **rxom); void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, - struct os_mbuf **rxom); + struct os_mbuf **rxom, bool variable); void ble_gattc_rx_read_group_type_adata( uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); diff --git a/src/nimble/nimble/host/src/ble_gattc.c b/src/nimble/nimble/host/src/ble_gattc.c index 4778aecf..d29c2f2b 100644 --- a/src/nimble/nimble/host/src/ble_gattc.c +++ b/src/nimble/nimble/host/src/ble_gattc.c @@ -94,11 +94,12 @@ #define BLE_GATT_OP_READ_UUID 8 #define BLE_GATT_OP_READ_LONG 9 #define BLE_GATT_OP_READ_MULT 10 -#define BLE_GATT_OP_WRITE 11 -#define BLE_GATT_OP_WRITE_LONG 12 -#define BLE_GATT_OP_WRITE_RELIABLE 13 -#define BLE_GATT_OP_INDICATE 14 -#define BLE_GATT_OP_CNT 15 +#define BLE_GATT_OP_READ_MULT_VAR 11 +#define BLE_GATT_OP_WRITE 12 +#define BLE_GATT_OP_WRITE_LONG 13 +#define BLE_GATT_OP_WRITE_RELIABLE 14 +#define BLE_GATT_OP_INDICATE 15 +#define BLE_GATT_OP_CNT 16 /** Procedure stalled due to resource exhaustion. */ #define BLE_GATTC_PROC_F_STALLED 0x01 @@ -189,7 +190,9 @@ struct ble_gattc_proc { struct { uint16_t handles[MYNEWT_VAL(BLE_GATT_READ_MAX_ATTRS)]; uint8_t num_handles; + bool variable; ble_gatt_attr_fn *cb; + ble_gatt_attr_mult_fn *cb_mult; void *cb_arg; } read_mult; @@ -586,7 +589,7 @@ ble_gattc_log_read_long(struct ble_gattc_proc *proc) } static void -ble_gattc_log_read_mult(const uint16_t *handles, uint8_t num_handles) +ble_gattc_log_read_mult(const uint16_t *handles, uint8_t num_handles, bool variable) { int i; @@ -3081,7 +3084,6 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle, #if !MYNEWT_VAL(BLE_GATT_READ_UUID) return BLE_HS_ENOTSUP; #endif - /* TODO:Roshan */ struct ble_gattc_proc *proc; int rc; @@ -3322,6 +3324,73 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset, * $read multiple * *****************************************************************************/ +static int +ble_gattc_read_mult_cb_var(struct ble_gattc_proc *proc, int status, + uint16_t att_handle, struct os_mbuf **om) +{ + struct ble_gatt_attr attr[proc->read_mult.num_handles]; + int rc; + int i; + uint16_t attr_len; + + if (proc->read_mult.cb_mult == NULL) { + return 0; + } + + memset(attr, 0, sizeof(*attr)); + + for (i = 0; i < proc->read_mult.num_handles; i++) { + attr[i].handle = proc->read_mult.handles[i]; + attr[i].offset = 0; + if (om == NULL || OS_MBUF_PKTLEN(*om) == 0) { + continue; + } + + *om = os_mbuf_pullup(*om, 2); + assert(*om); + + attr_len = get_le16((*om)->om_data); + + os_mbuf_adj(*om, 2); + + if (attr_len > BLE_ATT_ATTR_MAX_LEN) { + /*TODO Figure out what to do here */ + break; + } + + attr[i].om = os_msys_get_pkthdr(attr_len, 0); + if (!attr[i].om) { + /*TODO Figure out what to do here */ + break; + } + + rc = os_mbuf_appendfrom(attr[i].om, *om, 0, attr_len); + if (rc) { + /*TODO Figure out what to do here */ + break; + } + + os_mbuf_adj(*om, attr_len); + } + + /*FIXME Testing assert */ + assert(i == proc->read_mult.num_handles); + + proc->read_mult.cb_mult(proc->conn_handle, + ble_gattc_error(status, att_handle), &attr[0], + i, + proc->read_mult.cb_arg); + + for (i = 0; i < proc->read_mult.num_handles; i++) { + if (attr[i].om != NULL) { + os_mbuf_free_chain(attr[i].om); + } + } + + return 0; +} + + /** * Calls a read-multiple-characteristics proc's callback with the specified * parameters. If the proc has no callback, this function is a no-op. @@ -3344,6 +3413,10 @@ ble_gattc_read_mult_cb(struct ble_gattc_proc *proc, int status, STATS_INC(ble_gattc_stats, read_mult_fail); } + if (proc->read_mult.variable) { + return ble_gattc_read_mult_cb_var(proc, status, att_handle, om); + } + attr.handle = 0; attr.offset = 0; if (om == NULL) { @@ -3400,7 +3473,7 @@ ble_gattc_read_mult_tx(struct ble_gattc_proc *proc) int rc; rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->read_mult.handles, - proc->read_mult.num_handles); + proc->read_mult.num_handles, proc->read_mult.variable); if (rc != 0) { return rc; } @@ -3409,10 +3482,11 @@ ble_gattc_read_mult_tx(struct ble_gattc_proc *proc) } -int -ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, - uint8_t num_handles, ble_gatt_attr_fn *cb, - void *cb_arg) +static int +ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles, + uint8_t num_handles, bool variable, ble_gatt_attr_fn *cb, + ble_gatt_attr_mult_fn *cb_mult, + void *cb_arg) { #if !MYNEWT_VAL(BLE_GATT_READ_MULT) return BLE_HS_ENOTSUP; @@ -3436,14 +3510,20 @@ ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, goto done; } - proc->op = BLE_GATT_OP_READ_MULT; + if (variable) { + proc->op = BLE_GATT_OP_READ_MULT_VAR; + } else { + proc->op = BLE_GATT_OP_READ_MULT; + } proc->conn_handle = conn_handle; memcpy(proc->read_mult.handles, handles, num_handles * sizeof *handles); proc->read_mult.num_handles = num_handles; + proc->read_mult.variable = variable; proc->read_mult.cb = cb; + proc->read_mult.cb_mult = cb_mult; proc->read_mult.cb_arg = cb_arg; - ble_gattc_log_read_mult(handles, num_handles); + ble_gattc_log_read_mult(handles, num_handles, variable); rc = ble_gattc_read_mult_tx(proc); if (rc != 0) { goto done; @@ -3458,6 +3538,28 @@ ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, return rc; } +int +ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, + uint8_t num_handles, ble_gatt_attr_fn *cb, + void *cb_arg) +{ + return ble_gattc_read_mult_internal(conn_handle, handles, + num_handles, false, cb, NULL, cb_arg); +} + +int +ble_gattc_read_mult_var(uint16_t conn_handle, const uint16_t *handles, + uint8_t num_handles, ble_gatt_attr_mult_fn *cb, + void *cb_arg) +{ +#if MYNEWT_VAL(BLE_GATT_READ_MULT_VAR) + return ble_gattc_read_mult_internal(conn_handle, handles, num_handles, + true, NULL, cb, cb_arg); +#else + return BLE_HS_ENOTSUP; +#endif +} + /***************************************************************************** * $write no response * *****************************************************************************/ @@ -3520,6 +3622,7 @@ ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_store_value_sec value_sec; struct ble_store_key_sec key_sec; struct ble_gap_conn_desc desc; + uint8_t csrk[16]; STATS_INC(ble_gattc_stats, signed_write); @@ -3547,8 +3650,11 @@ ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, goto err; } + /* Converting the csrk to little endian */ + swap_buf(csrk, value_sec.csrk, 16); + rc = ble_att_clt_tx_signed_write_cmd(conn_handle, attr_handle, - value_sec.csrk, value_sec.sign_counter, txom); + csrk, value_sec.sign_counter, txom); if (rc != 0) { goto err; } @@ -4871,16 +4977,18 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, */ void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, - struct os_mbuf **om) + struct os_mbuf **om, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return; #endif struct ble_gattc_proc *proc; + uint8_t op; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_READ_MULT); + op = variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT; + + proc = ble_gattc_extract_first_by_conn_op(conn_handle, op); if (proc != NULL) { ble_gattc_read_mult_cb(proc, status, 0, om); ble_gattc_process_status(proc, BLE_HS_EDONE); diff --git a/src/nimble/nimble/host/src/ble_gatts.c b/src/nimble/nimble/host/src/ble_gatts.c index bdb00a60..e07a91e6 100644 --- a/src/nimble/nimble/host/src/ble_gatts.c +++ b/src/nimble/nimble/host/src/ble_gatts.c @@ -590,8 +590,9 @@ ble_gatts_calculate_hash(uint8_t *out_hash_key) int size; int rc; uint8_t *buf; - uint8_t key[16] = {0}; + uint8_t key[16]; + memset(key, 0, sizeof(key)); /* data with all zeroes */ rc = ble_att_get_database_size(&size); if(rc != 0) { @@ -761,7 +762,7 @@ ble_gatts_cpfd_is_sane(const struct ble_gatt_cpfd *cpfd) return 0; } - if ((cpfd->namespace_ == BLE_GATT_CHR_NAMESPACE_BT_SIG) && (cpfd->description > 0x0110)) { + if ((cpfd->name_space == BLE_GATT_CHR_NAMESPACE_BT_SIG) && (cpfd->description > 0x0110)) { return 0; } @@ -1058,7 +1059,7 @@ ble_gatts_cpfd_access(uint16_t conn_handle, uint16_t attr_handle, rc += os_mbuf_append(*om, &(cpfd->format), sizeof(cpfd->format)); rc += os_mbuf_append(*om, &(cpfd->exponent), sizeof(cpfd->exponent)); rc += os_mbuf_append(*om, &(cpfd->unit), sizeof(cpfd->unit)); - rc += os_mbuf_append(*om, &(cpfd->namespace_), sizeof(cpfd->namespace_)); + rc += os_mbuf_append(*om, &(cpfd->name_space), sizeof(cpfd->name_space)); rc += os_mbuf_append(*om, &(cpfd->description), sizeof(cpfd->description)); return ((rc == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES); @@ -2214,6 +2215,8 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) int rc = 0; int i; + BLE_HS_LOG(DEBUG, ""); + if (!om) { return BLE_ATT_ERR_INSUFFICIENT_RES; } diff --git a/src/nimble/nimble/host/src/ble_hs_conn.c b/src/nimble/nimble/host/src/ble_hs_conn.c index 0f10c826..a01ec413 100644 --- a/src/nimble/nimble/host/src/ble_hs_conn.c +++ b/src/nimble/nimble/host/src/ble_hs_conn.c @@ -503,86 +503,73 @@ ble_hs_conn_timer(void) #endif struct ble_hs_conn *conn; - ble_npl_time_t now; - int32_t next_exp_in; + ble_npl_time_t now = ble_npl_time_get(); + int32_t next_exp_in = BLE_HS_FOREVER; + int32_t next_exp_in_new; + bool next_exp_in_updated; int32_t time_diff; - uint16_t conn_handle; - for (;;) { - conn_handle = BLE_HS_CONN_HANDLE_NONE; - next_exp_in = BLE_HS_FOREVER; - now = ble_npl_time_get(); + ble_hs_lock(); - ble_hs_lock(); - - /* This loop performs one of two tasks: - * 1. Determine if any connections need to be terminated due to timeout. - * If so, break out of the loop and terminate the connection. This - * function will need to be executed again. - * 2. Otherwise, determine when the next timeout will occur. - */ - SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) { - if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) { + /* This loop performs one of two tasks: + * 1. Determine if any connections need to be terminated due to timeout. If + * so connection is disconnected. + * 2. Otherwise, determine when the next timeout will occur. + */ + SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) { + if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) { + next_exp_in_updated = false; #if MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT) != 0 - /* Check each connection's rx fragment timer. If too much time - * passes after a partial packet is received, the connection is - * terminated. - */ - if (conn->bhc_rx_chan != NULL) { - time_diff = conn->bhc_rx_timeout - now; - - if (time_diff <= 0) { - /* ACL reassembly has timed out. Remember the connection - * handle so it can be terminated after the mutex is - * unlocked. - */ - conn_handle = conn->bhc_handle; - break; - } - - /* Determine if this connection is the soonest to time out. */ - if (time_diff < next_exp_in) { - next_exp_in = time_diff; - } - } -#endif + /* Check each connection's rx fragment timer. If too much time + * passes after a partial packet is received, the connection is + * terminated. + */ + if (conn->bhc_rx_chan != NULL) { + time_diff = conn->bhc_rx_timeout - now; -#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO - /* Check each connection's rx queued write timer. If too much - * time passes after a prep write is received, the queue is - * cleared. - */ - time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now); if (time_diff <= 0) { - /* ACL reassembly has timed out. Remember the connection - * handle so it can be terminated after the mutex is - * unlocked. - */ - conn_handle = conn->bhc_handle; - break; + /* ACL reassembly has timed out.*/ + ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM); + continue; } /* Determine if this connection is the soonest to time out. */ if (time_diff < next_exp_in) { - next_exp_in = time_diff; + next_exp_in_new = time_diff; + next_exp_in_updated = true; } + } #endif + +#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO + /* Check each connection's rx queued write timer. If too much + * time passes after a prep write is received, the queue is + * cleared. + */ + time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now); + if (time_diff <= 0) { + /* Queued write has timed out.*/ + ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM); + continue; } - } - ble_hs_unlock(); + /* Determine if this connection is the soonest to time out. */ + if (time_diff < next_exp_in) { + next_exp_in_new = time_diff; + next_exp_in_updated = true; + } +#endif - /* If a connection has timed out, terminate it. We need to repeatedly - * call this function again to determine when the next timeout is. - */ - if (conn_handle != BLE_HS_CONN_HANDLE_NONE) { - ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM); - continue; + if (next_exp_in_updated) { + next_exp_in = next_exp_in_new; + } } - - return next_exp_in; } + + ble_hs_unlock(); + + return next_exp_in; } int diff --git a/src/nimble/nimble/host/src/ble_hs_hci_evt.c b/src/nimble/nimble/host/src/ble_hs_hci_evt.c index bc77dc3a..d1580512 100644 --- a/src/nimble/nimble/host/src/ble_hs_hci_evt.c +++ b/src/nimble/nimble/host/src/ble_hs_hci_evt.c @@ -31,10 +31,10 @@ struct ble_gap_reattempt_ctxt { ble_addr_t peer_addr; uint8_t count; -}; +}reattempt_conn; -static struct ble_gap_reattempt_ctxt reattempt_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; extern int ble_gap_master_connect_reattempt(uint16_t conn_handle); +extern int ble_gap_slave_adv_reattempt(void); #ifdef CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT #define MAX_REATTEMPT_ALLOWED CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT @@ -79,6 +79,7 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_complete; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_upd_complete; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_lt_key_req; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_parm_req; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_data_len_change; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_phy_update_complete; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_enh_conn_complete; #endif @@ -147,6 +148,7 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = { [BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE] = ble_hs_hci_evt_le_conn_upd_complete, [BLE_HCI_LE_SUBEV_LT_KEY_REQ] = ble_hs_hci_evt_le_lt_key_req, [BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ] = ble_hs_hci_evt_le_conn_parm_req, + [BLE_HCI_LE_SUBEV_DATA_LEN_CHG] = ble_hs_hci_evt_le_data_len_change, [BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE] = ble_hs_hci_evt_le_enh_conn_complete, #endif [BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT] = ble_hs_hci_evt_le_dir_adv_rpt, @@ -200,22 +202,6 @@ ble_hs_hci_evt_le_dispatch_find(uint8_t event_code) return ble_hs_hci_evt_le_dispatch[event_code]; } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) -static int -ble_gap_find_reattempt_conn_idx(const struct ble_hs_conn *conn) -{ - int i; - - for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { - if (memcmp(&reattempt_conn[i].peer_addr, &conn->bhc_peer_addr, sizeof(ble_addr_t)) == 0) { - return i; - } - } - /* No matching entry found. Return invalid index */ - return MYNEWT_VAL(BLE_MAX_CONNECTIONS); -} -#endif - #if NIMBLE_BLE_CONNECT static int ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data, @@ -236,68 +222,47 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data, ble_hs_unlock(); #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - if (ev->reason == BLE_ERR_CONN_ESTABLISHMENT) { - int rc, i, idx; + if (conn && ev->reason == BLE_ERR_CONN_ESTABLISHMENT) { uint16_t handle; + int rc; - idx = ble_gap_find_reattempt_conn_idx(conn); - - if (idx == MYNEWT_VAL(BLE_MAX_CONNECTIONS)) { - /* This means, no matching addr exists in databse. So create a new one */ - for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { - if (reattempt_conn[i].count == 0) { - idx = i; - break; - } - } - } - - if (idx == MYNEWT_VAL(BLE_MAX_CONNECTIONS)) { - BLE_HS_LOG(DEBUG, "No space left in array "); + if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { //slave + BLE_HS_LOG(INFO, "Reattempt advertising; reason: 0x%x, status = %x", + ev->reason, ev->status); - for (i = 0; i < idx; i++) { - memset(&reattempt_conn[i], 0x0, sizeof(struct ble_gap_reattempt_ctxt)); - } - goto done; - } - - if (conn != NULL) { - BLE_HS_LOG(DEBUG, "Reattempt connection; reason = 0x%x, status = %d," - "reattempt count = %d ", ev->reason, ev->status, - reattempt_conn[idx].count); - if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { - if (reattempt_conn[idx].count < MAX_REATTEMPT_ALLOWED) { - reattempt_conn[idx].count += 1; + rc = ble_gap_slave_adv_reattempt(); + if (rc != 0) { + BLE_HS_LOG(INFO, "Adv reattempt failed; rc= %d ", rc); + } - for (i = 0; i < BLE_DEV_ADDR_LEN; i++) { - reattempt_conn[idx].peer_addr.val[i] = conn->bhc_peer_addr.val[i]; - } + return 0; // Restart advertising, so don't post disconnect event - reattempt_conn[idx].peer_addr.type = conn->bhc_peer_addr.type; + } else { // master + if (reattempt_conn.count < MAX_REATTEMPT_ALLOWED ) { + /* Got for connection */ + BLE_HS_LOG(INFO, "Reattempt connection; reason = 0x%x, status = %d," + "reattempt count = %d ", ev->reason, ev->status, + reattempt_conn.count); + reattempt_conn.count += 1; - handle = le16toh(ev->conn_handle); - /* Post event to interested application */ - ble_gap_reattempt_count(handle, reattempt_conn[idx].count); + handle = le16toh(ev->conn_handle); + /* Post event to interested application */ + ble_gap_reattempt_count(handle, reattempt_conn.count); - rc = ble_gap_master_connect_reattempt(ev->conn_handle); - if (rc != 0) { - BLE_HS_LOG(DEBUG, "Master reconnect attempt failed; rc = %d", rc); - } - } else { - memset(&reattempt_conn[idx].peer_addr, 0x0, BLE_DEV_ADDR_LEN); - reattempt_conn[idx].count = 0; + rc = ble_gap_master_connect_reattempt(ev->conn_handle); + if (rc != 0) { + BLE_HS_LOG(INFO, "Master reconnect attempt failed; rc = %d", rc); } + } else { + /* Exhausted attempts */ + memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); } - } else { - /* Disconnect completed with some other reason than - * BLE_ERR_CONN_ESTABLISHMENT, reset the corresponding reattempt count - * */ - memset(&reattempt_conn[idx].peer_addr, 0x0, BLE_DEV_ADDR_LEN); - reattempt_conn[idx].count = 0; - } + } + } + else { + /* Normal disconnect. Reset the structure */ + memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); } -done: - #endif ble_gap_rx_disconn_complete(ev); @@ -670,6 +635,9 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len) rl = ble_hs_resolv_rpa_addr(desc.addr.val, desc.addr.type); if (rl != NULL) { + if(desc.addr.type == 1) { + rl->rl_isrpa = 1; + } memcpy(desc.addr.val, rl->rl_identity_addr, BLE_DEV_ADDR_LEN); desc.addr.type = rl->rl_addr_type; } @@ -1071,6 +1039,22 @@ ble_hs_hci_evt_le_phy_update_complete(uint8_t subevent, const void *data, return 0; } + +static int +ble_hs_hci_evt_le_data_len_change(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_data_len_chg *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_data_len_change(ev); + + return 0; + +} #endif int diff --git a/src/nimble/nimble/host/src/ble_hs_pvcy.c b/src/nimble/nimble/host/src/ble_hs_pvcy.c index 8995ce1f..dee55e87 100644 --- a/src/nimble/nimble/host/src/ble_hs_pvcy.c +++ b/src/nimble/nimble/host/src/ble_hs_pvcy.c @@ -29,6 +29,7 @@ static uint8_t ble_hs_pvcy_irk[16]; /** Use this as a default IRK if none gets set. */ uint8_t ble_hs_pvcy_default_irk[16]; +uint16_t rpa_timeout; static int ble_hs_pvcy_set_addr_timeout(uint16_t timeout) @@ -50,6 +51,23 @@ ble_hs_pvcy_set_addr_timeout(uint16_t timeout) &cmd, sizeof(cmd), NULL, 0); } +void ble_hs_set_rpa_timeout (uint16_t timeout) +{ + rpa_timeout = timeout; + + ble_hs_pvcy_set_addr_timeout(rpa_timeout); +} + +uint16_t ble_hs_get_rpa_timeout(void) +{ + return rpa_timeout; +} + +void ble_hs_reset_rpa_timeout(void) +{ + rpa_timeout = 0 ; +} + #if (!MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)) int ble_hs_pvcy_set_resolve_enabled(int enable) @@ -179,6 +197,7 @@ int ble_hs_pvcy_ensure_started(void) { int rc; + uint16_t rpa_timeout; if (ble_hs_pvcy_started) { return 0; @@ -189,8 +208,16 @@ ble_hs_pvcy_ensure_started(void) ble_hs_resolv_init(); #endif + /* Check if user has already set any timeout. If yes, use it */ + rpa_timeout = ble_hs_get_rpa_timeout(); + /* Set up the periodic change of our RPA. */ - rc = ble_hs_pvcy_set_addr_timeout(MYNEWT_VAL(BLE_RPA_TIMEOUT)); + if (rpa_timeout) { + rc = ble_hs_pvcy_set_addr_timeout(rpa_timeout); + } else { + rc = ble_hs_pvcy_set_addr_timeout(MYNEWT_VAL(BLE_RPA_TIMEOUT)); + } + if (rc != 0) { return rc; } diff --git a/src/nimble/nimble/host/src/ble_hs_resolv_priv.h b/src/nimble/nimble/host/src/ble_hs_resolv_priv.h index 5a74b942..382ac82b 100644 --- a/src/nimble/nimble/host/src/ble_hs_resolv_priv.h +++ b/src/nimble/nimble/host/src/ble_hs_resolv_priv.h @@ -35,6 +35,7 @@ struct ble_hs_resolv_entry { uint8_t rl_pseudo_id[BLE_DEV_ADDR_LEN]; uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN]; uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN]; + uint8_t rl_isrpa; }; #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) diff --git a/src/nimble/nimble/host/src/ble_sm_priv.h b/src/nimble/nimble/host/src/ble_sm_priv.h index ddfb413e..261147a1 100644 --- a/src/nimble/nimble/host/src/ble_sm_priv.h +++ b/src/nimble/nimble/host/src/ble_sm_priv.h @@ -432,7 +432,6 @@ int ble_sm_init(void); struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle); void *ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); int ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom); -int ble_sm_alg_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out); #ifdef __cplusplus diff --git a/src/nimble/nimble/host/store/config/src/ble_store_config.c b/src/nimble/nimble/host/store/config/src/ble_store_config.c index d4fc8e01..4b785767 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_config.c +++ b/src/nimble/nimble/host/store/config/src/ble_store_config.c @@ -19,6 +19,7 @@ #include #include +#include #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" @@ -32,6 +33,9 @@ struct ble_store_value_sec #endif int ble_store_config_num_our_secs; +uint16_t ble_store_config_our_bond_count; +uint16_t ble_store_config_peer_bond_count; + #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) struct ble_store_value_sec ble_store_config_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; @@ -66,6 +70,107 @@ int ble_store_config_num_local_irks; * $sec * *****************************************************************************/ +int ble_store_config_compare_bond_count(const void *a, const void *b) { + const struct ble_store_value_sec *sec_a = (const struct ble_store_value_sec *)a; + const struct ble_store_value_sec *sec_b = (const struct ble_store_value_sec *)b; + + return sec_a->bond_count - sec_b->bond_count; +} + +/* This function gets the stored device records of OUR_SEC object type, arranges them in order of their bond count, + * and then updates them with new counts so they're in sequence. + */ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +int ble_restore_our_sec_nvs(void) +{ + int rc; + extern uint16_t ble_store_config_our_bond_count; + struct ble_store_value_sec temp_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; + int temp_count = 0; + + ble_store_config_our_bond_count = 0; + + memcpy(temp_our_secs, ble_store_config_our_secs, ble_store_config_num_our_secs * sizeof(struct ble_store_value_sec)); + temp_count = ble_store_config_num_our_secs; + + qsort(temp_our_secs, temp_count, sizeof(struct ble_store_value_sec), ble_store_config_compare_bond_count); + + for (int i = 0; i < temp_count; i++) { + + union ble_store_key key; + ble_store_key_from_value_sec(&key.sec, &temp_our_secs[i]); + + rc = ble_store_config_delete(BLE_STORE_OBJ_TYPE_OUR_SEC, &key); + + if (rc != 0) { + BLE_HS_LOG(DEBUG, "Error deleting from nvs"); + return rc; + } + } + + for (int i = 0; i < temp_count; i++) { + + union ble_store_value val; + val.sec = temp_our_secs[i]; + + rc = ble_store_config_write(BLE_STORE_OBJ_TYPE_OUR_SEC, &val); + + if (rc != 0) { + BLE_HS_LOG(DEBUG, "Error writing record to NVS"); + return rc; + } + } + + return 0; +} + +/* This function gets the stored device records of PEER_SEC object type, arranges them in order of their bond count, + * and then updates them with new counts so they're in sequence. + */ +int ble_restore_peer_sec_nvs(void) +{ + int rc; + extern uint16_t ble_store_config_peer_bond_count; + struct ble_store_value_sec temp_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; + int temp_count = 0; + + ble_store_config_peer_bond_count = 0; + + memcpy(temp_peer_secs, ble_store_config_peer_secs, ble_store_config_num_peer_secs * sizeof(struct ble_store_value_sec)); + temp_count = ble_store_config_num_peer_secs; + + qsort(temp_peer_secs, temp_count, sizeof(struct ble_store_value_sec), ble_store_config_compare_bond_count); + + for (int i = 0; i < temp_count; i++) { + + union ble_store_key key; + ble_store_key_from_value_sec(&key.sec, &temp_peer_secs[i]); + + rc = ble_store_config_delete(BLE_STORE_OBJ_TYPE_PEER_SEC, &key); + + if (rc != 0) { + BLE_HS_LOG(DEBUG, "Error deleting from nvs"); + return rc; + } + } + + for (int i = 0; i < temp_count; i++) { + + union ble_store_value val; + val.sec = temp_peer_secs[i]; + + rc = ble_store_config_write(BLE_STORE_OBJ_TYPE_PEER_SEC, &val); + + if (rc != 0) { + BLE_HS_LOG(DEBUG, "Error writing record to NVS"); + return rc; + } + } + + return 0; +} +#endif + #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static void ble_store_config_print_value_sec(const struct ble_store_value_sec *sec) @@ -197,11 +302,20 @@ ble_store_config_write_our_sec(const struct ble_store_value_sec *value_sec) ble_store_config_our_secs[idx] = *value_sec; + ble_store_config_our_secs[idx].bond_count = ++ble_store_config_our_bond_count; + rc = ble_store_config_persist_our_secs(); if (rc != 0) { return rc; } + if (ble_store_config_our_bond_count > (UINT16_MAX - 5)) { + rc = ble_restore_our_sec_nvs(); + if (rc != 0) { + return rc; + } + } + return 0; #else return BLE_HS_ENOENT; @@ -216,7 +330,7 @@ ble_store_config_delete_obj(void *values, int value_size, int idx, { uint8_t *dst; uint8_t *src; - int move_count; + uint8_t move_count; (*num_values)--; if (idx < *num_values) { @@ -347,10 +461,20 @@ ble_store_config_write_peer_sec(const struct ble_store_value_sec *value_sec) ble_store_config_peer_secs[idx] = *value_sec; + ble_store_config_peer_secs[idx].bond_count = ++ble_store_config_peer_bond_count; + rc = ble_store_config_persist_peer_secs(); if (rc != 0) { return rc; } + + if (ble_store_config_peer_bond_count > (UINT16_MAX - 5)) { + rc = ble_restore_peer_sec_nvs(); + if (rc != 0) { + return rc; + } + } + return 0; #else return BLE_HS_ENOENT; diff --git a/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h b/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h index cdc676e1..581cefdc 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h +++ b/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h @@ -56,6 +56,10 @@ extern int ble_store_config_num_local_irks; int ble_store_config_persist_our_secs(void); int ble_store_config_persist_peer_secs(void); int ble_store_config_persist_cccds(void); +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +int ble_restore_our_sec_nvs(void); +int ble_restore_peer_sec_nvs(void); +#endif #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_config_persist_eads(void); #endif diff --git a/src/nimble/nimble/host/store/config/src/ble_store_nvs.c b/src/nimble/nimble/host/store/config/src/ble_store_nvs.c index a7be71a5..18aa00e5 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_nvs.c +++ b/src/nimble/nimble/host/store/config/src/ble_store_nvs.c @@ -526,7 +526,12 @@ static int ble_nvs_restore_sec_keys(void) { esp_err_t err; + int flag = 0; + extern uint16_t ble_store_config_our_bond_count; + extern uint16_t ble_store_config_peer_bond_count; + extern int ble_store_config_compare_bond_count(const void *a, const void *b); +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_OUR_SEC, ble_store_config_our_secs, &ble_store_config_num_our_secs); if (err != ESP_OK) { @@ -541,9 +546,32 @@ ble_nvs_restore_sec_keys(void) ESP_LOGE(TAG, "NVS operation failed for 'peer sec'"); return err; } + + for (int i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS) - 1; i++) { + if ((ble_store_config_our_secs[i].bond_count > ble_store_config_our_secs[i+1].bond_count) + || (ble_store_config_peer_secs[i].bond_count > ble_store_config_peer_secs[i+1].bond_count)) { + flag = 1; + break; + } + } + + if (flag) { + + qsort(ble_store_config_our_secs, ble_store_config_num_our_secs, + sizeof(struct ble_store_value_sec), ble_store_config_compare_bond_count); + + qsort(ble_store_config_peer_secs, ble_store_config_num_peer_secs, + sizeof(struct ble_store_value_sec), ble_store_config_compare_bond_count); + } + + ble_store_config_our_bond_count = ble_store_config_our_secs[ble_store_config_num_our_secs - 1].bond_count; + ble_store_config_peer_bond_count = ble_store_config_peer_secs[ble_store_config_num_peer_secs - 1].bond_count; + ESP_LOGD(TAG, "ble_store_config_peer_secs restored %d bonds", ble_store_config_num_peer_secs); +#endif +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_CCCD, ble_store_config_cccds, &ble_store_config_num_cccds); if (err != ESP_OK) { @@ -552,6 +580,7 @@ ble_nvs_restore_sec_keys(void) } ESP_LOGD(TAG, "ble_store_config_cccds restored %d bonds", ble_store_config_num_cccds); +#endif #if MYNEWT_VAL(ENC_ADV_DATA) err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_EAD, ble_store_config_eads, @@ -606,6 +635,7 @@ ble_nvs_restore_peer_records(void) } #endif +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) int ble_store_config_persist_cccds(void) { int nvs_count, nvs_idx; @@ -636,6 +666,7 @@ int ble_store_config_persist_cccds(void) } return 0; } +#endif #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_config_persist_eads(void) diff --git a/src/nimble/nimble/include/nimble/hci_common.h b/src/nimble/nimble/include/nimble/hci_common.h index 3da5c1f1..3bfb5e62 100644 --- a/src/nimble/nimble/include/nimble/hci_common.h +++ b/src/nimble/nimble/include/nimble/hci_common.h @@ -1949,6 +1949,11 @@ struct ble_hci_ev_le_subev_subrate_change { uint16_t supervision_tmo; } __attribute__((packed)); +#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) +// LE vendor hci event +#define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0 +#endif // (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) + /* Data buffer overflow event */ #define BLE_HCI_EVENT_ACL_BUF_OVERFLOW (0x01) diff --git a/src/nimble/nimble/include/nimble/nimble_opt_auto.h b/src/nimble/nimble/include/nimble/nimble_opt_auto.h index f7c3e4ba..0abb28c8 100644 --- a/src/nimble/nimble/include/nimble/nimble_opt_auto.h +++ b/src/nimble/nimble/include/nimble/nimble_opt_auto.h @@ -77,6 +77,10 @@ extern "C" { #define NIMBLE_BLE_ATT_CLT_READ_MULT \ (MYNEWT_VAL(BLE_GATT_READ_MULT)) +#undef NIMBLE_BLE_ATT_CLT_READ_MULT_VAR +#define NIMBLE_BLE_ATT_CLT_READ_MULT_VAR \ + (MYNEWT_VAL(BLE_GATT_READ_MULT_VAR)) + #undef NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE #define NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE \ (MYNEWT_VAL(BLE_GATT_DISC_ALL_SVCS)) diff --git a/src/nimble/porting/nimble/include/syscfg/syscfg.h b/src/nimble/porting/nimble/include/syscfg/syscfg.h index b321e3d5..53caee6c 100644 --- a/src/nimble/porting/nimble/include/syscfg/syscfg.h +++ b/src/nimble/porting/nimble/include/syscfg/syscfg.h @@ -735,6 +735,10 @@ #define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif +#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR +#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ_UUID #define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/src/nimble/porting/nimble/src/nimble_port.c b/src/nimble/porting/nimble/src/nimble_port.c index 08e2fbc0..572bdc4d 100644 --- a/src/nimble/porting/nimble/src/nimble_port.c +++ b/src/nimble/porting/nimble/src/nimble_port.c @@ -143,7 +143,7 @@ esp_err_t esp_nimble_init(void) */ esp_err_t esp_nimble_deinit(void) { -#if !SOC_ESP_NIMBLE_CONTROLLER +#if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED if(esp_nimble_hci_deinit() != ESP_OK) { ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci deinit failed\n"); @@ -193,6 +193,11 @@ nimble_port_init(void) ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); if (ret != ESP_OK) { + // Deinit to free any memory the controller is using. + if(esp_bt_controller_deinit() != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller deinit failed\n"); + } + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller enable failed\n"); return ret; } @@ -201,7 +206,19 @@ nimble_port_init(void) ret = esp_nimble_init(); if (ret != ESP_OK) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "nimble host init failed\n"); + +#if CONFIG_BT_CONTROLLER_ENABLED + // Disable and deinit controller to free memory + if(esp_bt_controller_disable() != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller disable failed\n"); + } + + if(esp_bt_controller_deinit() != ESP_OK) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller deinit failed\n"); + } +#endif + + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "nimble host init failed\n"); return ret; } diff --git a/src/nimble/porting/npl/freertos/src/npl_os_freertos.c b/src/nimble/porting/npl/freertos/src/npl_os_freertos.c index d246342c..951d5c1c 100644 --- a/src/nimble/porting/npl/freertos/src/npl_os_freertos.c +++ b/src/nimble/porting/npl/freertos/src/npl_os_freertos.c @@ -896,10 +896,9 @@ npl_freertos_callout_deinit(struct ble_npl_callout *co) if(esp_timer_delete(callout->handle)) ESP_LOGW(TAG, "Timer not deleted"); - #else - xTimerDelete(callout->handle, portMAX_DELAY); +#endif #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_co_pool,callout); @@ -907,7 +906,6 @@ npl_freertos_callout_deinit(struct ble_npl_callout *co) free((void *)callout); #endif -#endif co->co = NULL; memset(co, 0, sizeof(struct ble_npl_callout)); }