mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(ble/bluedroid): match read-multiple responses by handle
Read Multiple may mix stack auto-responses with app async responses,
so multi_rsp_q order can differ from the request handle order. Look up
each response by handle (with occurrence for duplicates) instead of
walking the queue by index, and treat opcode-only buffers as empty.
(cherry picked from commit f91a41510c)
Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
This commit is contained in:
@@ -148,6 +148,66 @@ void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb)
|
|||||||
memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD));
|
memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function gatt_find_multi_rsp_by_handle
|
||||||
|
**
|
||||||
|
** Description Find a read-multiple response entry by attribute handle.
|
||||||
|
** occurrence selects the Nth matching entry (for duplicate
|
||||||
|
** handles in the same request).
|
||||||
|
**
|
||||||
|
** Returns Pointer to response, or NULL if not found
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static tGATTS_RSP *gatt_find_multi_rsp_by_handle(tGATT_SR_CMD *p_cmd, UINT16 handle,
|
||||||
|
UINT16 occurrence)
|
||||||
|
{
|
||||||
|
list_t *list;
|
||||||
|
const list_node_t *node;
|
||||||
|
UINT16 match_count = 0;
|
||||||
|
|
||||||
|
if (p_cmd->multi_rsp_q == NULL || fixed_queue_is_empty(p_cmd->multi_rsp_q)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = fixed_queue_get_list(p_cmd->multi_rsp_q);
|
||||||
|
for (node = list_begin(list); node != list_end(list); node = list_next(node)) {
|
||||||
|
tGATTS_RSP *p_rsp = (tGATTS_RSP *)list_node(node);
|
||||||
|
|
||||||
|
if (p_rsp->attr_value.handle == handle) {
|
||||||
|
if (match_count == occurrence) {
|
||||||
|
return p_rsp;
|
||||||
|
}
|
||||||
|
match_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
** Function gatt_get_multi_handle_occurrence
|
||||||
|
**
|
||||||
|
** Description Return occurrence index of handle at multi_req index.
|
||||||
|
**
|
||||||
|
** Returns occurrence count
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
static UINT16 gatt_get_multi_handle_occurrence(tGATT_SR_CMD *p_cmd, UINT16 index)
|
||||||
|
{
|
||||||
|
UINT16 ii;
|
||||||
|
UINT16 occurrence = 0;
|
||||||
|
|
||||||
|
for (ii = 0; ii < index; ii++) {
|
||||||
|
if (p_cmd->multi_req.handles[ii] == p_cmd->multi_req.handles[index]) {
|
||||||
|
occurrence++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return occurrence;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
** Function process_read_multi_rsp
|
** Function process_read_multi_rsp
|
||||||
@@ -206,24 +266,12 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
|
|||||||
*p++ = GATT_RSP_READ_MULTI;
|
*p++ = GATT_RSP_READ_MULTI;
|
||||||
p_buf->len = 1;
|
p_buf->len = 1;
|
||||||
|
|
||||||
/* Now walk through the buffers putting the data into the response in order */
|
/* Walk request handles in order; match responses by handle because
|
||||||
list_t *list = NULL;
|
* stack (sync) and app (async) replies may arrive out of order. */
|
||||||
const list_node_t *node = NULL;
|
|
||||||
if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) {
|
|
||||||
list = fixed_queue_get_list(p_cmd->multi_rsp_q);
|
|
||||||
}
|
|
||||||
for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++) {
|
for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++) {
|
||||||
tGATTS_RSP *p_rsp = NULL;
|
tGATTS_RSP *p_rsp = gatt_find_multi_rsp_by_handle(
|
||||||
if (list != NULL) {
|
p_cmd, p_cmd->multi_req.handles[ii],
|
||||||
if (ii == 0) {
|
gatt_get_multi_handle_occurrence(p_cmd, ii));
|
||||||
node = list_begin(list);
|
|
||||||
} else {
|
|
||||||
node = list_next(node);
|
|
||||||
}
|
|
||||||
if (node != list_end(list)) {
|
|
||||||
p_rsp = (tGATTS_RSP *)list_node(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_rsp != NULL) {
|
if (p_rsp != NULL) {
|
||||||
|
|
||||||
@@ -238,16 +286,11 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
|
|||||||
len = p_rsp->attr_value.len;
|
len = p_rsp->attr_value.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) {
|
memcpy (p, p_rsp->attr_value.value, len);
|
||||||
memcpy (p, p_rsp->attr_value.value, len);
|
if (!is_overflow) {
|
||||||
if (!is_overflow) {
|
p += len;
|
||||||
p += len;
|
|
||||||
}
|
|
||||||
p_buf->len += len;
|
|
||||||
} else {
|
|
||||||
p_cmd->status = GATT_NOT_FOUND;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
p_buf->len += len;
|
||||||
|
|
||||||
if (is_overflow) {
|
if (is_overflow) {
|
||||||
break;
|
break;
|
||||||
@@ -262,7 +305,7 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
|
|||||||
|
|
||||||
|
|
||||||
/* Sanity check on the buffer length */
|
/* Sanity check on the buffer length */
|
||||||
if (p_buf->len == 0) {
|
if (p_buf->len <= 1) {
|
||||||
GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!");
|
GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!");
|
||||||
p_cmd->status = GATT_NOT_FOUND;
|
p_cmd->status = GATT_NOT_FOUND;
|
||||||
osi_free (p_buf);
|
osi_free (p_buf);
|
||||||
|
|||||||
Reference in New Issue
Block a user