diff --git a/nimble/host/src/ble_att_clt.c b/nimble/host/src/ble_att_clt.c index 2b60f8b533..04c3558440 100644 --- a/nimble/host/src/ble_att_clt.c +++ b/nimble/host/src/ble_att_clt.c @@ -431,13 +431,20 @@ ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx adata.value_len = data_len - sizeof(*data); adata.value = data->value; - ble_gattc_rx_read_type_adata(conn_handle, cid, &adata); + rc = ble_gattc_rx_read_type_adata(conn_handle, cid, &adata); + if (rc != 0) { + /* We should not call complete callback if this returned an error + * since proc is not added to the proc list. + */ + return rc; + } os_mbuf_adj(*rxom, data_len); } done: /* Notify GATT that the response is done being parsed. */ ble_gattc_rx_read_type_complete(conn_handle, cid, rc); + return rc; } diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index 50e0a75b91..5f1d49075a 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -119,8 +119,8 @@ void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); void ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status); void ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu); -void ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, - struct ble_att_read_type_adata *adata); +int ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, + struct ble_att_read_type_adata *adata); void ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status); void ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 0ff4ec28e6..883521c33e 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -754,12 +754,16 @@ ble_gattc_proc_free(struct ble_gattc_proc *proc) } static void -ble_gattc_proc_insert(struct ble_gattc_proc *proc) +ble_gattc_proc_insert(struct ble_gattc_proc *proc, bool insert_head) { ble_gattc_dbg_assert_proc_not_inserted(proc); ble_hs_lock(); - STAILQ_INSERT_TAIL(&ble_gattc_procs, proc, next); + if (insert_head) { + STAILQ_INSERT_HEAD(&ble_gattc_procs, proc, next); + } else { + STAILQ_INSERT_TAIL(&ble_gattc_procs, proc, next); + } ble_hs_unlock(); } @@ -790,7 +794,7 @@ ble_gattc_proc_set_resume_timer(struct ble_gattc_proc *proc) } static void -ble_gattc_process_status(struct ble_gattc_proc *proc, int status) +ble_gattc_process_status(struct ble_gattc_proc *proc, int status, bool insert_head) { switch (status) { case 0: @@ -798,7 +802,7 @@ ble_gattc_process_status(struct ble_gattc_proc *proc, int status) ble_gattc_proc_set_exp_timer(proc); } - ble_gattc_proc_insert(proc); + ble_gattc_proc_insert(proc, insert_head); ble_hs_timer_resched(); break; @@ -1187,7 +1191,7 @@ ble_gattc_resume_procs(void) proc->flags &= ~BLE_GATTC_PROC_F_STALLED; rc = resume_cb(proc); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -1398,7 +1402,7 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg) STATS_INC(ble_gattc_stats, mtu_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -1623,7 +1627,7 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, STATS_INC(ble_gattc_stats, disc_all_svcs_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -1837,7 +1841,7 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, STATS_INC(ble_gattc_stats, disc_svc_uuid_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -2153,7 +2157,7 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, STATS_INC(ble_gattc_stats, find_inc_svcs_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -2386,7 +2390,7 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, STATS_INC(ble_gattc_stats, disc_all_chrs_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -2626,7 +2630,7 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle, STATS_INC(ble_gattc_stats, disc_chrs_uuid_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -2836,7 +2840,7 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle, STATS_INC(ble_gattc_stats, disc_all_dscs_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -2971,7 +2975,7 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle, STATS_INC(ble_gattc_stats, read_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -3135,7 +3139,7 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle, STATS_INC(ble_gattc_stats, read_uuid_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -3331,7 +3335,7 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset, STATS_INC(ble_gattc_stats, read_long_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -3555,7 +3559,7 @@ ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles, STATS_INC(ble_gattc_stats, read_mult_fail); } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -3730,7 +3734,7 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, /* Free the mbuf in case the send failed. */ os_mbuf_free_chain(txom); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -4048,7 +4052,7 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, /* Free the mbuf in case of failure. */ os_mbuf_free_chain(txom); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -4337,7 +4341,7 @@ ble_gattc_write_reliable(uint16_t conn_handle, attrs[i].om = NULL; } - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); return rc; } @@ -4709,7 +4713,7 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, /* Tell the application that an indication transmission was attempted. */ ble_gap_notify_tx_event(rc, conn_handle, chr_val_handle, 1); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); os_mbuf_free_chain(txom); return rc; } @@ -4777,7 +4781,7 @@ ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_m proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, BLE_L2CAP_CID_ATT, BLE_GATT_OP_MTU); if (proc != NULL) { ble_gattc_mtu_cb(proc, status, 0, chan_mtu); - ble_gattc_process_status(proc, BLE_HS_EDONE); + ble_gattc_process_status(proc, BLE_HS_EDONE, false); } } @@ -4800,7 +4804,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_idata(proc, idata); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4822,7 +4826,7 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status) BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_complete(proc, status); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4845,7 +4849,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_hinfo(proc, hinfo); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4867,7 +4871,7 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int st BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_complete(proc, status); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4875,7 +4879,7 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int st * Dispatches an incoming "attribute data" entry from a read-by-type-response * to the appropriate active GATT procedure. */ -void +int ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata) { @@ -4892,8 +4896,15 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, adata); - ble_gattc_process_status(proc, rc); + /* We need to put procedure on head of the queue since caller expects + * to process the same proc again. + */ + ble_gattc_process_status(proc, rc, true); + } else { + rc = -1; } + + return rc; } /** @@ -4916,7 +4927,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status) &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4939,7 +4950,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_adata(proc, adata); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4961,7 +4972,7 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int st BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_complete(proc, status); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -4985,7 +4996,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_ &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status, om); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -5008,7 +5019,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, BLE_GATT_OP_READ_LONG); if (proc != NULL) { rc = ble_gattc_read_long_rx_read_rsp(proc, status, om); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -5032,7 +5043,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, op); if (proc != NULL) { ble_gattc_read_mult_cb(proc, status, 0, om); - ble_gattc_process_status(proc, BLE_HS_EDONE); + ble_gattc_process_status(proc, BLE_HS_EDONE, false); } } @@ -5053,7 +5064,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid) BLE_GATT_OP_WRITE); if (proc != NULL) { ble_gattc_write_cb(proc, 0, 0); - ble_gattc_process_status(proc, BLE_HS_EDONE); + ble_gattc_process_status(proc, BLE_HS_EDONE, false); } } @@ -5079,7 +5090,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status, handle, offset, om); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -5102,7 +5113,7 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status) ble_gattc_rx_exec_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); - ble_gattc_process_status(proc, rc); + ble_gattc_process_status(proc, rc, false); } } @@ -5123,7 +5134,7 @@ ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid) BLE_GATT_OP_INDICATE); if (proc != NULL) { ble_gatts_indicate_rx_rsp(proc); - ble_gattc_process_status(proc, BLE_HS_EDONE); + ble_gattc_process_status(proc, BLE_HS_EDONE, false); } }