diff --git a/nimble/host/audio/src/ble_audio_broadcast_source.c b/nimble/host/audio/src/ble_audio_broadcast_source.c index 210536f7e..093a7d104 100644 --- a/nimble/host/audio/src/ble_audio_broadcast_source.c +++ b/nimble/host/audio/src/ble_audio_broadcast_source.c @@ -18,6 +18,7 @@ */ #include "host/ble_uuid.h" +#include "host/ble_hs_hci.h" #include "audio/ble_audio_broadcast_source.h" #include "os/util.h" @@ -140,7 +141,10 @@ ble_audio_broadcast_create(const struct ble_broadcast_create_params *params, return BLE_HS_EALREADY; } - ble_hs_hci_rand(broadcast_id, 3); + rc = ble_hs_hci_util_rand(broadcast_id, 3); + if (rc != 0) { + return rc; + } params->base->broadcast_id = get_le24(broadcast_id); broadcast = os_memblock_get(&ble_audio_broadcast_pool); diff --git a/nimble/host/services/cts/src/ble_svc_cts.c b/nimble/host/services/cts/src/ble_svc_cts.c index 699fc4f71..1af4c84ba 100644 --- a/nimble/host/services/cts/src/ble_svc_cts.c +++ b/nimble/host/services/cts/src/ble_svc_cts.c @@ -121,7 +121,7 @@ int ble_svc_cts_curr_time_validate(struct ble_svc_cts_curr_time curr_time) { curr_time.et_256.d_d_t.d_t.hours > 23 || curr_time.et_256.d_d_t.d_t.minutes > 59 || curr_time.et_256.d_d_t.d_t.seconds > 59 || - curr_time.adjust_reason >> 4 > 0 + (curr_time.adjust_reason >> 4) > 0 ) { return BLE_SVC_CTS_ERR_DATA_FIELD_IGNORED; } diff --git a/nimble/host/services/gap/src/ble_svc_gap.c b/nimble/host/services/gap/src/ble_svc_gap.c index 5d01dadd5..90ff73e54 100644 --- a/nimble/host/services/gap/src/ble_svc_gap.c +++ b/nimble/host/services/gap/src/ble_svc_gap.c @@ -671,7 +671,7 @@ ble_svc_gap_deinit_name(void) void ble_svc_gap_init(void) { -#if NIMBLE_BLE_CONNECT +#if NIMBLE_BLE_CONNECT || MYNEWT_VAL(BLE_STATIC_TO_DYNAMIC) int rc; #endif /* Ensure this function only gets called by sysinit. */ diff --git a/nimble/host/services/htp/src/ble_svc_htp.c b/nimble/host/services/htp/src/ble_svc_htp.c index 5aa73c681..d23e5d16d 100644 --- a/nimble/host/services/htp/src/ble_svc_htp.c +++ b/nimble/host/services/htp/src/ble_svc_htp.c @@ -392,7 +392,7 @@ ble_svc_htp_notify(uint16_t conn_handle, float temp, bool temp_unit) txom = ble_hs_mbuf_from_flat(measurement, sizeof(measurement)); if (!txom) { - return ESP_FAIL; + return BLE_HS_ENOMEM; } rc = ble_gatts_notify_custom(conn_handle, @@ -435,7 +435,7 @@ ble_svc_htp_indicate(uint16_t conn_handle, float temp, bool temp_unit) txom = ble_hs_mbuf_from_flat(measurement, sizeof(measurement)); if (!txom) { - return ESP_FAIL; + return BLE_HS_ENOMEM; } rc = ble_gatts_indicate_custom(conn_handle, diff --git a/nimble/host/services/prox/src/ble_svc_prox.c b/nimble/host/services/prox/src/ble_svc_prox.c index 7be504b7a..be4789f61 100644 --- a/nimble/host/services/prox/src/ble_svc_prox.c +++ b/nimble/host/services/prox/src/ble_svc_prox.c @@ -29,7 +29,7 @@ typedef struct { uint8_t _ble_svc_prox_link_loss_alert; int8_t _ble_svc_prox_alert; - uint8_t _ble_svc_prox_tx_pwr_lvl; + int8_t _ble_svc_prox_tx_pwr_lvl; bool _ble_svc_prox_alert_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; TaskHandle_t _ble_prox_task_handle; } ble_svc_prox_ctx_t; diff --git a/nimble/host/services/ras/src/ble_svc_ras.c b/nimble/host/services/ras/src/ble_svc_ras.c index 3c4384c8b..1ccac207b 100644 --- a/nimble/host/services/ras/src/ble_svc_ras.c +++ b/nimble/host/services/ras/src/ble_svc_ras.c @@ -115,6 +115,9 @@ ble_svc_ras_ensure_ctx_init() { if (ble_svc_ras_ctx == NULL) { ble_svc_ras_ctx = nimble_platform_mem_calloc(1, sizeof(ble_svc_ras_ctx_t)); + if (ble_svc_ras_ctx == NULL) { + return; + } } reset_ranging_buffer(); @@ -379,9 +382,11 @@ static int gatt_svr_chr_access_ras_val(uint16_t conn_handle, uint16_t attr_handl sizeof(ble_svc_ras_rt_rd_val), sizeof(ble_svc_ras_rt_rd_val), &ble_svc_ras_rt_rd_val, NULL); - ble_gatts_chr_updated(attr_handle); - MODLOG_DFLT(INFO, "Notification/Indication scheduled for " - "all subscribed peers.\n"); + if (rc == 0) { + ble_gatts_chr_updated(attr_handle); + MODLOG_DFLT(INFO, "Notification/Indication scheduled for " + "all subscribed peers.\n"); + } return rc; } else if (attr_handle == ble_svc_ras_od_rd_val_handle) { /* Ensure the buffer is allocated before writing to it */ @@ -456,18 +461,22 @@ static int gatt_svr_chr_access_ras_val(uint16_t conn_handle, uint16_t attr_handl sizeof(ble_svc_ras_rd_val), sizeof(ble_svc_ras_rd_val), &ble_svc_ras_rd_val, NULL); - ble_gatts_chr_updated(attr_handle); - MODLOG_DFLT(INFO, "Notification/Indication scheduled for " - "all subscribed peers.\n"); + if (rc == 0) { + ble_gatts_chr_updated(attr_handle); + MODLOG_DFLT(INFO, "Notification/Indication scheduled for " + "all subscribed peers.\n"); + } return rc; } else if (attr_handle == ble_svc_ras_rd_ov_val_handle) { rc = gatt_svr_write(ctxt->om, sizeof(ble_svc_ras_rd_ov_val), sizeof(ble_svc_ras_rd_ov_val), &ble_svc_ras_rd_ov_val, NULL); - ble_gatts_chr_updated(attr_handle); - MODLOG_DFLT(INFO, "Notification/Indication scheduled for " - "all subscribed peers.\n"); + if (rc == 0) { + ble_gatts_chr_updated(attr_handle); + MODLOG_DFLT(INFO, "Notification/Indication scheduled for " + "all subscribed peers.\n"); + } return rc; } @@ -529,6 +538,7 @@ void ble_gatts_store_ranging_data(struct ble_cs_event ranging_subevent) { buf->ranging_data.ranging_header.antenna_paths_mask = (num_paths > 0) ? ((1u << num_paths) - 1) : 0; uint16_t max_subevent_data = BLE_RAS_PROCEDURE_MEM - sizeof(struct ranging_header); + uint16_t saved_cursor = buf->subevent_cursor; if (buf->subevent_cursor + sizeof(struct subevent_header) > max_subevent_data) { MODLOG_DFLT(ERROR, "Ranging buffer overflow on subevent header\n"); @@ -554,6 +564,7 @@ void ble_gatts_store_ranging_data(struct ble_cs_event ranging_subevent) { if (buf->subevent_cursor + BLE_RAS_STEP_MODE_LEN + step->data_len > max_subevent_data) { MODLOG_DFLT(ERROR, "Ranging buffer overflow on step data\n"); + buf->subevent_cursor = saved_cursor; return; } diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index d973cdc3e..3e8cbb1e6 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -1005,6 +1005,7 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle, uint16_t cid, if (rsp == NULL) { *att_err = BLE_ATT_ERR_INSUFFICIENT_RES; rc = BLE_HS_ENOMEM; + txom = NULL; goto done; } @@ -1318,6 +1319,7 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, uint16_t cid, if (buf == NULL) { *out_att_err = BLE_ATT_ERR_INSUFFICIENT_RES; rc = BLE_HS_ENOMEM; + txom = NULL; goto done; } @@ -1493,6 +1495,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid, *att_err = BLE_ATT_ERR_INSUFFICIENT_RES; *err_handle = 0; rc = BLE_HS_ENOMEM; + txom = NULL; goto done; } @@ -1997,13 +2000,6 @@ ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, uint16_t cid, rc = BLE_HS_ENOMEM; goto done; } - if (tuple_len != 0) { - rc = os_mbuf_appendfrom(txom, tmp, 0, tuple_len); - if (rc != 0) { - *err_handle = handle; - goto done; - } - } } if (tuple_len != 0) { @@ -2193,6 +2189,7 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, uint16_t cid, if (rsp == NULL) { *att_err = BLE_ATT_ERR_INSUFFICIENT_RES; rc = BLE_HS_ENOMEM; + txom = NULL; goto done; } diff --git a/nimble/host/src/ble_cs.c b/nimble/host/src/ble_cs.c index e8fe12a63..b7d559e6a 100644 --- a/nimble/host/src/ble_cs.c +++ b/nimble/host/src/ble_cs.c @@ -224,18 +224,19 @@ static int ble_cs_call_event_cb(struct ble_cs_event *event) { int rc; + +#if MYNEWT_VAL(BLE_STATIC_TO_DYNAMIC) + /* After deinit, leftover HCI events must not re-allocate CS state. */ + if (cs_state_ptr == NULL) { + return 0; + } +#endif + ble_hs_lock(); ble_cs_event_fn *cb = cs_state.cb; void *cb_arg = cs_state.cb_arg; ble_hs_unlock(); -#if MYNEWT_VAL(BLE_STATIC_TO_DYNAMIC) - rc = ble_cs_state_ensure_init(); - if (rc != 0) { - return rc; - } -#endif - if (cb != NULL) { rc = cb(event, cb_arg); } else { @@ -965,6 +966,12 @@ ble_hs_hci_evt_le_cs_subevent_result(uint8_t subevent, const void *data, int steps_remaining = 0; int step_size = 0; + if (data == NULL || len < sizeof(*event)) { + BLE_HS_LOG(ERROR, "%s invalid length, rc=%d\n", + __func__, BLE_HS_ECONTROLLER); + return BLE_HS_ECONTROLLER; + } + expected_len += sizeof(*event); steps_remaining = event->num_steps_reported; step_ptr = (void *)event->steps; @@ -1089,7 +1096,7 @@ ble_cs_initiator_procedure_start(const struct ble_cs_initiator_procedure_start_p cmd.conn_handle = params->conn_handle; rc = ble_cs_rd_rem_supp_cap(&cmd); if (rc) { - BLE_HS_LOG(DEBUG, "Failed to read local supported CS capabilities," + BLE_HS_LOG(DEBUG, "Failed to read remote supported CS capabilities, " "err %d", rc); } diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 32d1fd1cd..b528958d5 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -3102,6 +3102,11 @@ ble_gap_rx_big_sync_estab(const struct ble_hci_ev_le_subev_big_sync_established { struct ble_gap_event event; + if (ev->num_bis > MYNEWT_VAL(BLE_ISO_BIS_PER_BIG)) { + BLE_HS_LOG(ERROR, "Invalid BIG sync BIS count: %u\n", ev->num_bis); + return; + } + memset(&event, 0, sizeof(event)); event.type = BLE_GAP_EVENT_BIG_SYNC_ESTAB; @@ -3326,7 +3331,7 @@ ble_gap_rx_frame_space_update_complete(const struct ble_hci_ev_le_subev_frame_sp #if MYNEWT_VAL(BLE_UTP_OTA) void -ble_gap_rx_utp_receive(const struct ble_hci_ev_le_subev_utp_receive *ev, uint8_t len) +ble_gap_rx_utp_receive(const struct ble_hci_ev_le_subev_utp_receive *ev, unsigned int len) { struct ble_gap_event event; const uint8_t *data_ptr; @@ -4632,11 +4637,29 @@ ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used { #if NIMBLE_BLE_CONNECT struct ble_hs_conn *conn; + bool conn_found; + bool is_master; int rc; ble_hs_lock(); conn = ble_hs_conn_find(le16toh(ev->conn_handle)); + conn_found = conn != NULL; + if (conn_found) { + is_master = conn->bhc_flags & BLE_HS_CONN_F_MASTER; + if (ev->status == 0) { +#if MYNEWT_VAL(BT_NIMBLE_MEM_OPTIMIZATION) + conn->supported_feat = !!(get_le32(ev->features) & BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST); +#else + conn->supported_feat = get_le32(ev->features); +#endif + } + if (!is_master) { + conn->slave_conn = 1; + } + } else { + is_master = false; + } ble_hs_unlock(); @@ -4648,30 +4671,15 @@ ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used return; } - if ((conn != NULL) && (conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { - if (ev->status == 0) { -#if MYNEWT_VAL(BT_NIMBLE_MEM_OPTIMIZATION) - conn->supported_feat = !!(get_le32(ev->features) & BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST); -#else - conn->supported_feat = get_le32(ev->features); -#endif - } + if (conn_found && is_master) { rc = ble_gap_rd_rem_ver_tx(le16toh(ev->conn_handle)); if (rc != 0) { ble_gap_event_connect_call(ev->conn_handle, 0); } } else { - if (conn != NULL) { - if (ev->status == 0) { -#if MYNEWT_VAL(BT_NIMBLE_MEM_OPTIMIZATION) - conn->supported_feat = !!(get_le32(ev->features) & BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST); -#else - conn->supported_feat = get_le32(ev->features); -#endif - } + if (conn_found) { /* Connection is established regardless of feature read result; * pass 0 to avoid falsely reporting a connection failure. */ - conn->slave_conn = 1; ble_gap_event_connect_call(ev->conn_handle, 0); } } @@ -8248,9 +8256,9 @@ ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents, struct periodic_adv_subevents *subevents; uint16_t opcode; uint16_t subev_data_len; - uint8_t buf_size; + uint16_t buf_size; uint8_t param_size; - uint8_t buf_offset; + uint16_t buf_offset; uint32_t cmd_len; int rc; @@ -8677,6 +8685,10 @@ ble_gap_set_conn_cte_recv_param(uint16_t conn_handle, uint8_t sampling_enable, c int ble_gap_set_conn_cte_transmit_param(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, const uint8_t *antenna_ids) { + if (switching_pattern_len > 75) { + return BLE_HS_EINVAL; + } + uint8_t buf[sizeof(struct ble_hci_le_set_conn_cte_tx_params_cp) + switching_pattern_len]; struct ble_hci_le_set_conn_cte_tx_params_cp *cmd = (void *)buf; struct ble_hci_le_set_conn_cte_tx_params_rp rsp; @@ -13286,9 +13298,10 @@ int ble_gap_config_ext_scan_adi_filter(uint8_t enable, uint8_t did_filter, uint8 struct ble_gap_adi_filter_entry *filter_list[]) { uint8_t vs_cmd[64]; + size_t offset; memset(vs_cmd, 0x0, sizeof(vs_cmd)); - if (sid_cnt > 15) { + if (sid_cnt > 15 || (sid_cnt > 0 && filter_list == NULL)) { BLE_HS_LOG(ERROR, "%s rc=%d\n", __func__, BLE_HS_EINVAL); return BLE_HS_EINVAL; } @@ -13296,10 +13309,32 @@ int ble_gap_config_ext_scan_adi_filter(uint8_t enable, uint8_t did_filter, uint8 vs_cmd[0] = enable; vs_cmd[1] = did_filter; vs_cmd[2] = sid_cnt; - memcpy(&vs_cmd[3], filter_list, sid_cnt * sizeof(struct ble_gap_adi_filter_entry *)); + offset = 3; + for (int i = 0; i < sid_cnt; i++) { + struct ble_gap_adi_filter_entry *entry = filter_list[i]; + size_t entry_len; + + if (entry == NULL) { + return BLE_HS_EINVAL; + } + + entry_len = sizeof(entry->sid) + sizeof(entry->did_cnt) + + entry->did_cnt * sizeof(entry->did[0]); + if (offset + entry_len > sizeof(vs_cmd)) { + return BLE_HS_EINVAL; + } + + vs_cmd[offset++] = entry->sid; + put_le16(&vs_cmd[offset], entry->did_cnt); + offset += sizeof(entry->did_cnt); + for (int j = 0; j < entry->did_cnt; j++) { + put_le16(&vs_cmd[offset], entry->did[j]); + offset += sizeof(entry->did[j]); + } + } return ble_hs_hci_send_vs_cmd(BLE_HCI_OCF_VS_SET_SCAN_SID, - &vs_cmd, sid_cnt * sizeof(struct ble_gap_adi_filter_entry *) + 3, NULL, 0); + &vs_cmd, offset, NULL, 0); } #endif // MYNEWT_VAL(BLE_SCAN_ALLOW_ENH_ADI_FILTER) #endif diff --git a/nimble/host/src/ble_gap_priv.h b/nimble/host/src/ble_gap_priv.h index 77b55c13d..d008db0b8 100644 --- a/nimble/host/src/ble_gap_priv.h +++ b/nimble/host/src/ble_gap_priv.h @@ -224,7 +224,7 @@ void ble_gap_rx_frame_space_update_complete(const struct ble_hci_ev_le_subev_fra #endif #if MYNEWT_VAL(BLE_UTP_OTA) -void ble_gap_rx_utp_receive(const struct ble_hci_ev_le_subev_utp_receive *ev, uint8_t len); +void ble_gap_rx_utp_receive(const struct ble_hci_ev_le_subev_utp_receive *ev, unsigned int len); #endif #ifdef __cplusplus diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index ccc0493d0..2262a672b 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -264,6 +264,7 @@ extern struct ble_gatts_aware_state ble_gatts_conn_aware_states[MYNEWT_VAL(BLE_S /*** @misc. */ int ble_gatts_conn_can_alloc(void); int ble_gatts_conn_init(struct ble_gatts_conn *gatts_conn); +void ble_gatts_conn_deinit(struct ble_gatts_conn *gatts_conn); int ble_gatts_init(void); #if MYNEWT_VAL(BLE_GATT_CACHING) int ble_gattc_cache_conn_init(); diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 0165c6cf1..17e281857 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -5799,7 +5799,7 @@ ble_gatts_notify_multiple_custom(uint16_t conn_handle, } for (i = 0; i < chr_count; i++) { - if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu && cur_chr_cnt < 2) { + if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) + 4 > mtu && cur_chr_cnt < 2) { /* Flush any previously buffered characteristic first to maintain ordering */ if (cur_chr_cnt == 1) { /* Strip the 4-byte handle+length header and send as a standard @@ -5827,7 +5827,7 @@ ble_gatts_notify_multiple_custom(uint16_t conn_handle, goto done; } continue; - } else if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu) { + } else if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) + 4 > mtu) { rc = ble_att_clt_tx_multi_notify(conn_handle, txom); txom = NULL; if (rc != 0) { diff --git a/nimble/host/src/ble_gattc_cache.c b/nimble/host/src/ble_gattc_cache.c index fe0f34863..865641974 100644 --- a/nimble/host/src/ble_gattc_cache.c +++ b/nimble/host/src/ble_gattc_cache.c @@ -261,6 +261,7 @@ ble_gattc_cacheReset(ble_addr_t *addr) /* Reduced the number address counter also */ cache_env->num_addr--; + memset(&cache_env->cache_addr[cache_env->num_addr], 0, sizeof(cache_addr_info_t)); /* Update addr list to storage flash */ if (cache_env->num_addr > 0) { @@ -628,6 +629,11 @@ ble_gattc_cache_save(struct ble_gattc_cache_conn *peer, size_t num_attr) uint8_t index = INVALID_ADDR_NUM; struct ble_gatt_nv_attr *nv_attr; + if (num_attr == 0) { + BLE_HS_LOG(INFO, "%s() skipped empty cache save", __func__); + return; + } + nv_attr = (struct ble_gatt_nv_attr *) nimble_platform_mem_calloc(1,num_attr * sizeof(ble_gatt_nv_attr)); if (nv_attr == NULL) { BLE_HS_LOG(ERROR, "Failed to allocate memory to nv_attr"); @@ -942,6 +948,7 @@ ble_gattc_cache_load(ble_addr_t peer_addr) cache_index = ble_gattc_cache_find_addr(peer_addr); if (cache_index == INVALID_ADDR_NUM) { BLE_HS_LOG(ERROR, "Address not found in cache"); + cacheClose(peer_addr); return BLE_HS_ENOENT; } ble_gattc_cache_conn_load_hash(cache_env->cache_addr[cache_index].addr, diff --git a/nimble/host/src/ble_gattc_cache_conn.c b/nimble/host/src/ble_gattc_cache_conn.c index 57f205a28..3aa4d61a3 100644 --- a/nimble/host/src/ble_gattc_cache_conn.c +++ b/nimble/host/src/ble_gattc_cache_conn.c @@ -1818,7 +1818,7 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) struct ble_gattc_cache_conn_op *op; struct ble_hs_conn *hs_conn; const struct ble_gattc_cache_conn_chr *chr; - bool bonded; + bool bonded = false; peer->disc_prev_chr_val = 0; if (rc == 0) { @@ -1831,18 +1831,21 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) ble_addr_t peer_addr; ble_hs_lock(); hs_conn = ble_hs_conn_find(peer->conn_handle); - BLE_HS_DBG_ASSERT(hs_conn != NULL); - bonded = hs_conn->bhc_sec_state.bonded; - peer_addr = hs_conn->bhc_peer_addr; /* Copy address while holding lock */ - ble_hs_unlock(); + if (hs_conn == NULL) { + ble_hs_unlock(); + } else { + bonded = hs_conn->bhc_sec_state.bonded; + peer_addr = hs_conn->bhc_peer_addr; /* Copy address while holding lock */ + ble_hs_unlock(); - chr = ble_gattc_cache_conn_chr_find_uuid(peer, - BLE_UUID16_DECLARE(BLE_GATT_SVC_UUID16), - BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)); - if (bonded || chr != NULL) { - /* persist the cache */ - ble_gattc_cacheReset(&peer_addr); - ble_gattc_cache_conn_cache_peer(peer); /* TODO */ + chr = ble_gattc_cache_conn_chr_find_uuid(peer, + BLE_UUID16_DECLARE(BLE_GATT_SVC_UUID16), + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)); + if (bonded || chr != NULL) { + /* persist the cache */ + ble_gattc_cacheReset(&peer_addr); + ble_gattc_cache_conn_cache_peer(peer); /* TODO */ + } } } else { peer->cache_state = CACHE_INVALID; diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c index 4d691cedc..bc66ae6a7 100644 --- a/nimble/host/src/ble_gatts.c +++ b/nimble/host/src/ble_gatts.c @@ -663,7 +663,10 @@ ble_gatts_val_access(uint16_t conn_handle, uint16_t attr_handle, attr_len = OS_MBUF_PKTLEN(gatt_ctxt->om) - initial_len - offset; if (attr_len >= 0) { if (new_om) { - os_mbuf_appendfrom(*om, gatt_ctxt->om, offset, attr_len); + rc = os_mbuf_appendfrom(*om, gatt_ctxt->om, offset, attr_len); + if (rc != 0) { + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + } } } else { rc = BLE_ATT_ERR_INVALID_OFFSET; @@ -2563,6 +2566,35 @@ ble_gatts_rx_indicate_ack(uint16_t conn_handle, uint16_t chr_val_handle) return 0; } +void +ble_gatts_conn_deinit(struct ble_gatts_conn *gatts_conn) +{ +#if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) + struct ble_gatts_clt_cfg *clt_cfg; + + if (gatts_conn == NULL) { + return; + } + + while ((clt_cfg = STAILQ_FIRST(&gatts_conn->clt_cfgs)) != NULL) { + STAILQ_REMOVE_HEAD(&gatts_conn->clt_cfgs, next); + ble_gatts_clt_cfg_free(clt_cfg); + } + gatts_conn->num_clt_cfgs = 0; +#else + int rc; + + if (gatts_conn == NULL || gatts_conn->clt_cfgs == NULL) { + return; + } + + rc = os_memblock_put(&ble_gatts_clt_cfg_pool, gatts_conn->clt_cfgs); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + gatts_conn->clt_cfgs = NULL; + gatts_conn->num_clt_cfgs = 0; +#endif +} + void ble_gatts_chr_updated(uint16_t chr_val_handle) { diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c index 963c6e9a9..03d6d8cb8 100644 --- a/nimble/host/src/ble_hs.c +++ b/nimble/host/src/ble_hs.c @@ -293,8 +293,10 @@ ble_hs_lock_nested(void) counter_lock++; ble_hs_mutex_locked = 1; ble_hs_task_handle = xTaskGetCurrentTaskHandle(); - ble_hs_task_handles[ble_hs_task_handle_index] = xTaskGetCurrentTaskHandle(); - ble_hs_task_handle_index++; + if (ble_hs_task_handle_index < MAX_NESTED_LOCKS) { + ble_hs_task_handles[ble_hs_task_handle_index] = xTaskGetCurrentTaskHandle(); + ble_hs_task_handle_index++; + } #endif BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); } @@ -317,10 +319,15 @@ ble_hs_unlock_nested(void) if (counter_lock == 0) { ble_hs_mutex_locked = 0; } - if (ble_hs_task_handles[ble_hs_task_handle_index - 1] == xTaskGetCurrentTaskHandle()) { + if (ble_hs_task_handle_index > 0 && + ble_hs_task_handles[ble_hs_task_handle_index - 1] == xTaskGetCurrentTaskHandle()) { ble_hs_task_handle_index--; ble_hs_task_handles[ble_hs_task_handle_index] = NULL; - ble_hs_task_handle = ble_hs_task_handles[ble_hs_task_handle_index -1]; + if (ble_hs_task_handle_index > 0) { + ble_hs_task_handle = ble_hs_task_handles[ble_hs_task_handle_index - 1]; + } else { + ble_hs_task_handle = NULL; + } } } #endif @@ -928,6 +935,10 @@ ble_hs_init(void) ble_hs_state_ctx = nimble_platform_mem_calloc(1, sizeof(*ble_hs_state_ctx)); if (!ble_hs_state_ctx) { MODLOG_DFLT(ERROR, "Failed to allocate ble_hs_state_ctx (%zu bytes)\n", sizeof(*ble_hs_state_ctx)); + nimble_platform_mem_free(ble_hs_ctx->hci_os_event_buf); + ble_hs_ctx->hci_os_event_buf = NULL; + nimble_platform_mem_free(ble_hs_ctx); + ble_hs_ctx = NULL; return; } } diff --git a/nimble/host/src/ble_hs_adv.c b/nimble/host/src/ble_hs_adv.c index 5c8700ede..3bce5af83 100644 --- a/nimble/host/src/ble_hs_adv.c +++ b/nimble/host/src/ble_hs_adv.c @@ -42,6 +42,9 @@ typedef struct{ ble_uuid16_t _ble_hs_adv_uuids16[BLE_HS_ADV_MAX_FIELD_SZ / 2]; ble_uuid32_t _ble_hs_adv_uuids32[BLE_HS_ADV_MAX_FIELD_SZ / 4]; ble_uuid128_t _ble_hs_adv_uuids128[BLE_HS_ADV_MAX_FIELD_SZ / 16]; + ble_uuid16_t _ble_hs_adv_sol_uuids16[BLE_HS_ADV_MAX_FIELD_SZ / 2]; + ble_uuid32_t _ble_hs_adv_sol_uuids32[BLE_HS_ADV_MAX_FIELD_SZ / 4]; + ble_uuid128_t _ble_hs_adv_sol_uuids128[BLE_HS_ADV_MAX_FIELD_SZ / 16]; }ble_hs_adv_uuids_ctx; static ble_hs_adv_uuids_ctx *ble_hs_adv_uuids; @@ -49,6 +52,9 @@ static ble_hs_adv_uuids_ctx *ble_hs_adv_uuids; #define ble_hs_adv_uuids16 (ble_hs_adv_uuids->_ble_hs_adv_uuids16) #define ble_hs_adv_uuids32 (ble_hs_adv_uuids->_ble_hs_adv_uuids32) #define ble_hs_adv_uuids128 (ble_hs_adv_uuids->_ble_hs_adv_uuids128) +#define ble_hs_adv_sol_uuids16 (ble_hs_adv_uuids->_ble_hs_adv_sol_uuids16) +#define ble_hs_adv_sol_uuids32 (ble_hs_adv_uuids->_ble_hs_adv_sol_uuids32) +#define ble_hs_adv_sol_uuids128 (ble_hs_adv_uuids->_ble_hs_adv_sol_uuids128) /* ble_hs_adv_parse_fields is intentionally non-reentrant; * NimBLE runs in a single host task - concurrent calls violate the threading model */ @@ -56,6 +62,11 @@ static ble_hs_adv_uuids_ctx *ble_hs_adv_uuids; static ble_uuid16_t ble_hs_adv_uuids16[BLE_HS_ADV_MAX_FIELD_SZ / 2]; static ble_uuid32_t ble_hs_adv_uuids32[BLE_HS_ADV_MAX_FIELD_SZ / 4]; static ble_uuid128_t ble_hs_adv_uuids128[BLE_HS_ADV_MAX_FIELD_SZ / 16]; +#if MYNEWT_VAL(BLE_EXTRA_ADV_FIELDS) +static ble_uuid16_t ble_hs_adv_sol_uuids16[BLE_HS_ADV_MAX_FIELD_SZ / 2]; +static ble_uuid32_t ble_hs_adv_sol_uuids32[BLE_HS_ADV_MAX_FIELD_SZ / 4]; +static ble_uuid128_t ble_hs_adv_sol_uuids128[BLE_HS_ADV_MAX_FIELD_SZ / 16]; +#endif #endif static int @@ -844,6 +855,86 @@ ble_hs_adv_parse_uuids128(struct ble_hs_adv_fields *adv_fields, return 0; } +#if MYNEWT_VAL(BLE_EXTRA_ADV_FIELDS) +static int +ble_hs_adv_parse_sol_uuids16(struct ble_hs_adv_fields *adv_fields, + const uint8_t *data, uint8_t data_len) +{ + ble_uuid_any_t uuid; + int uuid_cnt; + + if (data_len % 2 != 0) { + return BLE_HS_EBADDATA; + } + + uuid_cnt = data_len / 2; + if (uuid_cnt > BLE_HS_ADV_MAX_FIELD_SZ / sizeof(uint16_t)) { + return BLE_HS_EMSGSIZE; + } + + adv_fields->sol_uuids16 = ble_hs_adv_sol_uuids16; + adv_fields->sol_num_uuids16 = uuid_cnt; + for (int i = 0; i < uuid_cnt; i++) { + ble_uuid_init_from_buf(&uuid, data + i * 2, 2); + ble_hs_adv_sol_uuids16[i] = uuid.u16; + } + + return 0; +} + +static int +ble_hs_adv_parse_sol_uuids32(struct ble_hs_adv_fields *adv_fields, + const uint8_t *data, uint8_t data_len) +{ + ble_uuid_any_t uuid; + int uuid_cnt; + + if (data_len % 4 != 0) { + return BLE_HS_EBADDATA; + } + + uuid_cnt = data_len / 4; + if (uuid_cnt > BLE_HS_ADV_MAX_FIELD_SZ / sizeof(uint32_t)) { + return BLE_HS_EMSGSIZE; + } + + adv_fields->sol_uuids32 = ble_hs_adv_sol_uuids32; + adv_fields->sol_num_uuids32 = uuid_cnt; + for (int i = 0; i < uuid_cnt; i++) { + ble_uuid_init_from_buf(&uuid, data + i * 4, 4); + ble_hs_adv_sol_uuids32[i] = uuid.u32; + } + + return 0; +} + +static int +ble_hs_adv_parse_sol_uuids128(struct ble_hs_adv_fields *adv_fields, + const uint8_t *data, uint8_t data_len) +{ + ble_uuid_any_t uuid; + int uuid_cnt; + + if (data_len % 16 != 0) { + return BLE_HS_EBADDATA; + } + + uuid_cnt = data_len / 16; + if (uuid_cnt > BLE_HS_ADV_MAX_FIELD_SZ / sizeof(ble_uuid128_t)) { + return BLE_HS_EMSGSIZE; + } + + adv_fields->sol_uuids128 = ble_hs_adv_sol_uuids128; + adv_fields->sol_num_uuids128 = uuid_cnt; + for (int i = 0; i < uuid_cnt; i++) { + ble_uuid_init_from_buf(&uuid, data + i * 16, 16); + ble_hs_adv_sol_uuids128[i] = uuid.u128; + } + + return 0; +} +#endif + #if MYNEWT_VAL(BLE_STATIC_TO_DYNAMIC) static int ble_hs_adv_uuids_alloc(void) @@ -996,14 +1087,14 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields, #if MYNEWT_VAL(BLE_EXTRA_ADV_FIELDS) case BLE_HS_ADV_TYPE_SOL_UUIDS16: - rc = ble_hs_adv_parse_uuids16(adv_fields, data, data_len); + rc = ble_hs_adv_parse_sol_uuids16(adv_fields, data, data_len); if (rc != 0) { return rc; } break; case BLE_HS_ADV_TYPE_SOL_UUIDS128: - rc = ble_hs_adv_parse_uuids128(adv_fields, data, data_len); + rc = ble_hs_adv_parse_sol_uuids128(adv_fields, data, data_len); if (rc != 0) { return rc; } @@ -1096,7 +1187,7 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields, #if MYNEWT_VAL(BLE_EXTRA_ADV_FIELDS) case BLE_HS_ADV_TYPE_SOL_UUIDS32: - rc = ble_hs_adv_parse_uuids32(adv_fields, data, data_len); + rc = ble_hs_adv_parse_sol_uuids32(adv_fields, data, data_len); if (rc != 0) { return rc; } diff --git a/nimble/host/src/ble_hs_conn.c b/nimble/host/src/ble_hs_conn.c index caf02bcdf..04759f07f 100644 --- a/nimble/host/src/ble_hs_conn.c +++ b/nimble/host/src/ble_hs_conn.c @@ -313,6 +313,7 @@ ble_hs_conn_free(struct ble_hs_conn *conn) #if MYNEWT_VAL(BLE_GATTS) ble_att_svr_prep_clear(&conn->bhc_att_svr.basc_prep_list); + ble_gatts_conn_deinit(&conn->bhc_gatt_svr); #endif while ((chan = SLIST_FIRST(&conn->bhc_channels)) != NULL) { diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index 7f9f9db0d..3d31fcaaa 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -2226,7 +2226,7 @@ ble_hs_hci_evt_le_utp_receive(uint8_t subevent, const void *data, unsigned int l if (len < sizeof(*ev) || len != (sizeof(*ev) + ev->len)) { return BLE_HS_EBADDATA; } - ble_gap_rx_utp_receive(data, (uint8_t)len); + ble_gap_rx_utp_receive(data, len); return 0; } #endif diff --git a/nimble/host/src/ble_hs_resolv.c b/nimble/host/src/ble_hs_resolv.c index 387290429..cb187b40b 100644 --- a/nimble/host/src/ble_hs_resolv.c +++ b/nimble/host/src/ble_hs_resolv.c @@ -900,7 +900,7 @@ ble_hs_resolv_list_rmv(uint8_t addr_type, uint8_t *ident_addr) if (position) { memmove(&g_ble_hs_resolv_list[position], &g_ble_hs_resolv_list[position + 1], - (g_ble_hs_resolv_data.rl_cnt - position) * sizeof (struct + (g_ble_hs_resolv_data.rl_cnt - position - 1) * sizeof (struct ble_hs_resolv_entry)); --g_ble_hs_resolv_data.rl_cnt; diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index 6f29163c9..e0c651cd6 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -973,7 +973,7 @@ ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle, } rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data; - ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0); + ble_l2cap_sig_coc_reconfig_cb(proc, (le16toh(rsp->result) > 0) ? BLE_HS_EREJECT : 0); done: if (rc != 0) { @@ -2137,6 +2137,7 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list) if (time_diff < next_exp_in) { next_exp_in = time_diff; } + prev = proc; } proc = next; diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index 6d985e6d1..3b5b4455f 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -161,8 +161,8 @@ ble_sm_state_dispatch[BLE_SM_PROC_STATE_CNT] = { static os_membuf_t *ble_sm_proc_mem = NULL; #else static os_membuf_t ble_sm_proc_mem[ - OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SM_MAX_PROCS), - sizeof (struct ble_sm_proc)) + OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_SM_MAX_PROCS), + sizeof(struct ble_sm_proc)) / sizeof(os_membuf_t) ]; #endif @@ -3869,10 +3869,9 @@ ble_sm_init(void) } #if !MYNEWT_VAL(MP_RUNTIME_ALLOC) - size_t proc_mem_size = OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SM_MAX_PROCS), sizeof(struct ble_sm_proc)); - if (!ble_sm_proc_mem) { - ble_sm_proc_mem = nimble_platform_mem_calloc(1,proc_mem_size * sizeof(os_membuf_t)); + ble_sm_proc_mem = nimble_platform_mem_calloc(1, + OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_SM_MAX_PROCS), sizeof(struct ble_sm_proc))); if (!ble_sm_proc_mem) { /* free the allocated memory */ nimble_platform_mem_free(ble_sm_ctx); @@ -4128,7 +4127,7 @@ ble_sm_csis_generate_rsi(const uint8_t *sirk, uint8_t *out) int rc; do { - rc = ble_hs_hci_rand(prand, 3); + rc = ble_hs_hci_util_rand(prand, 3); if (rc != 0) { return rc; } diff --git a/porting/nimble/src/hal_uart.c b/porting/nimble/src/hal_uart.c index ac58952ce..da2927b75 100644 --- a/porting/nimble/src/hal_uart.c +++ b/porting/nimble/src/hal_uart.c @@ -60,6 +60,14 @@ static void hci_uart_rx_task(void *pvParameters) { uart_event_t event; uint8_t* dtmp = (uint8_t*) nimble_platform_mem_calloc(1,RD_BUF_SIZE); + if (dtmp == NULL) { + ESP_LOGE(TAG, "Failed to allocate UART RX buffer"); + hci_uart.uart_opened = false; + hci_uart.rx_task_handler = NULL; + vTaskDelete(NULL); + return; + } + while(hci_uart.uart_opened) { //Waiting for UART event. if(xQueueReceive(hci_uart.evt_queue, (void * )&event, (TickType_t)portMAX_DELAY)) { @@ -122,12 +130,40 @@ static void hci_uart_rx_task(void *pvParameters) int hal_uart_config(int uart, int32_t speed, uint8_t data_bits, uint8_t stop_bits, enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl) { + uart_parity_t uart_parity; + uart_hw_flowcontrol_t uart_flow_ctrl; + + switch (parity) { + case HAL_UART_PARITY_NONE: + uart_parity = UART_PARITY_DISABLE; + break; + case HAL_UART_PARITY_ODD: + uart_parity = UART_PARITY_ODD; + break; + case HAL_UART_PARITY_EVEN: + uart_parity = UART_PARITY_EVEN; + break; + default: + return -1; + } + + switch (flow_ctl) { + case HAL_UART_FLOW_CTL_NONE: + uart_flow_ctrl = UART_HW_FLOWCTRL_DISABLE; + break; + case HAL_UART_FLOW_CTL_RTS_CTS: + uart_flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS; + break; + default: + return -1; + } + uart_config_t uart_cfg = { .baud_rate = speed, .data_bits = data_bits, - .parity = parity, + .parity = uart_parity, .stop_bits = stop_bits, - .flow_ctrl = flow_ctl, + .flow_ctrl = uart_flow_ctrl, .source_clk = UART_SCLK_DEFAULT, }; hci_uart.port = uart; @@ -147,7 +183,14 @@ int hal_uart_config(int uart, int32_t speed, uint8_t data_bits, uint8_t stop_bit ESP_LOGI(TAG, "set baud_rate:%d.\n", speed); //Create a task to handler UART event from ISR - xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, &hci_uart.rx_task_handler); + if (xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, + &hci_uart.rx_task_handler) != pdPASS) { + ESP_LOGE(TAG, "Failed to create UART RX task"); + hci_uart.uart_opened = false; + hci_uart.rx_task_handler = NULL; + uart_driver_delete(uart); + return -1; + } return 0; } diff --git a/porting/nimble/src/os_mempool.c b/porting/nimble/src/os_mempool.c index 2acb29771..9b5006f4b 100644 --- a/porting/nimble/src/os_mempool.c +++ b/porting/nimble/src/os_mempool.c @@ -567,9 +567,12 @@ os_memblock_get(struct os_mempool *mp) bool need_alloc = false; void *allocated_block; uint32_t alloc_size; + uint16_t prev_min_free; OS_ENTER_CRITICAL(sr); + prev_min_free = mp->mp_min_free; + if (mp->mp_num_free) { #if MYNEWT_VAL(MP_BLOCK_REUSED) if (mp->mp_flags & OS_MEMPOOL_F_REUSED) { @@ -615,6 +618,7 @@ os_memblock_get(struct os_mempool *mp) // Should not happen OS_ENTER_CRITICAL(sr); mp->mp_num_free++; + mp->mp_min_free = prev_min_free; /* apply the changes: restore pre-incremented mp_alloc_blocks on * malloc failure to keep counter consistent with actual allocations */ #if MYNEWT_VAL(MP_BLOCK_REUSED) diff --git a/porting/npl/freertos/src/npl_os_freertos.c b/porting/npl/freertos/src/npl_os_freertos.c index df8447e00..bec7c9ea3 100644 --- a/porting/npl/freertos/src/npl_os_freertos.c +++ b/porting/npl/freertos/src/npl_os_freertos.c @@ -593,6 +593,12 @@ npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) BLE_NPL_EXIT_CRITICAL_ISR(); ret = xQueueSendToBackFromISR(eventq->q, &ev, &woken); + if (ret != pdPASS) { + BLE_NPL_ENTER_CRITICAL_ISR(); + event->queued = false; + BLE_NPL_EXIT_CRITICAL_ISR(); + return; + } if (woken == pdTRUE) { portYIELD_FROM_ISR(); }