mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(ble/bluedroid): Fix double-free, exec write, bounds and HCI param checks
- gap_ble: add length/attribute checks in gap_proc_write_req
- gatt_cl: set p_cmd->p_cmd=NULL before memset to avoid double-free;
pending_cl_req %= GATT_CL_MAX_LCB
- gatt_sr: fix exec write zeroed_attrs and offset/len bounds, OOM cleanup
- gatt_sr_hash: null checks for p_attr->p_next, p_data+=2, len==0 in
gatts_calculate_datebase_hash, gatts_show_local_database
- gatt_utils: explicit return NULL, indent, idx<GATT_MAX_APPS checks,
len>GATT_MAX_ATTR_LEN, gatt_cleanup_upon_disc dealloc branch
- hciblecmds: length/handle validation in BLE ext adv/BIG sync HCI commands
(cherry picked from commit 1d31286f1a)
Co-authored-by: zhiweijian <zhiweijian@espressif.com>
This commit is contained in:
@@ -315,6 +315,9 @@ UINT8 gap_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
|
||||
switch (p_db_attr->uuid) {
|
||||
#if (GATTS_DEVICE_NAME_WRITABLE == TRUE)
|
||||
case GATT_UUID_GAP_DEVICE_NAME: {
|
||||
if (p_data->len > BD_NAME_LEN) {
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
UINT8 *p_val = p_data->value;
|
||||
p_val[p_data->len] = '\0';
|
||||
BTM_SetLocalDeviceName((char *)p_val, BT_DEVICE_TYPE_BLE);
|
||||
|
||||
@@ -1146,9 +1146,11 @@ BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
|
||||
}
|
||||
} else {
|
||||
GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
|
||||
|
||||
/* attp_send_msg_to_l2cap() already freed p_cmd->p_cmd on failure */
|
||||
p_cmd->p_cmd = NULL;
|
||||
memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
|
||||
p_tcb->pending_cl_req ++;
|
||||
p_tcb->pending_cl_req %= GATT_CL_MAX_LCB;
|
||||
p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
|
||||
}
|
||||
|
||||
|
||||
@@ -486,9 +486,11 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
tGATT_IF gatt_if;
|
||||
UINT16 conn_id;
|
||||
UINT16 queue_num = 0;
|
||||
BOOLEAN is_first = TRUE;
|
||||
UINT16 zeroed_cap = 0, zeroed_count = 0;
|
||||
void **zeroed_attrs = NULL;
|
||||
BOOLEAN is_prepare_write_valid = FALSE;
|
||||
BOOLEAN is_need_dequeue_sr_cmd = FALSE;
|
||||
BOOLEAN sr_cmd_already_dequeued = FALSE;
|
||||
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
|
||||
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
|
||||
|
||||
@@ -529,6 +531,7 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
gatt_exec_write_rsp.op_code = GATT_RSP_EXEC_WRITE;
|
||||
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_exec_write_rsp), sizeof(gatt_exec_write_rsp));
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
sr_cmd_already_dequeued = TRUE;
|
||||
if (flag != GATT_PREP_WRITE_CANCEL){
|
||||
is_prepare_write_valid = TRUE;
|
||||
}
|
||||
@@ -549,23 +552,99 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
gatt_send_error_rsp(p_tcb, prepare_record->error_code_app, GATT_REQ_EXEC_WRITE, 0, is_need_dequeue_sr_cmd);
|
||||
}
|
||||
|
||||
//dequeue prepare write data
|
||||
/* Track which attributes we've zeroed so we only zero on first write per attribute.
|
||||
* Zeroing all up-front would leave attr_len=0 for attributes whose write is later
|
||||
* skipped (e.g. overflow), causing data loss. */
|
||||
if (is_prepare_write_valid && queue_num > 0) {
|
||||
zeroed_cap = queue_num; /* max unique attributes in this exec is at most queue_num */
|
||||
zeroed_attrs = (void **)osi_calloc(zeroed_cap * sizeof(void *));
|
||||
if (zeroed_attrs == NULL) {
|
||||
GATT_TRACE_ERROR("%s: no memory for zeroed_attrs, abort exec write", __func__);
|
||||
while (fixed_queue_try_peek_first(prepare_record->queue)) {
|
||||
queue_data = fixed_queue_dequeue(prepare_record->queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
osi_free(queue_data);
|
||||
}
|
||||
fixed_queue_free(prepare_record->queue, NULL);
|
||||
prepare_record->queue = NULL;
|
||||
{
|
||||
UINT16 total_num_saved = prepare_record->total_num;
|
||||
prepare_record->total_num = 0;
|
||||
prepare_record->error_code_app = GATT_SUCCESS;
|
||||
/* Only send error (and dequeue via gatt_send_error_rsp) if we did not already send success and dequeue (first branch) */
|
||||
if (!sr_cmd_already_dequeued) {
|
||||
gatt_send_error_rsp(p_tcb, GATT_NO_RESOURCES, GATT_REQ_EXEC_WRITE, 0, TRUE);
|
||||
} else {
|
||||
/* Success already sent to peer; notify apps and clear prep_cnt so state stays consistent */
|
||||
if (!gatt_sr_is_prep_cnt_zero(p_tcb)) {
|
||||
if (total_num_saved > queue_num) {
|
||||
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
|
||||
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
|
||||
}
|
||||
for (i = 0; i < GATT_MAX_APPS; i++) {
|
||||
if (p_tcb->prep_cnt[i]) {
|
||||
gatt_if = (tGATT_IF) (i + 1);
|
||||
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
|
||||
gatt_sr_send_req_callback(conn_id,
|
||||
trans_id,
|
||||
GATTS_REQ_TYPE_WRITE_EXEC,
|
||||
(tGATTS_DATA *)&flag);
|
||||
p_tcb->prep_cnt[i] = 0;
|
||||
}
|
||||
}
|
||||
/* OOM path: we enqueued sr_cmd but will not get app response flow; clear sr_cmd so later requests are not dropped */
|
||||
if (total_num_saved > queue_num) {
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while(fixed_queue_try_peek_first(prepare_record->queue)) {
|
||||
queue_data = fixed_queue_dequeue(prepare_record->queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
if (is_prepare_write_valid){
|
||||
if((queue_data->p_attr->p_value != NULL) && (queue_data->p_attr->p_value->attr_val.attr_val != NULL)){
|
||||
if(is_first) {
|
||||
//clear attr_val.attr_len before handle prepare write data
|
||||
queue_data->p_attr->p_value->attr_val.attr_len = 0;
|
||||
is_first = FALSE;
|
||||
UINT16 attr_max_len = queue_data->p_attr->p_value->attr_val.attr_max_len;
|
||||
if (queue_data->offset > attr_max_len ||
|
||||
queue_data->len > attr_max_len - queue_data->offset) {
|
||||
GATT_TRACE_ERROR("%s: exec write overflow prevented, offset=%u len=%u max=%u",
|
||||
__func__, queue_data->offset, queue_data->len, attr_max_len);
|
||||
} else {
|
||||
UINT16 k;
|
||||
BOOLEAN need_zero = TRUE;
|
||||
/* Zero attr_len only on first successful write to this attribute in this exec */
|
||||
if (zeroed_attrs != NULL) {
|
||||
for (k = 0; k < zeroed_count; k++) {
|
||||
if (zeroed_attrs[k] == (void *)queue_data->p_attr) {
|
||||
need_zero = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (need_zero) {
|
||||
queue_data->p_attr->p_value->attr_val.attr_len = 0;
|
||||
if (zeroed_attrs != NULL && zeroed_count < zeroed_cap) {
|
||||
zeroed_attrs[zeroed_count++] = (void *)queue_data->p_attr;
|
||||
}
|
||||
}
|
||||
memcpy(queue_data->p_attr->p_value->attr_val.attr_val + queue_data->offset,
|
||||
queue_data->value, queue_data->len);
|
||||
{
|
||||
UINT16 write_end = queue_data->offset + queue_data->len;
|
||||
if (write_end > queue_data->p_attr->p_value->attr_val.attr_len) {
|
||||
queue_data->p_attr->p_value->attr_val.attr_len = write_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(queue_data->p_attr->p_value->attr_val.attr_val+queue_data->offset, queue_data->value, queue_data->len);
|
||||
//don't forget to increase the attribute value length in the gatts database.
|
||||
queue_data->p_attr->p_value->attr_val.attr_len += queue_data->len;
|
||||
}
|
||||
}
|
||||
osi_free(queue_data);
|
||||
}
|
||||
if (zeroed_attrs != NULL) {
|
||||
osi_free(zeroed_attrs);
|
||||
}
|
||||
fixed_queue_free(prepare_record->queue, NULL);
|
||||
prepare_record->queue = NULL;
|
||||
|
||||
|
||||
@@ -86,10 +86,13 @@ static size_t calculate_database_info_size(void)
|
||||
len += 8 + get_uuid_stream_len(p_attr->p_value->incl_handle.service_type);
|
||||
} else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) {
|
||||
tBT_UUID char_uuid = {0};
|
||||
// Characteristic declaration
|
||||
if (p_attr->p_next == NULL) {
|
||||
GATT_TRACE_ERROR("%s: malformed DB, char decl at handle %u has no value attr",
|
||||
__func__, p_attr->handle);
|
||||
break;
|
||||
}
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid);
|
||||
// Increment 1 to fetch characteristic uuid from value declaration attribute
|
||||
len += 7 + get_uuid_stream_len(char_uuid);
|
||||
} else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION ||
|
||||
p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG ||
|
||||
@@ -136,14 +139,17 @@ static void fill_database_info(UINT8 *p_data)
|
||||
gatt_build_uuid_to_stream(&p_data, p_attr->p_value->incl_handle.service_type);
|
||||
} else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) {
|
||||
tBT_UUID char_uuid = {0};
|
||||
// Characteristic declaration
|
||||
if (p_attr->p_next == NULL) {
|
||||
GATT_TRACE_ERROR("%s: malformed DB, char decl at handle %u has no value attr",
|
||||
__func__, p_attr->handle);
|
||||
break;
|
||||
}
|
||||
UINT16_TO_STREAM(p_data, p_attr->handle);
|
||||
UINT16_TO_STREAM(p_data, GATT_UUID_CHAR_DECLARE);
|
||||
UINT8_TO_STREAM(p_data, p_attr->p_value->char_decl.property);
|
||||
UINT16_TO_STREAM(p_data, p_attr->p_value->char_decl.char_val_handle);
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid);
|
||||
// Increment 1 to fetch characteristic uuid from value declaration attribute
|
||||
gatt_build_uuid_to_stream(&p_data, char_uuid);
|
||||
} else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION ||
|
||||
p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG ||
|
||||
@@ -160,6 +166,7 @@ static void fill_database_info(UINT8 *p_data)
|
||||
// TODO: process extended properties descriptor
|
||||
if (p_attr->p_value->attr_val.attr_len == 2) {
|
||||
memcpy(p_data, p_attr->p_value->attr_val.attr_val, 2);
|
||||
p_data += 2;
|
||||
} else {
|
||||
UINT16_TO_STREAM(p_data, 0x0000);
|
||||
}
|
||||
@@ -180,6 +187,11 @@ tGATT_STATUS gatts_calculate_datebase_hash(BT_OCTET16 hash)
|
||||
|
||||
len = calculate_database_info_size();
|
||||
|
||||
if (len == 0) {
|
||||
memset(hash, 0, BT_OCTET16_LEN);
|
||||
return GATT_SUCCESS;
|
||||
}
|
||||
|
||||
data_buf = (UINT8 *)osi_malloc(len);
|
||||
if (data_buf == NULL) {
|
||||
GATT_TRACE_ERROR ("%s failed to allocate buffer (%u)\n", __func__, len);
|
||||
@@ -237,6 +249,10 @@ void gatts_show_local_database(void)
|
||||
tBT_UUID char_uuid = {0};
|
||||
tGATT_ATTR16 *p_char_val;
|
||||
p_char_val = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
if (p_char_val == NULL) {
|
||||
printf("characteristic (malformed - no value attr)\n");
|
||||
break;
|
||||
}
|
||||
attr_uuid_to_bt_uuid((void *)p_char_val, &char_uuid);
|
||||
|
||||
printf("%s\n", gatt_get_attr_name(p_attr->uuid));
|
||||
|
||||
@@ -797,11 +797,11 @@ tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda)
|
||||
p_buf = (tGATTS_SRV_CHG *)list_node(node);
|
||||
if (!memcmp( bda, p_buf->bda, BD_ADDR_LEN)) {
|
||||
GATT_TRACE_DEBUG("bda is in the srv chg clt list");
|
||||
break;
|
||||
return p_buf;
|
||||
}
|
||||
}
|
||||
|
||||
return p_buf;
|
||||
return NULL;
|
||||
}
|
||||
#endif // (GATTS_INCLUDED == TRUE)
|
||||
|
||||
@@ -1006,11 +1006,11 @@ tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport)
|
||||
allocated = TRUE;
|
||||
}
|
||||
if (i != GATT_INDEX_INVALID) {
|
||||
p_tcb = gatt_tcb_alloc(i);
|
||||
if (!p_tcb) {
|
||||
return NULL;
|
||||
}
|
||||
if (allocated) {
|
||||
p_tcb = gatt_tcb_alloc(i);
|
||||
if (!p_tcb) {
|
||||
return NULL;
|
||||
}
|
||||
memset(p_tcb, 0, sizeof(tGATT_TCB));
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
p_tcb->pending_enc_clcb = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
@@ -1018,6 +1018,11 @@ tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport)
|
||||
p_tcb->in_use = TRUE;
|
||||
p_tcb->tcb_idx = i;
|
||||
p_tcb->transport = transport;
|
||||
} else {
|
||||
p_tcb = gatt_get_tcb_by_idx(i);
|
||||
if (!p_tcb) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
memcpy(p_tcb->peer_bda, bda, BD_ADDR_LEN);
|
||||
#if GATTS_ROBUST_CACHING_ENABLED
|
||||
@@ -1778,10 +1783,10 @@ tGATT_TCB *gatt_find_tcb_by_cid (UINT16 lcid)
|
||||
for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) {
|
||||
p_tcb = list_node(p_node);
|
||||
if (p_tcb->in_use && p_tcb->att_lcid == lcid) {
|
||||
break;
|
||||
return p_tcb;
|
||||
}
|
||||
}
|
||||
return p_tcb;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -1969,7 +1974,7 @@ void gatt_sr_update_cback_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc
|
||||
#if (GATTS_INCLUDED == TRUE)
|
||||
UINT8 idx = ((UINT8) gatt_if) - 1 ;
|
||||
|
||||
if (p_tcb) {
|
||||
if (p_tcb && idx < GATT_MAX_APPS) {
|
||||
if (is_reset_first) {
|
||||
gatt_sr_reset_cback_cnt(p_tcb);
|
||||
}
|
||||
@@ -1999,9 +2004,9 @@ void gatt_sr_update_prep_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc,
|
||||
UINT8 idx = ((UINT8) gatt_if) - 1 ;
|
||||
|
||||
GATT_TRACE_DEBUG("gatt_sr_update_prep_cnt tcb idx=%d gatt_if=%d is_inc=%d is_reset_first=%d",
|
||||
p_tcb->tcb_idx, gatt_if, is_inc, is_reset_first);
|
||||
p_tcb ? p_tcb->tcb_idx : 0, gatt_if, is_inc, is_reset_first);
|
||||
|
||||
if (p_tcb) {
|
||||
if (p_tcb && idx < GATT_MAX_APPS) {
|
||||
if (is_reset_first) {
|
||||
gatt_sr_reset_prep_cnt(p_tcb);
|
||||
}
|
||||
@@ -2164,6 +2169,11 @@ UINT8 gatt_send_write_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code,
|
||||
{
|
||||
tGATT_CL_MSG msg;
|
||||
|
||||
if (len > GATT_MAX_ATTR_LEN) {
|
||||
GATT_TRACE_ERROR("%s: len %u exceeds max %u", __func__, len, GATT_MAX_ATTR_LEN);
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
msg.attr_value.handle = handle;
|
||||
msg.attr_value.len = len;
|
||||
msg.attr_value.offset = offset;
|
||||
@@ -2312,9 +2322,9 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
|
||||
GATT_TRACE_DEBUG ("found p_clcb conn_id=%d clcb_idx=%d", p_clcb->conn_id, p_clcb->clcb_idx);
|
||||
if (p_clcb->operation != GATTC_OPTYPE_NONE) {
|
||||
gatt_end_operation(p_clcb, GATT_ERROR, NULL);
|
||||
p_clcb = NULL;
|
||||
} else {
|
||||
gatt_clcb_dealloc(p_clcb);
|
||||
}
|
||||
gatt_clcb_dealloc(p_clcb);
|
||||
}
|
||||
}
|
||||
#if (GATTC_INCLUDED == TRUE)
|
||||
|
||||
@@ -1329,6 +1329,10 @@ UINT8 btsnd_hcic_ble_set_ext_adv_data(UINT8 adv_handle,
|
||||
HCI_TRACE_EVENT("%s, adv_handle = %d, operation = %d, fragment_prefrence = %d,\
|
||||
data_len = %d", __func__, adv_handle, operation, fragment_prefrence, data_len);
|
||||
|
||||
if (data_len > HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA) {
|
||||
data_len = HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA;
|
||||
}
|
||||
|
||||
HCIC_BLE_CMD_CREATED(p, pp, data_len + 4);
|
||||
UINT16_TO_STREAM(pp, HCI_BLE_SET_EXT_ADV_DATA);
|
||||
UINT8_TO_STREAM(pp, data_len + 4);
|
||||
@@ -1336,10 +1340,6 @@ UINT8 btsnd_hcic_ble_set_ext_adv_data(UINT8 adv_handle,
|
||||
UINT8_TO_STREAM(pp, operation);
|
||||
UINT8_TO_STREAM(pp, fragment_prefrence);
|
||||
|
||||
if (data_len > HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA) {
|
||||
data_len = HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA;
|
||||
}
|
||||
|
||||
UINT8_TO_STREAM (pp, data_len);
|
||||
|
||||
if (p_data != NULL && data_len > 0){
|
||||
@@ -1361,6 +1361,10 @@ UINT8 btsnd_hcic_ble_set_ext_adv_scan_rsp_data(UINT8 adv_handle,
|
||||
HCI_TRACE_EVENT("%s, adv_handle = %d, operation = %d, fragment_prefrence = %d,\n\
|
||||
data_len = %d", __func__, adv_handle, operation, fragment_prefrence, data_len);
|
||||
|
||||
if (data_len > HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA) {
|
||||
data_len = HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA;
|
||||
}
|
||||
|
||||
HCIC_BLE_CMD_CREATED(p, pp, data_len + 4);
|
||||
|
||||
UINT16_TO_STREAM(pp, HCI_BLE_SET_EXT_SCAN_RSP_DATA);
|
||||
@@ -1369,12 +1373,6 @@ UINT8 btsnd_hcic_ble_set_ext_adv_scan_rsp_data(UINT8 adv_handle,
|
||||
UINT8_TO_STREAM(pp, operation);
|
||||
UINT8_TO_STREAM(pp, fragment_prefrence);
|
||||
|
||||
memset(pp, 0, data_len);
|
||||
|
||||
if (data_len > HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA) {
|
||||
data_len = HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA;
|
||||
}
|
||||
|
||||
UINT8_TO_STREAM (pp, data_len);
|
||||
if (p_data != NULL && data_len > 0) {
|
||||
ARRAY_TO_STREAM (pp, p_data, data_len);
|
||||
@@ -1540,6 +1538,10 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_data(UINT8 adv_handle,
|
||||
HCI_TRACE_EVENT("%s, adv_handle = %d, operation = %d, len = %d",
|
||||
__func__, adv_handle, operation, len);
|
||||
|
||||
if (len > HCIC_PARAM_SIZE_WRITE_PERIODIC_ADV_DATA) {
|
||||
len = HCIC_PARAM_SIZE_WRITE_PERIODIC_ADV_DATA;
|
||||
}
|
||||
|
||||
HCIC_BLE_CMD_CREATED(p, pp, len + 3);
|
||||
|
||||
UINT16_TO_STREAM(pp, HCI_BLE_SET_PERIOD_ADV_DATA);
|
||||
@@ -1547,12 +1549,6 @@ UINT8 btsnd_hcic_ble_set_periodic_adv_data(UINT8 adv_handle,
|
||||
UINT8_TO_STREAM(pp, adv_handle);
|
||||
UINT8_TO_STREAM(pp, operation);
|
||||
|
||||
//memset(pp, 0, len);
|
||||
|
||||
if (len > HCIC_PARAM_SIZE_WRITE_PERIODIC_ADV_DATA) {
|
||||
len = HCIC_PARAM_SIZE_WRITE_PERIODIC_ADV_DATA;
|
||||
}
|
||||
|
||||
UINT8_TO_STREAM (pp, len);
|
||||
|
||||
if (p_data != NULL && len > 0) {
|
||||
@@ -2268,17 +2264,19 @@ UINT8 btsnd_hcic_ble_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
|
||||
|
||||
HCI_TRACE_DEBUG("big sync create: big_handle %d sync_handle %d encryption %d mse %d big_sync_timeout %d", big_handle, sync_handle, encryption, mse, big_sync_timeout);
|
||||
|
||||
// for (uint8_t i = 0; i < num_bis; i++)
|
||||
// {
|
||||
// HCI_TRACE_ERROR("i %d bis %d", bis[i]);
|
||||
// }
|
||||
#define HCIC_PARAM_SIZE_BIG_SYNC_CREATE_FIXED 24
|
||||
if (num_bis > (HCIC_PARAM_SIZE_BIG_SYNC_CREATE_PARAMS - HCIC_PARAM_SIZE_BIG_SYNC_CREATE_FIXED)) {
|
||||
HCI_TRACE_ERROR("%s: num_bis %u exceeds max", __func__, num_bis);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_BIG_SYNC_CREATE_PARAMS);
|
||||
UINT8 param_size = HCIC_PARAM_SIZE_BIG_SYNC_CREATE_FIXED + num_bis;
|
||||
HCIC_BLE_CMD_CREATED(p, pp, param_size);
|
||||
|
||||
pp = (UINT8 *)(p + 1);
|
||||
|
||||
UINT16_TO_STREAM(pp, HCI_BLE_BIG_CREATE_SYNC);
|
||||
UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BIG_SYNC_CREATE_PARAMS);
|
||||
UINT8_TO_STREAM(pp, param_size);
|
||||
|
||||
UINT8_TO_STREAM(pp, big_handle);
|
||||
UINT16_TO_STREAM(pp, sync_handle);
|
||||
|
||||
Reference in New Issue
Block a user