Merge branch 'fix/fix_ai_review_bug_for_bluedroid_host_260318' into 'master'

Fixed some BLE AI review bugs for bluedroid

Closes BLERP-2630

See merge request espressif/esp-idf!46730
This commit is contained in:
Island
2026-03-19 10:31:09 +08:00
59 changed files with 995 additions and 364 deletions
@@ -45,7 +45,8 @@
#define BTA_DM_MSG_LEN 50
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id))
/* Use 1ULL to avoid UB: 1 << 32 is undefined when int is 32-bit (C11 §6.5.7) */
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) ((UINT32)(1ULL << (id)))
/* DM events */
enum {
@@ -108,7 +108,6 @@ const tBTA_GATTC_ACTION bta_gattc_action[] = {
#define BTA_GATTC_ACTIONS 1 /* number of actions */
#define BTA_GATTC_NEXT_STATE 1 /* position of next state */
#define BTA_GATTC_NUM_COLS 2 /* number of columns in state tables */
/* state table for idle state */
static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] = {
/* Event Action 1 Next state */
@@ -298,6 +297,11 @@ BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_D
event &= 0x00FF;
if (event >= sizeof(bta_gattc_st_idle) / sizeof(bta_gattc_st_idle[0])) {
APPL_TRACE_ERROR("bta_gattc_sm_execute: invalid event index %d", event);
return TRUE;
}
/* set next state */
p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE];
@@ -125,8 +125,13 @@ tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda
tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
UINT8 i;
if (remote_bda == NULL) {
return NULL;
}
for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++) {
if (p_clcb->in_use &&
p_clcb->p_rcb != NULL &&
p_clcb->p_rcb->client_if == client_if &&
p_clcb->transport == transport &&
bdcmp(p_clcb->bda, remote_bda) == 0) {
@@ -244,16 +249,16 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
if (p_clcb) {
p_srcb = p_clcb->p_srcb;
if (p_srcb->num_clcb) {
if (p_srcb != NULL && p_srcb->num_clcb) {
p_srcb->num_clcb --;
}
if (p_clcb->p_rcb->num_clcb) {
if (p_clcb->p_rcb != NULL && p_clcb->p_rcb->num_clcb) {
p_clcb->p_rcb->num_clcb --;
}
/* if the srcb is no longer needed, reset the state */
if ( p_srcb->num_clcb == 0) {
if (p_srcb != NULL && p_srcb->num_clcb == 0) {
p_srcb->connected = FALSE;
p_srcb->state = BTA_GATTC_SERV_IDLE;
p_srcb->mtu = 0;
@@ -268,13 +273,13 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
#endif
}
if ( p_clcb->p_q_cmd != NULL && !list_contains(p_clcb->p_cmd_list, p_clcb->p_q_cmd)){
if (p_clcb->p_q_cmd != NULL &&
(p_clcb->p_cmd_list == NULL || !list_contains(p_clcb->p_cmd_list, p_clcb->p_q_cmd))) {
osi_free(p_clcb->p_q_cmd);
p_clcb->p_q_cmd = NULL;
}
// don't forget to clear the command queue before dealloc the clcb.
list_clear(p_clcb->p_cmd_list);
osi_free((void *)p_clcb->p_cmd_list);
list_free(p_clcb->p_cmd_list);
p_clcb->p_cmd_list = NULL;
//osi_free_and_reset((void **)&p_clcb->p_q_cmd);
memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
@@ -970,6 +975,10 @@ tBTA_GATTC_CLCB *bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg)
{
tBTA_GATTC_CLCB *p_clcb = NULL;
if (p_msg == NULL) {
return NULL;
}
if (p_msg->int_conn.role == HCI_ROLE_SLAVE) {
bta_gattc_conn_find_alloc(p_msg->int_conn.remote_bda);
}
@@ -1005,6 +1014,10 @@ tBTA_GATTC_CLCB *bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg)
{
tBTA_GATTC_CLCB *p_clcb = NULL;
if (p_msg == NULL) {
return NULL;
}
bta_gattc_conn_dealloc(p_msg->int_conn.remote_bda);
if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific)) == NULL) {
/* connection attempt failed, send connection callback event */
@@ -1033,6 +1046,8 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
switch (p_src->len)
{
case 0:
/* Invalid/empty UUID: zero p_dest so callers don't use garbage */
memset(p_dest->uu, 0, sizeof(p_dest->uu));
break;
case LEN_UUID_16:
@@ -1041,8 +1056,8 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
break;
case LEN_UUID_32:
p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
p_dest->uu[12] = p_src->uu.uuid32 & 0xff;
p_dest->uu[13] = (p_src->uu.uuid32 >> 8) & 0xff;
p_dest->uu[14] = (p_src->uu.uuid32 >> 16) & 0xff;
p_dest->uu[15] = (p_src->uu.uuid32 >> 24) & 0xff;
break;
@@ -1054,6 +1069,7 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
default:
APPL_TRACE_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len);
memset(p_dest->uu, 0, sizeof(p_dest->uu));
break;
}
}
@@ -872,7 +872,7 @@ void bta_gatts_send_service_change_indication (tBTA_GATTS_DATA *p_msg)
tBTA_GATTS_RCB *p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_send_service_change.server_if);
tBTA_GATTS_SERVICE_CHANGE service_change;
tBTA_GATT_STATUS status = BTA_GATT_OK;
UINT16 addr[BD_ADDR_LEN] = {0};
UINT8 addr[BD_ADDR_LEN] = {0};
if(memcmp(p_msg->api_send_service_change.remote_bda, addr, BD_ADDR_LEN) != 0) {
BD_ADDR bd_addr;
memcpy(bd_addr, p_msg->api_send_service_change.remote_bda, BD_ADDR_LEN);
@@ -223,6 +223,7 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_u
UINT16 len = 0;
if(attr_val != NULL){
len = attr_val->attr_len;
APPL_TRACE_DEBUG("attr_val->attr_len = %x, attr_max_len = %x\n",attr_val->attr_len, attr_val->attr_max_len);
}
if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) osi_malloc(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL) {
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
@@ -234,15 +235,22 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_u
if(control !=NULL){
p_buf->control.auto_rsp = control->auto_rsp;
}
if(attr_val != NULL){
APPL_TRACE_DEBUG("!!!!!!attr_val->attr_len = %x\n",attr_val->attr_len);
APPL_TRACE_DEBUG("!!!!!!!attr_val->attr_max_len = %x\n",attr_val->attr_max_len);
if(attr_val != NULL && len){
p_buf->attr_val.attr_len = attr_val->attr_len;
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
p_buf->attr_val.attr_val = (uint8_t *)osi_malloc(len);
if(p_buf->attr_val.attr_val != NULL){
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, len);
} else {
p_buf->attr_val.attr_len = 0;
p_buf->attr_val.attr_max_len = 0;
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
}
} else {
p_buf->attr_val.attr_len = 0;
p_buf->attr_val.attr_max_len = 0;
p_buf->attr_val.attr_val = NULL;
}
if (p_char_uuid) {
@@ -499,6 +507,9 @@ void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
if(value != NULL){
if((p_buf->value = (UINT8 *)osi_malloc(length)) != NULL){
memcpy(p_buf->value, value, length);
} else {
p_buf->length = 0;
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
}
}
@@ -103,6 +103,7 @@ enum {
#define BTA_SYS_ACTIONS 2 /* number of actions */
#define BTA_SYS_NEXT_STATE 2 /* position of next state */
#define BTA_SYS_NUM_COLS 3 /* number of columns in state tables */
#define BTA_SYS_NUM_STATES 4 /* OFF, STARTING, ON, STOPPING */
/* state table for OFF state */
@@ -213,22 +214,39 @@ BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
BOOLEAN freebuf = TRUE;
tBTA_SYS_ST_TBL state_table;
UINT8 action;
UINT8 evt_idx;
int i;
if (p_msg == NULL) {
return freebuf;
}
evt_idx = p_msg->event & 0x00ff;
if (evt_idx >= BTA_SYS_NUM_ACTIONS) {
APPL_TRACE_ERROR("bta_sys_sm_execute: event 0x%x out of range (evt_idx=%u)", p_msg->event, evt_idx);
return freebuf;
}
if (bta_sys_cb.state >= BTA_SYS_NUM_STATES) {
APPL_TRACE_ERROR("bta_sys_sm_execute: invalid state %u", bta_sys_cb.state);
return freebuf;
}
APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x\n", bta_sys_cb.state, p_msg->event);
/* look up the state table for the current state */
state_table = bta_sys_st_tbl[bta_sys_cb.state];
/* update state */
bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
bta_sys_cb.state = state_table[evt_idx][BTA_SYS_NEXT_STATE];
/* execute action functions */
for (i = 0; i < BTA_SYS_ACTIONS; i++) {
if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE) {
(*bta_sys_action[action])( (tBTA_SYS_HW_MSG *) p_msg);
} else {
action = state_table[evt_idx][i];
if (action == BTA_SYS_IGNORE) {
break;
}
if (action < BTA_SYS_NUM_ACTIONS) {
(*bta_sys_action[action])( (tBTA_SYS_HW_MSG *) p_msg);
}
}
return freebuf;
@@ -598,16 +616,29 @@ void bta_alarm_cb(void *data)
void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms)
{
osi_alarm_t *alarm = NULL;
assert(p_tle != NULL);
// Get the alarm for this p_tle.
osi_mutex_lock(&bta_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (!hash_map_has_key(bta_alarm_hash_map, p_tle)) {
hash_map_set(bta_alarm_hash_map, p_tle, osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0));
alarm = osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0);
if (alarm == NULL) {
APPL_TRACE_ERROR("%s unable to create new alarm.", __func__);
osi_mutex_unlock(&bta_alarm_lock);
return;
}
if (!hash_map_set(bta_alarm_hash_map, p_tle, alarm)) {
APPL_TRACE_ERROR("%s unable to set alarm in map.", __func__);
osi_alarm_free(alarm);
osi_mutex_unlock(&bta_alarm_lock);
return;
}
}
osi_mutex_unlock(&bta_alarm_lock);
osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
alarm = hash_map_get(bta_alarm_hash_map, p_tle);
if (alarm == NULL) {
APPL_TRACE_ERROR("%s unable to create alarm.", __func__);
return;
@@ -177,6 +177,7 @@ static bt_status_t _btc_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
break;
case BTM_LE_KEY_LID:
name = BTC_BLE_STORAGE_LE_KEY_LID_STR;
break;
default:
return BT_STATUS_FAIL;
}
@@ -105,7 +105,7 @@ bool btc_config_init(void)
return true;
error:;
error:
config_free(config);
osi_mutex_free(&lock);
config = NULL;
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -29,7 +29,8 @@
/******************************************************************************
** Constants & Macros
******************************************************************************/
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id))
/* Use 1ULL to avoid UB: 1 << 32 is undefined when int is 32-bit (C11 §6.5.7) */
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) ((tBTA_SERVICE_MASK)(1ULL << (id)))
/******************************************************************************
** Static variables
@@ -697,7 +698,7 @@ bt_status_t btc_dm_enable_service(tBTA_SERVICE_ID service_id)
{
tBTA_SERVICE_ID *p_id = &service_id;
btc_dm_cb.btc_enabled_services |= (1 << service_id);
btc_dm_cb.btc_enabled_services |= (tBTA_SERVICE_MASK)(1ULL << service_id);
BTC_TRACE_DEBUG("%s: current services:0x%x", __FUNCTION__, btc_dm_cb.btc_enabled_services);
@@ -710,7 +711,7 @@ bt_status_t btc_dm_disable_service(tBTA_SERVICE_ID service_id)
{
tBTA_SERVICE_ID *p_id = &service_id;
btc_dm_cb.btc_enabled_services &= (tBTA_SERVICE_MASK)(~(1 << service_id));
btc_dm_cb.btc_enabled_services &= (tBTA_SERVICE_MASK)(~(1ULL << service_id));
BTC_TRACE_DEBUG("%s: Current Services:0x%x", __FUNCTION__, btc_dm_cb.btc_enabled_services);
@@ -808,8 +809,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg)
case BTA_DM_DISABLE_EVT: {
tBTA_SERVICE_MASK service_mask = btc_get_enabled_services_mask();
for (int i = 0; i <= BTA_MAX_SERVICE_ID; i++) {
if (service_mask &
(tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i))) {
if (service_mask & BTA_SERVICE_ID_TO_SERVICE_MASK(i)) {
btc_in_execute_service_request(i, FALSE);
}
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -53,7 +53,12 @@ static void btc_init_bluetooth(void)
{
osi_alarm_create_mux();
osi_alarm_init();
bte_main_boot_entry(btc_init_callback);
if (bte_main_boot_entry(btc_init_callback) != 0) {
osi_alarm_deinit();
osi_alarm_delete_mux();
future_ready(*btc_main_get_future_p(BTC_MAIN_INIT_FUTURE), FUTURE_FAIL);
return;
}
#if (SMP_INCLUDED)
btc_config_init();
@@ -26,7 +26,7 @@ static inline void btc_cte_ble_cb_to_app(esp_ble_cte_cb_event_t event, esp_ble_c
static void btc_ble_cte_callback(tBTM_BLE_CTE_EVENT event,
tBTM_BLE_CTE_CB_PARAMS *params)
{
esp_ble_cte_cb_param_t param;
esp_ble_cte_cb_param_t param = {0};
bt_status_t ret;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CB;
@@ -114,9 +114,11 @@ void btc_to_bta_response(tBTA_GATTS_RSP *p_dest, esp_gatt_rsp_t *p_src)
{
p_dest->attr_value.auth_req = p_src->attr_value.auth_req;
p_dest->attr_value.handle = p_src->attr_value.handle;
p_dest->attr_value.len = p_src->attr_value.len;
p_dest->attr_value.offset = p_src->attr_value.offset;
memcpy(p_dest->attr_value.value, p_src->attr_value.value, ESP_GATT_MAX_ATTR_LEN);
uint16_t copy_len = (p_src->attr_value.len <= ESP_GATT_MAX_ATTR_LEN)
? p_src->attr_value.len : ESP_GATT_MAX_ATTR_LEN;
p_dest->attr_value.len = copy_len; /* match actual bytes copied (defensive if src len > buffer) */
memcpy(p_dest->attr_value.value, p_src->attr_value.value, copy_len);
}
uint16_t get_uuid16(tBT_UUID *p_uuid)
@@ -146,13 +148,18 @@ uint16_t set_read_value(uint8_t *gattc_if, esp_ble_gattc_cb_param_t *p_dest, tBT
if (( p_src->status == BTA_GATT_OK ) && (p_src->p_value != NULL))
{
BTC_TRACE_DEBUG("%s len = %d ", __func__, p_src->p_value->len);
p_dest->read.value_len = p_src->p_value->len;
if ( p_src->p_value->len > 0 && p_src->p_value->p_value != NULL ) {
p_dest->read.value_len = p_src->p_value->len;
p_dest->read.value = p_src->p_value->p_value;
len += p_src->p_value->len;
} else {
/* len>0 but p_value==NULL would leave value uninitialized; avoid that */
p_dest->read.value_len = 0;
p_dest->read.value = NULL;
}
len += p_src->p_value->len;
} else {
p_dest->read.value_len = 0;
p_dest->read.value = NULL;
}
return len;
@@ -31,7 +31,7 @@ esp_btc_creat_tab_t *btc_creat_tab_env_ptr;
#endif
static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
uint8_t max_nb_attr);
uint16_t max_nb_attr);
static inline void btc_gatts_cb_to_app(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
@@ -42,6 +42,14 @@ static inline void btc_gatts_cb_to_app(esp_gatts_cb_event_t event, esp_gatt_if_t
}
}
/* Report CREAT_ATTR_TAB error to app and reset env; use on all early-exit error paths in btc_gatts_act_create_attr_tab */
static void btc_gatts_creat_tab_fail_and_cleanup(esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
param->add_attr_tab.status = ESP_GATT_ERROR;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
}
static inline void btc_gatts_uuid_format_convert(esp_bt_uuid_t* dest_uuid, uint16_t src_uuid_len, uint8_t* src_uuid_p)
{
dest_uuid->len = src_uuid_len;
@@ -293,11 +301,13 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
//reset the env after sent the data to app
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
if (future_await(future_p) == FUTURE_FAIL) {
BTC_TRACE_ERROR("%s failed\n", __func__);
btc_gatts_creat_tab_fail_and_cleanup(gatts_if, &param);
return;
}
break;
@@ -320,10 +330,12 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
//reset the env after sent the data to app
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
if (future_await(future_p) == FUTURE_FAIL) {
BTC_TRACE_ERROR("%s failed\n", __func__);
btc_gatts_creat_tab_fail_and_cleanup(gatts_if, &param);
return;
}
break;
@@ -338,9 +350,24 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
if (future_await(future_p) == FUTURE_FAIL) {
BTC_TRACE_ERROR("%s failed\n", __func__);
btc_gatts_creat_tab_fail_and_cleanup(gatts_if, &param);
return;
}
} else {
/* svc_start_hdl == 0: service not created, report error and return */
param.add_attr_tab.status = ESP_GATT_ERROR;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
} else {
/* incl_svc_desc == NULL: no BTA call, future never completed; report error and return */
param.add_attr_tab.status = ESP_GATT_INVALID_PDU;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
break;
}
@@ -357,6 +384,20 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
svc_hal = btc_creat_tab_env.svc_start_hdl;
if((gatts_attr_db[i].att_desc.value) == NULL){
BTC_TRACE_ERROR("%s Characteristic declaration should not be NULL\n", __func__);
param.add_attr_tab.status = ESP_GATT_INVALID_PDU;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
else if (i + 1 >= max_nb_attr) {
BTC_TRACE_ERROR("%s Characteristic declaration at index %d missing value attribute\n",
__func__, i);
param.add_attr_tab.status = ESP_GATT_INVALID_PDU;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
else{
char_property = (uint8_t)(*(uint8_t*)(gatts_attr_db[i].att_desc.value));
@@ -372,9 +413,17 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
if (future_await(future_p) == FUTURE_FAIL) {
BTC_TRACE_ERROR("%s failed\n", __func__);
btc_gatts_creat_tab_fail_and_cleanup(gatts_if, &param);
return;
}
}
} else {
/* svc_start_hdl == 0: service not created, report error and return */
param.add_attr_tab.status = ESP_GATT_ERROR;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
break;
@@ -413,8 +462,16 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
if (future_await(future_p) == FUTURE_FAIL) {
BTC_TRACE_ERROR("%s failed\n", __func__);
btc_gatts_creat_tab_fail_and_cleanup(gatts_if, &param);
return;
}
} else {
/* svc_start_hdl == 0: service not created, report error and return */
param.add_attr_tab.status = ESP_GATT_ERROR;
btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, &param);
memset(&btc_creat_tab_env, 0, sizeof(esp_btc_creat_tab_t));
future_free(future_p);
return;
}
break;
}
@@ -440,9 +497,9 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
}
static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
uint8_t max_nb_attr)
uint16_t max_nb_attr)
{
uint8_t svc_num = 0;
uint16_t svc_num = 0;
uint16_t uuid = 0;
for(int i = 0; i < max_nb_attr; i++) {
@@ -601,7 +658,12 @@ static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
case BTA_GATTS_ADD_CHAR_EVT: {
uint16_t index = btc_creat_tab_env.handle_idx;
btc_creat_tab_env.handles[index] = p_data->add_result.attr_id - 1;
btc_creat_tab_env.handles[index+1] = p_data->add_result.attr_id;
if (index + 1 < btc_creat_tab_env.num_handle) {
btc_creat_tab_env.handles[index+1] = p_data->add_result.attr_id;
} else {
BTC_TRACE_ERROR("%s handles[%d+1] out of bounds (num_handle=%d)",
__func__, index, btc_creat_tab_env.num_handle);
}
break;
}
case BTA_GATTS_ADD_CHAR_DESCR_EVT: {
@@ -27,7 +27,7 @@ static inline void btc_iso_ble_cb_to_app(esp_ble_iso_cb_event_t event, esp_ble_i
static void btc_ble_iso_callback(tBTM_BLE_ISO_EVENT event,
tBTM_BLE_ISO_CB_PARAMS *params)
{
esp_ble_iso_cb_param_t param;
esp_ble_iso_cb_param_t param = {0};
bt_status_t ret;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CB;
@@ -681,10 +681,6 @@
#define BTA_DM_QOS_INCLUDED FALSE
#endif
#ifndef BTA_PAN_INCLUDED
#define BTA_PAN_INCLUDED FALSE
#endif
#ifndef BTA_HD_INCLUDED
#define BTA_HD_INCLUDED FALSE
#endif
@@ -223,13 +223,13 @@ static void start_up(void)
}
#endif
if ((bluedroid_config_get()->get_sc_enabled())) {
controller_param.secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(controller_param.features_classic[2].as_array);
if (controller_param.secure_connections_supported) {
response = AWAIT_COMMAND(controller_param.packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED));
controller_param.packet_parser->parse_generic_command_complete(response);
if ((bluedroid_config_get()->get_sc_enabled())) {
controller_param.secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(controller_param.features_classic[2].as_array);
if (controller_param.secure_connections_supported) {
response = AWAIT_COMMAND(controller_param.packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED));
controller_param.packet_parser->parse_generic_command_complete(response);
}
}
}
#if (BLE_INCLUDED == TRUE)
#if (CLASSIC_BT_INCLUDED)
@@ -546,7 +546,7 @@ static uint8_t get_ble_resolving_list_max_size(void)
return controller_param.ble_resolving_list_max_size;
}
static void set_ble_resolving_list_max_size(int resolving_list_max_size)
static void set_ble_resolving_list_max_size(uint8_t resolving_list_max_size)
{
assert(controller_param.readable);
assert(controller_param.ble_supported);
@@ -78,7 +78,7 @@ typedef struct controller_t {
uint8_t (*get_ble_white_list_size)(void);
uint8_t (*get_ble_resolving_list_max_size)(void);
void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
void (*set_ble_resolving_list_max_size)(uint8_t resolving_list_max_size);
#if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_50_EXTEND_ADV_EN == TRUE)
+11 -6
View File
@@ -34,7 +34,6 @@
#include "esp_bt.h"
#endif
#include "esp_bluedroid_hci.h"
#include "stack/hcimsgs.h"
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
#include "l2c_int.h"
@@ -319,9 +318,12 @@ static void hci_packet_complete(BT_HDR *packet){
}
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
bool host_recv_adv_packet(uint8_t *packet)
bool host_recv_adv_packet(uint8_t *packet, uint16_t len)
{
assert(packet);
if (len < 4) {
return false;
}
if(packet[0] == DATA_TYPE_EVENT && packet[1] == HCI_BLE_EVENT) {
if(packet[3] == HCI_BLE_ADV_PKT_RPT_EVT || packet[3] == HCI_BLE_DIRECT_ADV_EVT
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
@@ -543,7 +545,7 @@ static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt)
BT_HDR* packet = (BT_HDR *)linked_pkt->data;
stream = packet->data + packet->offset;
assert(host_recv_adv_packet(stream) == true);
assert(host_recv_adv_packet(stream, packet->len) == true);
STREAM_TO_UINT8(type, stream);
packet->offset++;
@@ -588,7 +590,10 @@ static void host_send_pkt_available_cb(void)
void bt_record_hci_data(uint8_t *data, uint16_t len)
{
#if (BT_HCI_LOG_INCLUDED == TRUE)
if ((data[0] == DATA_TYPE_EVENT) && (data[1] == HCI_BLE_EVENT) && ((data[3] == HCI_BLE_ADV_PKT_RPT_EVT) || (data[3] == HCI_BLE_DIRECT_ADV_EVT)
if (len < 2) {
return;
}
if ((len >= 4) && (data[0] == DATA_TYPE_EVENT) && (data[1] == HCI_BLE_EVENT) && ((data[3] == HCI_BLE_ADV_PKT_RPT_EVT) || (data[3] == HCI_BLE_DIRECT_ADV_EVT)
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|| (data[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT)
#endif // (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
@@ -641,7 +646,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
}
#endif // #if (BLE_FEAT_ISO_EN == TRUE)
bool is_adv_rpt = host_recv_adv_packet(data);
bool is_adv_rpt = host_recv_adv_packet(data, len);
if (!is_adv_rpt) {
pkt_size = BT_HDR_SIZE + len;
@@ -700,7 +705,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);
BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
BTTRC_DUMP_BUFFER("Recv Pkt", data, len);
return 0;
}
+11 -7
View File
@@ -117,7 +117,7 @@ int hci_start_up(void)
hci_host_thread = osi_thread_create(HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, HCI_HOST_TASK_PRIO, HCI_HOST_TASK_PINNED_TO_CORE,
HCI_HOST_TASK_WORKQUEUE_NUM, workqueue_len);
if (hci_host_thread == NULL) {
return -2;
goto error;
}
osi_event_bind(hci_host_env.downstream_data_ready, hci_host_thread, HCI_DOWNSTREAM_DATA_QUEUE_IDX);
@@ -137,13 +137,15 @@ error:
void hci_shut_down(void)
{
hci_host_startup_flag = false;
/* Close HAL and cleanup before freeing thread: hal->open() and osi_event_bind()
* stored references to hci_host_thread; they must not use it after osi_thread_free(). */
if (hci_host_thread != NULL) {
hal->close();
packet_fragmenter->cleanup();
}
hci_layer_deinit_env();
packet_fragmenter->cleanup();
//low_power_manager->cleanup();
hal->close();
osi_thread_free(hci_host_thread);
hci_host_thread = NULL;
}
@@ -445,7 +447,7 @@ static bool filter_incoming_event(BT_HDR *packet)
{
pkt_linked_item_t *wait_entry = NULL;
hci_cmd_metadata_t *metadata = NULL;
uint8_t *stream = packet->data + packet->offset;
uint8_t *stream;
uint8_t event_code;
command_opcode_t opcode;
@@ -453,6 +455,8 @@ static bool filter_incoming_event(BT_HDR *packet)
return true;
}
stream = packet->data + packet->offset;
if (packet->len < HCI_EVENT_PREAMBLE_SIZE) {
HCI_TRACE_WARNING("dropping too short HCI event (len=%u)", packet->len);
osi_free(packet);
@@ -250,6 +250,8 @@ static BT_HDR *make_command_no_params(uint16_t opcode)
static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out)
{
BT_HDR *packet = HCI_GET_CMD_BUF(parameter_size);
assert(packet != NULL);
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(packet);
metadata->opcode = opcode;
@@ -73,9 +73,10 @@ static void fragment_and_dispatch(BT_HDR *packet)
uint16_t continuation_handle;
uint16_t max_data_size, max_packet_size, remaining_length;
uint16_t event = packet->event & MSG_EVT_MASK;
uint8_t *stream = packet->data + packet->offset;
uint8_t *stream;
assert(packet != NULL);
stream = packet->data + packet->offset;
// We only fragment ACL packets
if (event != MSG_STACK_TO_HC_HCI_ACL) {
@@ -152,10 +152,6 @@
#include "bta_gatts_int.h"
#endif
#if BTA_PAN_INCLUDED==TRUE
#include "bta_pan_int.h"
#endif
#if BTA_PBA_CLIENT_INCLUDED == TRUE
#include "bta_pba_client_int.h"
#endif
@@ -481,9 +477,6 @@ bt_status_t BTE_InitStack(void)
}
memset((void *)bta_jv_cb_ptr, 0, sizeof(tBTA_JV_CB));
#endif //JV
#if BTA_HS_INCLUDED == TRUE
memset((void *)bta_hs_cb_ptr, 0, sizeof(tBTA_HS_CB));
#endif
#if BTA_SDP_INCLUDED == TRUE
if ((bta_sdp_cb_ptr = (tBTA_SDP_CB *)osi_malloc(sizeof(tBTA_SDP_CB))) == NULL) {
goto error_exit;
@@ -525,9 +518,6 @@ bt_status_t BTE_InitStack(void)
}
memset((void *)bta_hd_cb_ptr, 0, sizeof(tBTA_HD_CB));
#endif
#if BTA_HL_INCLUDED==TRUE
memset((void *)bta_hl_cb_ptr, 0, sizeof(tBTA_HL_CB));
#endif
#if GATTC_INCLUDED==TRUE
if ((bta_gattc_cb_ptr = (tBTA_GATTC_CB *)osi_malloc(sizeof(tBTA_GATTC_CB))) == NULL) {
goto error_exit;
@@ -540,9 +530,6 @@ bt_status_t BTE_InitStack(void)
}
memset((void *)bta_gatts_cb_ptr, 0, sizeof(tBTA_GATTS_CB));
#endif
#if BTA_PAN_INCLUDED==TRUE
memset((void *)bta_pan_cb_ptr, 0, sizeof(tBTA_PAN_CB));
#endif
#if BTA_PBA_CLIENT_INCLUDED == TRUE
if ((bta_pba_client_cb_ptr = (tBTA_PBA_CLIENT_CB *)osi_malloc(sizeof(tBTA_PBA_CLIENT_CB))) == NULL) {
goto error_exit;
+9 -1
View File
@@ -86,7 +86,10 @@ int bte_main_boot_entry(bluedroid_init_done_cb_t cb)
bluedroid_init_done_cb = cb;
osi_init();
if (osi_init() != 0) {
APPL_TRACE_ERROR("%s failed to initialize OS layer.\n", __func__);
return -1;
}
//Enable HCI
bte_main_enable();
@@ -235,6 +238,11 @@ void bte_main_lpm_wake_bt_device(void)
******************************************************************************/
void bte_main_hci_send (BT_HDR *p_msg, UINT16 event)
{
if (!p_msg) {
APPL_TRACE_ERROR("%s null message\n", __func__);
return;
}
UINT16 sub_event = event & BT_SUB_EVT_MASK; /* local controller ID */
p_msg->event = event;
@@ -362,128 +362,131 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L
}
else {
p = (tACL_CONN *)osi_malloc(sizeof(tACL_CONN));
if (p && !list_append(btm_cb.p_acl_db_list, p)) {
if (p == NULL) {
BTM_TRACE_ERROR("btm_acl_created: osi_malloc failed for tACL_CONN\n");
return;
}
if (!list_append(btm_cb.p_acl_db_list, p)) {
BTM_TRACE_ERROR("btm_acl_created: list_append failed\n");
osi_free(p);
return;
}
if (p) {
memset(p, 0, sizeof(tACL_CONN));
p->in_use = TRUE;
p->hci_handle = hci_handle;
p->link_role = link_role;
p->link_up_issued = FALSE;
memcpy (p->remote_addr, bda, BD_ADDR_LEN);
/* Set the default version of the peer device to version4.0 before exchange the version with it.
If the peer device act as a master and don't exchange the version with us, then it can only use the
legacy connect instead of secure connection in the pairing step. */
p->lmp_version = HCI_PROTO_VERSION_4_0;
memset(p, 0, sizeof(tACL_CONN));
p->in_use = TRUE;
p->hci_handle = hci_handle;
p->link_role = link_role;
p->link_up_issued = FALSE;
memcpy (p->remote_addr, bda, BD_ADDR_LEN);
/* Set the default version of the peer device to version4.0 before exchange the version with it.
If the peer device act as a master and don't exchange the version with us, then it can only use the
legacy connect instead of secure connection in the pairing step. */
p->lmp_version = HCI_PROTO_VERSION_4_0;
#if BLE_INCLUDED == TRUE
p->transport = transport;
p->transport = transport;
#if BLE_PRIVACY_SPT == TRUE
if (transport == BT_TRANSPORT_LE) {
btm_ble_refresh_local_resolvable_private_addr(bda,
btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr);
}
if (transport == BT_TRANSPORT_LE) {
btm_ble_refresh_local_resolvable_private_addr(bda,
btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr);
}
#else
p->conn_addr_type = BLE_ADDR_PUBLIC;
memcpy(p->conn_addr, &controller_get_interface()->get_address()->address, BD_ADDR_LEN);
BTM_TRACE_DEBUG ("conn_addr: RemBdAddr: %02x%02x%02x%02x%02x%02x\n",
p->conn_addr[0], p->conn_addr[1], p->conn_addr[2], p->conn_addr[3], p->conn_addr[4], p->conn_addr[5]);
p->conn_addr_type = BLE_ADDR_PUBLIC;
memcpy(p->conn_addr, &controller_get_interface()->get_address()->address, BD_ADDR_LEN);
BTM_TRACE_DEBUG ("conn_addr: RemBdAddr: %02x%02x%02x%02x%02x%02x\n",
p->conn_addr[0], p->conn_addr[1], p->conn_addr[2], p->conn_addr[3], p->conn_addr[4], p->conn_addr[5]);
#endif
#endif
#if (CLASSIC_BT_INCLUDED == TRUE)
p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
p->p_pm_mode_db = btm_pm_sm_alloc();
p->p_pm_mode_db = btm_pm_sm_alloc();
#if BTM_PM_DEBUG == TRUE
BTM_TRACE_DEBUG( "btm_pm_sm_alloc handle:%d st:%d", hci_handle, p->p_pm_mode_db->state);
BTM_TRACE_DEBUG( "btm_pm_sm_alloc handle:%d st:%d", hci_handle, p->p_pm_mode_db->state);
#endif // BTM_PM_DEBUG
#endif // (CLASSIC_BT_INCLUDED == TRUE)
#if (CLASSIC_BT_INCLUDED == TRUE)
btm_sec_update_legacy_auth_state(p, BTM_ACL_LEGACY_AUTH_NONE);
btm_sec_update_legacy_auth_state(p, BTM_ACL_LEGACY_AUTH_NONE);
#endif
if (dc) {
memcpy (p->remote_dc, dc, DEV_CLASS_LEN);
}
if (dc) {
memcpy (p->remote_dc, dc, DEV_CLASS_LEN);
}
if (bdn) {
memcpy (p->remote_name, bdn, BTM_MAX_REM_BD_NAME_LEN);
}
if (bdn) {
memcpy (p->remote_name, bdn, BTM_MAX_REM_BD_NAME_LEN);
}
/* if BR/EDR do something more */
if (transport == BT_TRANSPORT_BR_EDR) {
btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
btsnd_hcic_rmt_ver_req (p->hci_handle);
}
p_dev_rec = btm_find_dev_by_handle (hci_handle);
/* if BR/EDR do something more */
if (transport == BT_TRANSPORT_BR_EDR) {
btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
btsnd_hcic_rmt_ver_req (p->hci_handle);
}
p_dev_rec = btm_find_dev_by_handle (hci_handle);
#if (BLE_INCLUDED == TRUE)
if (p_dev_rec ) {
BTM_TRACE_DEBUG ("device_type=0x%x\n", p_dev_rec->device_type);
}
if (p_dev_rec ) {
BTM_TRACE_DEBUG ("device_type=0x%x\n", p_dev_rec->device_type);
}
#endif
if (p_dev_rec && !(transport == BT_TRANSPORT_LE)) {
if (!p_dev_rec->remote_secure_connection_previous_state) {
/* If remote features already known, copy them and continue connection setup */
if ((p_dev_rec->num_read_pages) &&
(p_dev_rec->num_read_pages <= (HCI_EXT_FEATURES_PAGE_MAX + 1))) {
memcpy (p->peer_lmp_features, p_dev_rec->features,
(HCI_FEATURE_BYTES_PER_PAGE * p_dev_rec->num_read_pages));
p->num_read_pages = p_dev_rec->num_read_pages;
if (p_dev_rec && !(transport == BT_TRANSPORT_LE)) {
if (!p_dev_rec->remote_secure_connection_previous_state) {
/* If remote features already known, copy them and continue connection setup */
if ((p_dev_rec->num_read_pages) &&
(p_dev_rec->num_read_pages <= (HCI_EXT_FEATURES_PAGE_MAX + 1))) {
memcpy (p->peer_lmp_features, p_dev_rec->features,
(HCI_FEATURE_BYTES_PER_PAGE * p_dev_rec->num_read_pages));
p->num_read_pages = p_dev_rec->num_read_pages;
#if (CLASSIC_BT_INCLUDED == TRUE)
const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
#endif ///CLASSIC_BT_INCLUDED == TRUE
/* Store the Peer Security Capabilities (in SM4 and rmt_sec_caps) */
/* Store the Peer Security Capabilities (in SM4 and rmt_sec_caps) */
#if (SMP_INCLUDED == TRUE)
btm_sec_set_peer_sec_caps(p, p_dev_rec);
btm_sec_set_peer_sec_caps(p, p_dev_rec);
#endif ///SMP_INCLUDED == TRUE
#if (CLASSIC_BT_INCLUDED == TRUE)
BTM_TRACE_API("%s: pend:%d\n", __FUNCTION__, req_pend);
if (req_pend) {
/* Request for remaining Security Features (if any) */
l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
}
#endif ///CLASSIC_BT_INCLUDED == TRUE
btm_establish_continue (p);
return;
BTM_TRACE_API("%s: pend:%d\n", __FUNCTION__, req_pend);
if (req_pend) {
/* Request for remaining Security Features (if any) */
l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
}
} else {
/* If remote features indicated secure connection (SC) mode, check the remote features again*/
/* this is to prevent from BIAS attack where attacker can downgrade SC mode*/
btm_read_remote_features (p->hci_handle);
#endif ///CLASSIC_BT_INCLUDED == TRUE
btm_establish_continue (p);
return;
}
}
#if (BLE_INCLUDED == TRUE)
/* If here, features are not known yet */
if (p_dev_rec && transport == BT_TRANSPORT_LE) {
#if BLE_PRIVACY_SPT == TRUE
btm_ble_get_acl_remote_addr (p_dev_rec, p->active_remote_addr,
&p->active_remote_addr_type);
#endif
if (link_role == HCI_ROLE_MASTER) {
btsnd_hcic_ble_read_remote_feat(p->hci_handle);
} else if (HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array)
&& link_role == HCI_ROLE_SLAVE) {
btsnd_hcic_rmt_ver_req (p->hci_handle);
} else {
btm_establish_continue(p);
}
} else
#endif
{
} else {
/* If remote features indicated secure connection (SC) mode, check the remote features again*/
/* this is to prevent from BIAS attack where attacker can downgrade SC mode*/
btm_read_remote_features (p->hci_handle);
}
/* read page 1 - on rmt feature event for buffer reasons */
return;
}
#if (BLE_INCLUDED == TRUE)
/* If here, features are not known yet */
if (p_dev_rec && transport == BT_TRANSPORT_LE) {
#if BLE_PRIVACY_SPT == TRUE
btm_ble_get_acl_remote_addr (p_dev_rec, p->active_remote_addr,
&p->active_remote_addr_type);
#endif
if (link_role == HCI_ROLE_MASTER) {
btsnd_hcic_ble_read_remote_feat(p->hci_handle);
} else if (HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array)
&& link_role == HCI_ROLE_SLAVE) {
btsnd_hcic_rmt_ver_req (p->hci_handle);
} else {
btm_establish_continue(p);
}
} else
#endif
{
btm_read_remote_features (p->hci_handle);
}
/* read page 1 - on rmt feature event for buffer reasons */
return;
}
}
@@ -593,11 +596,9 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport)
#if (CLASSIC_BT_INCLUDED == TRUE)
list_remove(btm_cb.p_pm_mode_db_list, p->p_pm_mode_db);
#endif // #if (CLASSIC_BT_INCLUDED == TRUE)
/* Clear the ACL connection data */
memset(p, 0, sizeof(tACL_CONN));
if (list_remove(btm_cb.p_acl_db_list, p)) {
p = NULL;
}
/* Remove and free the ACL connection data */
list_remove(btm_cb.p_acl_db_list, p);
p = NULL;
}
}
@@ -2173,9 +2173,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
case SMP_OOB_REQ_EVT:
case SMP_NC_REQ_EVT:
case SMP_SC_OOB_REQ_EVT:
/* fall through */
p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
/* fall through */
case SMP_SEC_REQUEST_EVT:
if (event == SMP_SEC_REQUEST_EVT && btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) {
BTM_TRACE_DEBUG("%s: Ignoring SMP Security request", __func__);
@@ -203,8 +203,6 @@ static const char *btm_ble_hci_status_to_str(tHCI_STATUS status)
default:
return "Invalid HCI status code.";
}
return NULL;
}
#endif /* !UC_BT_STACK_NO_LOG */
@@ -384,6 +382,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR
if ((status = btm_ble_ext_adv_params_validate(params)) != BTM_SUCCESS) {
BTM_TRACE_ERROR("%s, invalid extend adv params.", __func__);
goto end;
}
if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE) {
@@ -567,10 +566,6 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err);
status = BTM_HCI_ERROR | err;
}
osi_free(instance);
osi_free(duration);
osi_free(max_events);
} else {
// enable = false, num == 0 or ext_adv = NULL
@@ -584,6 +579,15 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
end:
if (instance) {
osi_free(instance);
}
if (duration) {
osi_free(duration);
}
if (max_events) {
osi_free(max_events);
}
if (!enable && status == BTM_SUCCESS) {
// disable all ext adv
@@ -602,6 +606,9 @@ end:
for (uint8_t i = 0; i < num; i++)
{
uint8_t index = ext_adv[i].instance;
if (index >= MAX_BLE_ADV_INSTANCE) {
continue;
}
adv_record[index].invalid = false;
adv_record[index].enabled = false;
adv_record[index].instance = INVALID_VALUE_8BIT;
@@ -616,6 +623,9 @@ end:
for (uint8_t i = 0; i < num; i++)
{
uint8_t index = ext_adv[i].instance;
if (index >= MAX_BLE_ADV_INSTANCE) {
continue;
}
adv_record[index].invalid = true;
adv_record[index].enabled = true;
adv_record[index].instance = ext_adv[i].instance;
@@ -441,12 +441,12 @@ tBTM_SEC_DEV_REC *btm_find_dev_by_identity_addr(BD_ADDR bd_addr, UINT8 addr_type
context.free_check = FALSE;
p_node = list_foreach(btm_cb.p_sec_dev_rec_list, btm_find_sec_dev_in_list, &context);
if (p_node) {
p_dev_rec = list_node(p_node);
p_dev_rec = list_node(p_node);
if ((p_dev_rec->ble.static_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
(addr_type & (~BLE_ADDR_TYPE_ID_BIT))) {
BTM_TRACE_WARNING("%s find pseudo->random match with diff addr type: %d vs %d",
__func__, p_dev_rec->ble.static_addr_type, addr_type);
}
}
}
return p_dev_rec;
#endif
@@ -1979,7 +1979,7 @@ UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
}
/* 16bits/32bits/128bits Service Data */
if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_DATA &&
p_data && p_data->p_service_data->len != 0 && p_data->p_service_data->p_val) {
p_data && p_data->p_service_data && p_data->p_service_data->len != 0 && p_data->p_service_data->p_val) {
if (len > (p_data->p_service_data->service_uuid.len + MIN_ADV_LENGTH)) {
if (p_data->p_service_data->len > (len - MIN_ADV_LENGTH)) {
cp_len = len - MIN_ADV_LENGTH - p_data->p_service_data->service_uuid.len;
@@ -3063,7 +3063,7 @@ static void btm_adv_pkt_handler(void *arg)
STREAM_TO_UINT8 (hci_evt_len, p);
STREAM_TO_UINT8 (ble_sub_code, p);
if (ble_sub_code == HCI_BLE_ADV_PKT_RPT_EVT) {
btm_ble_process_adv_pkt(p);
btm_ble_process_adv_pkt(p, hci_evt_len);
} else if (ble_sub_code == HCI_BLE_ADV_DISCARD_REPORT_EVT) {
btm_ble_process_adv_discard_evt(p);
} else if (ble_sub_code == HCI_BLE_DIRECT_ADV_EVT) {
@@ -3083,7 +3083,6 @@ static void btm_adv_pkt_handler(void *arg)
}
UNUSED(hci_evt_code);
UNUSED(hci_evt_len);
}
/*******************************************************************************
@@ -3099,7 +3098,7 @@ static void btm_adv_pkt_handler(void *arg)
** Returns void
**
*******************************************************************************/
void btm_ble_process_adv_pkt (UINT8 *p_data)
void btm_ble_process_adv_pkt (UINT8 *p_data, UINT8 evt_len)
{
BD_ADDR bda;
UINT8 evt_type = 0, *p = p_data;
@@ -3119,10 +3118,22 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
return;
}
/* sub_code(1) already consumed by caller, need at least num_reports(1) */
if (evt_len < 2) {
BTM_TRACE_ERROR("btm_ble_process_adv_pkt: evt too short (len=%u)", evt_len);
return;
}
/* Extract the number of reports in this event. */
STREAM_TO_UINT8(num_reports, p);
UINT8 remaining = evt_len - 2;
while (num_reports--) {
/* Per-report minimum: evt_type(1) + addr_type(1) + bda(6) + data_len(1) + rssi(1) = 10 */
if (remaining < 10) {
BTM_TRACE_ERROR("btm_ble_process_adv_pkt: remaining %u too short for report", remaining);
break;
}
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
/* Save current report start position for address resolution callback */
UINT8 *pp = p;
@@ -3131,8 +3142,6 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
STREAM_TO_UINT8 (evt_type, p);
STREAM_TO_UINT8 (addr_type, p);
STREAM_TO_BDADDR (bda, p);
//BTM_TRACE_ERROR("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x\n",
// bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
#if (!CONTROLLER_RPA_LIST_ENABLE)
@@ -3142,17 +3151,21 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
/* map address to security record */
match = btm_identity_addr_to_random_pseudo(bda, &addr_type, FALSE);
// BTM_TRACE_ERROR("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x\n",
// bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
/* always do RRA resolution on host */
#endif
/* Validate data_len before any path (callee reads 1 + data_len + 1 = data_len+2 bytes from p) */
data_len = *p; /* read without advancing; p points to data_len byte */
if (data_len + 2 > remaining - 8) {
BTM_TRACE_ERROR("btm_ble_process_adv_pkt: data_len %u + data + rssi exceeds remaining %u", data_len, (UINT16)(remaining - 8));
break;
}
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
/* RRA path: resolve first, btm_ble_process_adv_pkt_cont will be called from callback; else process now */
if (!match && BTM_BLE_IS_RESOLVE_BDA(bda)) {
btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_adv, pp);
} else
#endif
btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE && (!CONTROLLER_RPA_LIST_ENABLE))
//save current adv addr information if p_dev_rec!= NULL
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
if(p_dev_rec) {
p_dev_rec->ble.current_addr_type = temp_addr_type;
@@ -3161,9 +3174,11 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
}
#endif
STREAM_TO_UINT8(data_len, p);
remaining -= 9; /* evt_type(1) + addr_type(1) + bda(6) + data_len(1) */
/* Advance to the next event data_len + rssi byte */
p += data_len + 1;
remaining -= (data_len + 1);
}
}
@@ -46,7 +46,7 @@ void btm_ble_iso_read_iso_tx_sync_complete(UINT8 *p)
if (cb_params.btm_read_tx_sync.status != HCI_SUCCESS) {
cb_params.btm_read_tx_sync.status = (BTM_HCI_ERROR | cb_params.btm_read_tx_sync.status);
}
cb_params.btm_read_tx_sync.conn_hdl = (cb_params.btm_read_tx_sync.conn_hdl & 0xEFF);
cb_params.btm_read_tx_sync.conn_hdl = (cb_params.btm_read_tx_sync.conn_hdl & 0x0FFF);
cb_params.btm_read_tx_sync.time_offset = (cb_params.btm_read_tx_sync.time_offset & 0xFFFFFF);
BTM_TRACE_DEBUG("read tx sync cmpl, status 0x%x conn_hdl 0x%x pkt_seq_num %d tx_time_stamp %ld time_offset %ld\n",
cb_params.btm_read_tx_sync.status, cb_params.btm_read_tx_sync.conn_hdl, cb_params.btm_read_tx_sync.pkt_seq_num,
@@ -49,6 +49,7 @@
#define BTM_BLE_META_CLEAR_IRK_LEN 1
#define BTM_BLE_META_READ_IRK_LEN 2
#define BTM_BLE_META_ADD_WL_ATTR_LEN 9
#define BTM_BLE_IRK_LIST_INVALID_INDEX 0xFF
#if CONTROLLER_RPA_LIST_ENABLE && BLE_SMP_ID_RESET_ENABLE
static bool is_deleting_zero_addr;
@@ -166,7 +167,7 @@ void btm_ble_clear_irk_index(UINT8 index)
**
** Description find the first available IRK list index
**
** Returns index from 0 ~ max (127 default)
** Returns index from 0 ~ max-1, or BTM_BLE_IRK_LIST_INVALID_INDEX if full
**
*******************************************************************************/
UINT8 btm_ble_find_irk_index(void)
@@ -187,7 +188,7 @@ UINT8 btm_ble_find_irk_index(void)
}
BTM_TRACE_ERROR ("%s failed, list full", __func__);
return i;
return BTM_BLE_IRK_LIST_INVALID_INDEX;
}
/*******************************************************************************
@@ -209,7 +210,13 @@ void btm_ble_update_resolving_list(BD_ADDR pseudo_bda, BOOLEAN add)
if (add) {
p_dev_rec->ble.in_controller_list |= BTM_RESOLVING_LIST_BIT;
if (!controller_get_interface()->supports_ble_privacy()) {
p_dev_rec->ble.resolving_list_index = btm_ble_find_irk_index();
UINT8 irk_index = btm_ble_find_irk_index();
if (irk_index != BTM_BLE_IRK_LIST_INVALID_INDEX) {
p_dev_rec->ble.resolving_list_index = irk_index;
} else {
p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
BTM_TRACE_WARNING("%s: IRK list full, cannot add to resolving list", __func__);
}
}
} else {
p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
@@ -780,8 +780,8 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len,
if(ble_cb && ble_cb->update_exceptional_list_cmp_cb) {
(*ble_cb->update_exceptional_list_cmp_cb)(status, subcode, length, p);
}
break;
#endif // ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE))
break;
}
case HCI_VENDOR_BLE_CLEAR_ADV: {
uint8_t status;
@@ -322,7 +322,7 @@ void btm_sco_check_send_pkts (UINT16 sco_inx)
}
}
void btm_sco_process_num_completed_pkts (UINT8 *p)
void btm_sco_process_num_completed_pkts (UINT8 *p, UINT8 evt_len)
{
UINT8 num_handles, xx;
UINT16 handle;
@@ -330,7 +330,20 @@ void btm_sco_process_num_completed_pkts (UINT8 *p)
UINT16 sco_inx;
tSCO_CB *p_cb = &btm_cb.sco_cb;
tSCO_CONN * p_ccb;
if (evt_len < 1) {
BTM_TRACE_ERROR ("btm_sco_process_num_completed_pkts: evt too short (len=%u)", evt_len);
return;
}
STREAM_TO_UINT8 (num_handles, p);
if (num_handles > (evt_len - 1) / 4) {
BTM_TRACE_ERROR ("btm_sco_process_num_completed_pkts: num_handles %u exceeds evt_len %u, truncating",
num_handles, evt_len);
num_handles = (evt_len - 1) / 4;
}
for (xx = 0; xx < num_handles; xx++) {
STREAM_TO_UINT16 (handle, p);
STREAM_TO_UINT16 (num_sent, p);
@@ -401,7 +401,7 @@ extern "C" {
void btm_ble_timeout(TIMER_LIST_ENT *p_tle);
#if (BLE_42_SCAN_EN == TRUE)
void btm_ble_process_adv_pkt (UINT8 *p);
void btm_ble_process_adv_pkt (UINT8 *p, UINT8 evt_len);
void btm_ble_process_adv_discard_evt(UINT8 *p);
void btm_ble_process_direct_adv_pkt (UINT8 *p);
bool btm_ble_adv_pkt_ready(void);
@@ -1192,7 +1192,7 @@ void btm_pm_proc_ssr_evt (UINT8 *p, UINT16 evt_len);
void btm_sco_chk_pend_unpark (UINT8 hci_status, UINT16 hci_handle);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs);
void btm_sco_process_num_completed_pkts (UINT8 *p);
void btm_sco_process_num_completed_pkts (UINT8 *p, UINT8 evt_len);
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
#else
#define btm_sco_chk_pend_unpark(hci_status, hci_handle)
+219 -41
View File
@@ -100,7 +100,7 @@ static void btu_hcif_hardware_error_evt (UINT8 *p);
static void btu_hcif_flush_occured_evt (void);
static void btu_hcif_role_change_evt (UINT8 *p);
#endif // #if (CLASSIC_BT_INCLUDED == TRUE)
static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p);
static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p, UINT8 evt_len);
#if (CLASSIC_BT_INCLUDED == TRUE)
static void btu_hcif_mode_change_evt (UINT8 *p);
@@ -194,14 +194,14 @@ static void btu_ble_periodic_adv_sync_trans_recv(UINT8 *p);
#if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE)
void btu_ble_create_big_cmd_status(UINT8 status);
static void btu_ble_big_create_complete_evt(UINT8 *p);
static void btu_ble_big_create_complete_evt(UINT8 *p, UINT8 evt_len);
void btu_ble_big_terminate_cmd_status(UINT8 status);
static void btu_ble_big_terminate_complete_evt(UINT8 *p);
#endif // #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE)
#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE)
static void btu_ble_create_big_sync_cmd_status(UINT8 status);
static void btu_ble_big_sync_establish_evt(UINT8 *p);
static void btu_ble_big_sync_establish_evt(UINT8 *p, UINT8 evt_len);
static void btu_ble_big_sync_lost_evt(UINT8 *p);
static void btu_ble_biginfo_adv_report_evt(UINT8 *p);
#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE)
@@ -222,10 +222,10 @@ static void btu_ble_cis_disconnected(UINT16 handle, UINT8 reason);
#if (BLE_FEAT_CTE_EN == TRUE)
#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
static void btu_ble_cte_connless_iq_report_evt(UINT8 *p);
static void btu_ble_cte_connless_iq_report_evt(UINT8 *p, UINT8 evt_len);
#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE)
static void btu_ble_cte_conn_iq_report_evt(UINT8 *p);
static void btu_ble_cte_conn_iq_report_evt(UINT8 *p, UINT8 evt_len);
static void btu_ble_cte_req_failed_evt(UINT8 *p);
#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE)
#endif // #if (BLE_FEAT_CTE_EN == TRUE)
@@ -241,7 +241,7 @@ static void btu_ble_subrate_change_evt(UINT8 *p);
#if (BT_BLE_FEAT_PAWR_EN == TRUE)
static void btu_ble_pa_subevt_data_request_evt(UINT8 *p);
static void btu_ble_pa_response_report_evt(UINT8 *p);
static void btu_ble_pa_response_report_evt(UINT8 *p, UINT8 evt_len);
#endif // (BT_BLE_FEAT_PAWR_EN == TRUE)
#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
@@ -250,8 +250,8 @@ static void btu_ble_cs_read_remote_fae_tab_evt(UINT8 *p);
static void btu_ble_cs_security_enable_cmpl_evt(UINT8 *p);
static void btu_ble_cs_config_cmpl_evt(UINT8 *p);
static void btu_ble_cs_proc_enable_cmpl_evt(UINT8 *p);
static void btu_ble_cs_subevt_result_evt(UINT8 *p);
static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p);
static void btu_ble_cs_subevt_result_evt(UINT8 *p, UINT8 evt_len);
static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p, UINT8 evt_len);
#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
#if (BLE_42_ADV_EN == TRUE)
@@ -287,9 +287,20 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
#if BLE_INCLUDED == TRUE
UINT8 ble_sub_code;
#endif
if (p_msg->len < 2) {
HCI_TRACE_ERROR("%s: HCI event too short (len=%u), dropping", __func__, p_msg->len);
return;
}
STREAM_TO_UINT8 (hci_evt_code, p);
STREAM_TO_UINT8 (hci_evt_len, p);
if (hci_evt_len > p_msg->len - 2) {
HCI_TRACE_ERROR("%s: HCI evt 0x%02x param len %u exceeds buffer (avail=%u), dropping",
__func__, hci_evt_code, hci_evt_len, p_msg->len - 2);
return;
}
switch (hci_evt_code) {
#if (CLASSIC_BT_INCLUDED == TRUE)
case HCI_INQUIRY_COMP_EVT:
@@ -372,7 +383,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
break;
#endif // #if (CLASSIC_BT_INCLUDED == TRUE)
case HCI_NUM_COMPL_DATA_PKTS_EVT:
btu_hcif_num_compl_data_pkts_evt (p);
btu_hcif_num_compl_data_pkts_evt (p, hci_evt_len);
break;
#if (CLASSIC_BT_INCLUDED == TRUE)
case HCI_MODE_CHANGE_EVT:
@@ -469,6 +480,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
#if (BLE_INCLUDED == TRUE)
case HCI_BLE_EVENT:
if (hci_evt_len < 1) {
HCI_TRACE_ERROR("%s: BLE meta event param len %u invalid (need >= 1), dropping", __func__, hci_evt_len);
break;
}
STREAM_TO_UINT8 (ble_sub_code, p);
hci_evt_len--;
HCI_TRACE_DEBUG("BLE HCI(id=%d) event = 0x%02x)", hci_evt_code, ble_sub_code);
@@ -572,7 +587,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE)
#if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE)
case HCI_BLE_BIG_CREATE_COMPLETE_EVT:
btu_ble_big_create_complete_evt(p);
btu_ble_big_create_complete_evt(p, hci_evt_len);
break;
case HCI_BLE_BIG_TERMINATE_COMPLETE_EVT:
btu_ble_big_terminate_complete_evt(p);
@@ -580,7 +595,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
#endif // #if (BLE_FEAT_ISO_BIG_BROADCASTER_EN == TRUE)
#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE)
case HCI_BLE_BIG_SYNC_ESTABLISHED_EVT:
btu_ble_big_sync_establish_evt(p);
btu_ble_big_sync_establish_evt(p, hci_evt_len);
break;
case HCI_BLE_BIG_SYNC_LOST_EVT:
btu_ble_big_sync_lost_evt(p);
@@ -593,13 +608,13 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
#if (BLE_FEAT_CTE_EN == TRUE)
#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
case HCI_BLE_CONNLESS_IQ_REPORT_EVT:
btu_ble_cte_connless_iq_report_evt(p);
btu_ble_cte_connless_iq_report_evt(p, hci_evt_len);
break;
#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE)
case HCI_BLE_CONN_IQ_REPORT_EVT:
btu_ble_cte_conn_iq_report_evt(p);
btu_ble_cte_conn_iq_report_evt(p, hci_evt_len);
break;
case HCI_BLE_CTE_REQUEST_FAILED_EVT:
btu_ble_cte_req_failed_evt(p);
@@ -625,7 +640,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
btu_ble_pa_subevt_data_request_evt(p);
break;
case HCI_BLE_PA_RESPONSE_REPORT_EVT:
btu_ble_pa_response_report_evt(p);
btu_ble_pa_response_report_evt(p, hci_evt_len);
break;
#endif // #if (BT_BLE_FEAT_PAWR_EN == TRUE)
#if (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
@@ -645,10 +660,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
btu_ble_cs_proc_enable_cmpl_evt(p);
break;
case HCI_BLE_CS_SUBEVENT_RESULT_EVT:
btu_ble_cs_subevt_result_evt(p);
btu_ble_cs_subevt_result_evt(p, hci_evt_len);
break;
case HCI_BLE_CS_SUBEVENT_RESULT_CONTINUE_EVT:
btu_ble_cs_subevt_result_continue_evt(p);
btu_ble_cs_subevt_result_continue_evt(p, hci_evt_len);
break;
#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
}
@@ -1410,7 +1425,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
#if (BLE_FEAT_ISO_EN == TRUE)
#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE)
case HCI_BLE_BIG_TERMINATE_SYNC:
UINT16 big_handle;
UINT8 big_handle;
STREAM_TO_UINT8(status, p);
STREAM_TO_UINT8(big_handle, p);
btm_ble_big_sync_terminate_complete(status, big_handle);
@@ -1936,14 +1951,14 @@ static void btu_hcif_role_change_evt (UINT8 *p)
** Returns void
**
*******************************************************************************/
static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p)
static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p, UINT8 evt_len)
{
/* Process for L2CAP and SCO */
l2c_link_process_num_completed_pkts (p);
l2c_link_process_num_completed_pkts (p, evt_len);
/* Send on to SCO */
#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_SCO_INCLUDED == TRUE)
btm_sco_process_num_completed_pkts (p);
btm_sco_process_num_completed_pkts (p, evt_len);
#endif
}
#if (CLASSIC_BT_INCLUDED == TRUE)
@@ -2564,19 +2579,36 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len)
UINT16 evt_type = 0;
uint8_t addr_type;
BD_ADDR bda;
UINT16 remaining;
if (!p) {
HCI_TRACE_ERROR("%s, Invalid params.", __func__);
return;
}
if (evt_len < 1) {
HCI_TRACE_ERROR("%s, evt_len too short (%u)", __func__, evt_len);
return;
}
STREAM_TO_UINT8(num_reports, p);
remaining = evt_len - 1;
if (num_reports == 0) {
HCI_TRACE_ERROR("%s, Invalid number reports is 0", __func__);
}
/* Per-report fixed fields: evt_type(2) + addr_type(1) + bda(6) +
* primary_phy(1) + secondary_phy(1) + sid(1) + tx_power(1) + rssi(1) +
* per_adv_interval(2) + dir_addr_type(1) + dir_addr(6) + adv_data_len(1) = 24 */
#define EXT_ADV_RPT_FIXED_LEN 24
while (num_reports--) {
if (remaining < EXT_ADV_RPT_FIXED_LEN) {
HCI_TRACE_ERROR("%s, remaining %u too short for report (need %u)",
__func__, remaining, EXT_ADV_RPT_FIXED_LEN);
return;
}
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
/* Save current report start position for address resolution callback */
pp = p;
@@ -2624,6 +2656,14 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len)
STREAM_TO_UINT8(ext_adv_report.dir_addr_type, p);
STREAM_TO_BDADDR(ext_adv_report.dir_addr, p);
STREAM_TO_UINT8(ext_adv_report.adv_data_len, p);
remaining -= EXT_ADV_RPT_FIXED_LEN;
if (ext_adv_report.adv_data_len > remaining) {
HCI_TRACE_ERROR("%s, adv_data_len %u exceeds remaining %u",
__func__, ext_adv_report.adv_data_len, remaining);
return;
}
if (ext_adv_report.adv_data_len) {
ext_adv_report.adv_data = p;
} else {
@@ -2632,6 +2672,7 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len)
btm_ble_ext_adv_report_evt(&ext_adv_report);
p += ext_adv_report.adv_data_len;
remaining -= ext_adv_report.adv_data_len;
}
}
@@ -2948,7 +2989,7 @@ void btu_ble_create_big_cmd_status(UINT8 status)
}
}
static void btu_ble_big_create_complete_evt(UINT8 *p)
static void btu_ble_big_create_complete_evt(UINT8 *p, UINT8 evt_len)
{
HCI_TRACE_DEBUG("%s", __func__);
tBTM_BLE_BIG_CREATE_CMPL big_cmpl = {0};
@@ -2959,6 +3000,15 @@ static void btu_ble_big_create_complete_evt(UINT8 *p)
return;
}
/* Fixed fields: status(1) + big_handle(1) + big_sync_delay(3)
* + transport_latency(3) + phy(1) + nse(1) + bn(1) + pto(1) + irc(1)
* + max_pdu(2) + iso_interval(2) + num_bis(1) = 18 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 18) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=18)", __func__, evt_len);
return;
}
STREAM_TO_UINT8(big_cmpl.status, p);
STREAM_TO_UINT8(big_cmpl.big_handle, p);
STREAM_TO_UINT24(big_cmpl.big_sync_delay, p);
@@ -2972,11 +3022,14 @@ static void btu_ble_big_create_complete_evt(UINT8 *p)
STREAM_TO_UINT16(big_cmpl.iso_interval, p);
STREAM_TO_UINT8(num_bis, p);
// Validate num_bis to prevent buffer overflow
if (num_bis > BLE_ISO_BIS_MAX_COUNT) {
HCI_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT);
num_bis = BLE_ISO_BIS_MAX_COUNT;
}
if (num_bis > (evt_len - 18) / 2) {
HCI_TRACE_ERROR("%s, num_bis %d exceeds evt_len %u, truncating", __func__, num_bis, evt_len);
num_bis = (evt_len - 18) / 2;
}
big_cmpl.num_bis = num_bis;
for (uint8_t i = 0; i < num_bis; i++)
@@ -3025,7 +3078,7 @@ void btu_ble_create_big_sync_cmd_status(UINT8 status)
}
}
static void btu_ble_big_sync_establish_evt(UINT8 *p)
static void btu_ble_big_sync_establish_evt(UINT8 *p, UINT8 evt_len)
{
tBTM_BLE_BIG_SYNC_ESTAB_CMPL big_estb = {0};
UINT8 num_bis;
@@ -3035,6 +3088,15 @@ static void btu_ble_big_sync_establish_evt(UINT8 *p)
return;
}
/* Fixed fields: status(1) + big_handle(1) + transport_latency_big(3)
* + nse(1) + bn(1) + pto(1) + irc(1) + max_pdu(2) + iso_interval(2)
* + num_bis(1) = 14 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 14) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=14)", __func__, evt_len);
return;
}
STREAM_TO_UINT8(big_estb.status, p);
STREAM_TO_UINT8(big_estb.big_handle, p);
STREAM_TO_UINT24(big_estb.transport_latency_big, p);
@@ -3046,11 +3108,14 @@ static void btu_ble_big_sync_establish_evt(UINT8 *p)
STREAM_TO_UINT16(big_estb.iso_interval, p);
STREAM_TO_UINT8(num_bis, p);
// Validate num_bis to prevent buffer overflow
if (num_bis > BLE_ISO_BIS_MAX_COUNT) {
HCI_TRACE_ERROR("%s, num_bis %d exceeds BLE_ISO_BIS_MAX_COUNT %d", __func__, num_bis, BLE_ISO_BIS_MAX_COUNT);
num_bis = BLE_ISO_BIS_MAX_COUNT;
}
if (num_bis > (evt_len - 14) / 2) {
HCI_TRACE_ERROR("%s, num_bis %d exceeds evt_len %u, truncating", __func__, num_bis, evt_len);
num_bis = (evt_len - 14) / 2;
}
big_estb.num_bis = num_bis;
for (uint8_t i = 0; i < num_bis; i++)
@@ -3106,7 +3171,7 @@ static void btu_ble_biginfo_adv_report_evt(UINT8 *p)
#if (BLE_FEAT_CTE_EN == TRUE)
#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
static void btu_ble_cte_connless_iq_report_evt(UINT8 *p)
static void btu_ble_cte_connless_iq_report_evt(UINT8 *p, UINT8 evt_len)
{
tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT connless_iq_rpt = {0};
UINT8 sample_count;
@@ -3116,6 +3181,15 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p)
return;
}
/* Fixed fields: sync_handle(2) + channel_idx(1) + rssi(2)
* + rssi_ant_id(1) + cte_type(1) + slot_dur(1) + pkt_status(1)
* + periodic_evt_counter(2) + sample_count(1) = 12 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 12) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=12)", __func__, evt_len);
return;
}
STREAM_TO_UINT16(connless_iq_rpt.sync_handle, p);
STREAM_TO_UINT8(connless_iq_rpt.channel_idx, p);
STREAM_TO_UINT16(connless_iq_rpt.rssi, p);
@@ -3126,11 +3200,14 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p)
STREAM_TO_UINT16(connless_iq_rpt.periodic_evt_counter, p);
STREAM_TO_UINT8(sample_count, p);
// Validate sample_count to prevent buffer overflow
if (sample_count > BTM_BLE_CTE_MAX_SAMPLE_COUNT) {
HCI_TRACE_ERROR("%s, sample_count %d exceeds maximum %d", __func__, sample_count, BTM_BLE_CTE_MAX_SAMPLE_COUNT);
sample_count = BTM_BLE_CTE_MAX_SAMPLE_COUNT;
}
if (sample_count > (evt_len - 12) / 2) {
HCI_TRACE_ERROR("%s, sample_count %d exceeds evt_len %u, truncating", __func__, sample_count, evt_len);
sample_count = (evt_len - 12) / 2;
}
connless_iq_rpt.sample_count = sample_count;
for (uint8_t i = 0; i < sample_count; i++)
@@ -3148,7 +3225,7 @@ static void btu_ble_cte_connless_iq_report_evt(UINT8 *p)
#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE)
#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE)
static void btu_ble_cte_conn_iq_report_evt(UINT8 *p)
static void btu_ble_cte_conn_iq_report_evt(UINT8 *p, UINT8 evt_len)
{
tBTM_BLE_CTE_CONN_IQ_REPORT_EVT conn_iq_rpt = {0};
UINT8 sample_count;
@@ -3158,6 +3235,15 @@ static void btu_ble_cte_conn_iq_report_evt(UINT8 *p)
return;
}
/* Fixed fields: conn_handle(2) + rx_phy(1) + data_channel_idx(1)
* + rssi(2) + rssi_ant_id(1) + cte_type(1) + slot_dur(1) + pkt_status(1)
* + conn_evt_counter(2) + sample_count(1) = 13 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 13) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=13)", __func__, evt_len);
return;
}
STREAM_TO_UINT16(conn_iq_rpt.conn_handle, p);
STREAM_TO_UINT8(conn_iq_rpt.rx_phy, p);
STREAM_TO_UINT8(conn_iq_rpt.data_channel_idx, p);
@@ -3169,11 +3255,14 @@ static void btu_ble_cte_conn_iq_report_evt(UINT8 *p)
STREAM_TO_UINT16(conn_iq_rpt.conn_evt_counter, p);
STREAM_TO_UINT8(sample_count, p);
// Validate sample_count to prevent buffer overflow
if (sample_count > BTM_BLE_CTE_MAX_SAMPLE_COUNT) {
HCI_TRACE_ERROR("%s, sample_count %d exceeds maximum %d", __func__, sample_count, BTM_BLE_CTE_MAX_SAMPLE_COUNT);
sample_count = BTM_BLE_CTE_MAX_SAMPLE_COUNT;
}
if (sample_count > (evt_len - 13) / 2) {
HCI_TRACE_ERROR("%s, sample_count %d exceeds evt_len %u, truncating", __func__, sample_count, evt_len);
sample_count = (evt_len - 13) / 2;
}
conn_iq_rpt.sample_count = sample_count;
for (uint8_t i = 0; i < sample_count; i++)
@@ -3279,7 +3368,7 @@ static void btu_ble_pa_subevt_data_request_evt(UINT8 *p)
btm_ble_pa_subevt_data_req_evt(&pa_subevt_req_evt);
}
static void btu_ble_pa_response_report_evt(UINT8 *p)
static void btu_ble_pa_response_report_evt(UINT8 *p, UINT8 evt_len)
{
tBTM_BLE_PA_RSP_REPORT_EVT pa_rsp_rpt_evt = {0};
if (!p) {
@@ -3287,33 +3376,58 @@ static void btu_ble_pa_response_report_evt(UINT8 *p)
return;
}
/* Fixed fields: adv_handle(1) + subevt(1) + tx_status(1) + num_rsp(1) = 4 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 4) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=4)", __func__, evt_len);
return;
}
STREAM_TO_UINT8(pa_rsp_rpt_evt.adv_handle, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.subevt, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.tx_status, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.num_rsp, p);
// num_rsp is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate
UINT8 remaining = evt_len - 4;
if (pa_rsp_rpt_evt.num_rsp) {
pa_rsp_rpt_evt.rsp_data_info = osi_malloc(pa_rsp_rpt_evt.num_rsp * sizeof(tBTM_BLE_PA_RSP_DATA_INFO));
if (pa_rsp_rpt_evt.rsp_data_info)
{
for (UINT8 i = 0; i < pa_rsp_rpt_evt.num_rsp; i++)
{
/* Per-response fixed: tx_power(1)+rssi(1)+cte_type(1)+rsp_slot(1)+data_status(1)+data_len(1) = 6 */
if (remaining < 6) {
HCI_TRACE_ERROR("%s, remaining %u too short for response %d", __func__, remaining, i);
pa_rsp_rpt_evt.num_rsp = i;
break;
}
STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].tx_power, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].rssi, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].cte_type, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].rsp_slot, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].data_status, p);
STREAM_TO_UINT8(pa_rsp_rpt_evt.rsp_data_info[i].data_len, p);
// data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate
remaining -= 6;
if (pa_rsp_rpt_evt.rsp_data_info[i].data_len > remaining) {
HCI_TRACE_ERROR("%s, data_len %d exceeds remaining %u at index %d",
__func__, pa_rsp_rpt_evt.rsp_data_info[i].data_len, remaining, i);
pa_rsp_rpt_evt.rsp_data_info[i].data_len = 0;
pa_rsp_rpt_evt.rsp_data_info[i].data = NULL;
pa_rsp_rpt_evt.num_rsp = i + 1;
break;
}
if (pa_rsp_rpt_evt.rsp_data_info[i].data_len) {
pa_rsp_rpt_evt.rsp_data_info[i].data = osi_malloc(pa_rsp_rpt_evt.rsp_data_info[i].data_len);
if (pa_rsp_rpt_evt.rsp_data_info[i].data) {
STREAM_TO_ARRAY(pa_rsp_rpt_evt.rsp_data_info[i].data, p, pa_rsp_rpt_evt.rsp_data_info[i].data_len);
} else {
HCI_TRACE_ERROR("%s, no enough memory for data_len %d at index %d", __func__, pa_rsp_rpt_evt.rsp_data_info[i].data_len, i);
p += pa_rsp_rpt_evt.rsp_data_info[i].data_len;
remaining -= pa_rsp_rpt_evt.rsp_data_info[i].data_len;
pa_rsp_rpt_evt.rsp_data_info[i].data_len = 0;
}
remaining -= pa_rsp_rpt_evt.rsp_data_info[i].data_len;
} else {
pa_rsp_rpt_evt.rsp_data_info[i].data = NULL;
}
@@ -3462,13 +3576,25 @@ static void btu_ble_cs_proc_enable_cmpl_evt(UINT8 *p)
btm_ble_cs_proc_enable_cmpl_evt(&proc_en);
}
static void btu_ble_cs_subevt_result_evt(UINT8 *p)
static void btu_ble_cs_subevt_result_evt(UINT8 *p, UINT8 evt_len)
{
tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT subevt_result = {0};
if (!p) {
HCI_TRACE_ERROR("%s, Invalid params.", __func__);
return;
}
/* Fixed fields: conn_handle(2) + config_id(1) +
* start_acl_conn_event_counter(2) + procedure_counter(2) +
* frequency_compensation(2) + reference_power_level(1) +
* procedure_done_status(1) + subevent_done_status(1) + abort_reason(1) +
* num_ant_paths(1) + num_steps_reported(1) = 15 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 15) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=15)", __func__, evt_len);
return;
}
STREAM_TO_UINT16(subevt_result.conn_handle, p);
STREAM_TO_UINT8(subevt_result.config_id, p);
STREAM_TO_UINT16(subevt_result.start_acl_conn_event_counter, p);
@@ -3482,27 +3608,49 @@ static void btu_ble_cs_subevt_result_evt(UINT8 *p)
UINT8 num_steps_reported;
STREAM_TO_UINT8(num_steps_reported, p);
// Validate num_steps_reported per BLE spec: Range 0x00 to 0xA0 (0 to 160)
if (num_steps_reported > BTM_BLE_CS_MAX_STEPS_REPORTED) {
HCI_TRACE_ERROR("%s, num_steps_reported %d exceeds maximum %d", __func__, num_steps_reported, BTM_BLE_CS_MAX_STEPS_REPORTED);
num_steps_reported = BTM_BLE_CS_MAX_STEPS_REPORTED;
}
subevt_result.num_steps_reported = num_steps_reported;
subevt_result.step_info = osi_malloc(subevt_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO));
if (subevt_result.step_info) {
UINT8 remaining = evt_len - 15;
subevt_result.step_info = (subevt_result.num_steps_reported > 0)
? osi_malloc(subevt_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO))
: NULL;
if (subevt_result.step_info || subevt_result.num_steps_reported == 0) {
for (uint8_t i = 0; i < subevt_result.num_steps_reported; i++)
{
/* Per-step fixed: step_mode(1) + step_channel(1) + step_data_len(1) = 3 */
if (remaining < 3) {
HCI_TRACE_ERROR("%s, remaining %u too short for step %d", __func__, remaining, i);
subevt_result.num_steps_reported = i;
break;
}
STREAM_TO_UINT8(subevt_result.step_info[i].step_mode, p);
STREAM_TO_UINT8(subevt_result.step_info[i].step_channel, p);
STREAM_TO_UINT8(subevt_result.step_info[i].step_data_len, p);
// step_data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate
remaining -= 3;
if (subevt_result.step_info[i].step_data_len > remaining) {
HCI_TRACE_ERROR("%s, step_data_len %d exceeds remaining %u at step %d",
__func__, subevt_result.step_info[i].step_data_len, remaining, i);
subevt_result.step_info[i].step_data_len = 0;
subevt_result.step_info[i].data = NULL;
subevt_result.num_steps_reported = i + 1;
break;
}
subevt_result.step_info[i].data = osi_malloc(subevt_result.step_info[i].step_data_len);
if (subevt_result.step_info[i].data) {
STREAM_TO_ARRAY(subevt_result.step_info[i].data, p, subevt_result.step_info[i].step_data_len);
} else if (subevt_result.step_info[i].step_data_len) {
HCI_TRACE_ERROR("%s, no memory.", __func__);
p += subevt_result.step_info[i].step_data_len;
subevt_result.step_info[i].step_data_len = 0;
subevt_result.step_info[i].data = NULL;
subevt_result.num_steps_reported = i + 1;
break;
}
remaining -= subevt_result.step_info[i].step_data_len;
}
}
@@ -3521,7 +3669,7 @@ static void btu_ble_cs_subevt_result_evt(UINT8 *p)
}
static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p)
static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p, UINT8 evt_len)
{
tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT subevt_continue_result = {0};
@@ -3530,6 +3678,15 @@ static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p)
return;
}
/* Fixed fields: conn_handle(2) + config_id(1) + proc_done_status(1)
* + subevt_done_status(1) + abort_reason(1) + num_ant_paths(1)
* + num_steps_reported(1) = 8 bytes
* (subevent_code already subtracted from evt_len by caller) */
if (evt_len < 8) {
HCI_TRACE_ERROR("%s, evt too short (len=%u, need>=8)", __func__, evt_len);
return;
}
STREAM_TO_UINT16(subevt_continue_result.conn_handle, p);
STREAM_TO_UINT8(subevt_continue_result.config_id, p);
STREAM_TO_UINT8(subevt_continue_result.proc_done_status, p);
@@ -3539,26 +3696,47 @@ static void btu_ble_cs_subevt_result_continue_evt(UINT8 *p)
UINT8 num_steps_reported;
STREAM_TO_UINT8(num_steps_reported, p);
// Validate num_steps_reported per BLE spec: Range 0x00 to 0xA0 (0 to 160)
if (num_steps_reported > BTM_BLE_CS_MAX_STEPS_REPORTED) {
HCI_TRACE_ERROR("%s, num_steps_reported %d exceeds maximum %d", __func__, num_steps_reported, BTM_BLE_CS_MAX_STEPS_REPORTED);
num_steps_reported = BTM_BLE_CS_MAX_STEPS_REPORTED;
}
subevt_continue_result.num_steps_reported = num_steps_reported;
subevt_continue_result.step_info = osi_malloc(subevt_continue_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO));
if (subevt_continue_result.step_info) {
UINT8 remaining = evt_len - 8;
subevt_continue_result.step_info = (subevt_continue_result.num_steps_reported > 0)
? osi_malloc(subevt_continue_result.num_steps_reported * sizeof(tBTM_BLE_CS_STEP_INFO))
: NULL;
if (subevt_continue_result.step_info || subevt_continue_result.num_steps_reported == 0) {
for (uint8_t i = 0; i < subevt_continue_result.num_steps_reported; i++) {
if (remaining < 3) {
HCI_TRACE_ERROR("%s, remaining %u too short for step %d", __func__, remaining, i);
subevt_continue_result.num_steps_reported = i;
break;
}
STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_mode, p);
STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_channel, p);
STREAM_TO_UINT8(subevt_continue_result.step_info[i].step_data_len, p);
// step_data_len is UINT8, range 0x00 to 0xFF (0 to 255), no need to validate
remaining -= 3;
if (subevt_continue_result.step_info[i].step_data_len > remaining) {
HCI_TRACE_ERROR("%s, step_data_len %d exceeds remaining %u at step %d",
__func__, subevt_continue_result.step_info[i].step_data_len, remaining, i);
subevt_continue_result.step_info[i].step_data_len = 0;
subevt_continue_result.step_info[i].data = NULL;
subevt_continue_result.num_steps_reported = i + 1;
break;
}
subevt_continue_result.step_info[i].data = osi_malloc(subevt_continue_result.step_info[i].step_data_len);
if (subevt_continue_result.step_info[i].data) {
STREAM_TO_ARRAY(subevt_continue_result.step_info[i].data, p, subevt_continue_result.step_info[i].step_data_len);
} else if (subevt_continue_result.step_info[i].step_data_len) {
HCI_TRACE_ERROR("%s, no memory.", __func__);
p += subevt_continue_result.step_info[i].step_data_len;
subevt_continue_result.step_info[i].step_data_len = 0;
subevt_continue_result.step_info[i].data = NULL;
subevt_continue_result.num_steps_reported = i + 1;
break;
}
remaining -= subevt_continue_result.step_info[i].step_data_len;
}
} else {
HCI_TRACE_ERROR("%s, no memory for step_info.", __func__);
@@ -449,7 +449,17 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec)
osi_mutex_lock(&btu_general_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (!hash_map_has_key(btu_general_alarm_hash_map, p_tle)) {
alarm = osi_alarm_new("btu_gen", btu_general_alarm_cb, (void *)p_tle, 0);
hash_map_set(btu_general_alarm_hash_map, p_tle, alarm);
if (alarm == NULL) {
HCI_TRACE_ERROR("%s Unable to create new alarm", __func__);
osi_mutex_unlock(&btu_general_alarm_lock);
return;
}
if (!hash_map_set(btu_general_alarm_hash_map, p_tle, alarm)) {
HCI_TRACE_ERROR("%s Unable to set alarm in map", __func__);
osi_alarm_free(alarm);
osi_mutex_unlock(&btu_general_alarm_lock);
return;
}
}
osi_mutex_unlock(&btu_general_alarm_lock);
@@ -569,8 +579,12 @@ void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ti
osi_mutex_unlock(&btu_l2cap_alarm_lock);
return;
}
hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm);
if (!hash_map_set(btu_l2cap_alarm_hash_map, p_tle, (void *)alarm)) {
HCI_TRACE_ERROR("%s Unable to set alarm in map", __func__);
osi_alarm_free(alarm);
osi_mutex_unlock(&btu_l2cap_alarm_lock);
return;
}
}
osi_mutex_unlock(&btu_l2cap_alarm_lock);
@@ -656,7 +670,17 @@ void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_
osi_mutex_lock(&btu_oneshot_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
if (!hash_map_has_key(btu_oneshot_alarm_hash_map, p_tle)) {
alarm = osi_alarm_new("btu_oneshot", btu_oneshot_alarm_cb, (void *)p_tle, 0);
hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm);
if (alarm == NULL) {
HCI_TRACE_ERROR("%s Unable to create new alarm", __func__);
osi_mutex_unlock(&btu_oneshot_alarm_lock);
return;
}
if (!hash_map_set(btu_oneshot_alarm_hash_map, p_tle, alarm)) {
HCI_TRACE_ERROR("%s Unable to set alarm in map", __func__);
osi_alarm_free(alarm);
osi_mutex_unlock(&btu_oneshot_alarm_lock);
return;
}
}
osi_mutex_unlock(&btu_oneshot_alarm_lock);
@@ -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);
@@ -236,6 +248,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);
@@ -48,6 +48,7 @@
#define SMP_OPCODE_MAX SMP_OPCODE_PAIR_KEYPR_NOTIF
#define SMP_OPCODE_MIN SMP_OPCODE_PAIRING_REQ
#define SMP_OPCODE_PAIR_COMMITM 0x0F
#define SMP_OPCODE_ARRAY_SIZE (SMP_OPCODE_PAIR_COMMITM + 1)
// #endif
/* SMP event type */
@@ -465,10 +466,10 @@ extern void SMP_SecureConnectionOobDataReply(UINT8 *p_data);
** Description This function is called to encrypt the data with the specified
** key
**
** Parameters: key - Pointer to key key[0] conatins the MSB
** Parameters: key - Pointer to key key[0] contains the MSB
** key_len - key length
** plain_text - Pointer to data to be encrypted
** plain_text[0] conatins the MSB
** plain_text[0] contains the MSB
** pt_len - plain text length
** p_out - pointer to the encrypted outputs
**
@@ -461,7 +461,7 @@ typedef struct t_l2c_linkcb {
*/
/* create connection retry count*/
UINT8 retry_create_con;
UINT32 start_time_s;
int64_t start_time_s;
#endif
#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
@@ -736,7 +736,7 @@ extern void l2c_link_timeout (tL2C_LCB *p_lcb);
extern void l2c_info_timeout (tL2C_LCB *p_lcb);
extern void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf);
extern void l2c_link_adjust_allocation (void);
extern void l2c_link_process_num_completed_pkts (UINT8 *p);
extern void l2c_link_process_num_completed_pkts (UINT8 *p, UINT8 evt_len);
extern void l2c_link_process_num_completed_blocks (UINT8 controller_id, UINT8 *p, UINT16 evt_len);
extern void l2c_link_processs_num_bufs (UINT16 num_lm_acl_bufs);
extern UINT8 l2c_link_pkts_rcvd (UINT16 *num_pkts, UINT16 *handles);
@@ -1863,6 +1863,11 @@ UINT16 L2CA_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf)
BOOLEAN L2CA_CheckIsCongest(UINT16 fixed_cid, BD_ADDR addr)
{
if ((fixed_cid < L2CAP_FIRST_FIXED_CHNL) || (fixed_cid > L2CAP_LAST_FIXED_CHNL)) {
L2CAP_TRACE_ERROR ("L2CA_CheckIsCongest() Invalid CID: 0x%04x", fixed_cid);
return TRUE;
}
tL2C_LCB *p_lcb;
p_lcb = l2cu_find_lcb_by_bd_addr(addr, BT_TRANSPORT_LE);
@@ -828,7 +828,6 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
STREAM_TO_UINT16(mps, p);
STREAM_TO_UINT16(credits, p);
L2CAP_TRACE_DEBUG("%s spsm %x, scid %x", __func__, spsm, scid);
UNUSED(spsm);
p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, scid);
if (p_ccb) {
@@ -836,12 +835,11 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
break;
}
#if 0
p_rcb = l2cu_find_ble_rcb_by_psm(spsm);
if (p_rcb == NULL) {
l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_NO_PSM);
break;
}
#endif
p_ccb = l2cu_allocate_ccb(p_lcb, 0);
if (p_ccb == NULL) {
@@ -862,6 +860,34 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
l2cu_send_peer_ble_credit_based_conn_res(p_ccb, L2CAP_LE_RESULT_CONN_OK);
break;
}
case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT: {
if (cmd_len < L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN) {
L2CAP_TRACE_WARNING ("L2CAP - LE - flow ctrl credit too short: %d", cmd_len);
return;
}
tL2C_CCB *p_ccb = NULL;
UINT16 lcid;
UINT16 credit;
STREAM_TO_UINT16(lcid, p);
STREAM_TO_UINT16(credit, p);
p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
if (p_ccb == NULL) {
L2CAP_TRACE_WARNING ("L2CAP - LE - flow ctrl credit for unknown CID: 0x%04x", lcid);
break;
}
if ((p_ccb->peer_conn_cfg.credits + credit) > L2CAP_LE_MAX_CREDIT) {
L2CAP_TRACE_WARNING ("L2CAP - LE - credit overflow, disconnecting CID: 0x%04x", lcid);
l2cble_send_peer_disc_req(p_ccb);
} else {
p_ccb->peer_conn_cfg.credits += credit;
L2CAP_TRACE_DEBUG ("L2CAP - LE - credits updated to %d for CID: 0x%04x",
p_ccb->peer_conn_cfg.credits, lcid);
l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
}
break;
}
case L2CAP_CMD_DISC_REQ: {
if (cmd_len < 4) {
L2CAP_TRACE_WARNING ("L2CAP - LE - short cmd: %d", cmd_len);
@@ -988,13 +1014,20 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
uint32_t link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
if(GATTC_CONNECT_RETRY_COUNT) {
if(!p_lcb->retry_create_con) {
p_lcb->start_time_s = (esp_system_get_time()/1000);
p_lcb->start_time_s = esp_system_get_time() / 1000;
}
uint32_t current_time = (esp_system_get_time()/1000);
link_timeout = (L2CAP_BLE_LINK_CONNECT_TOUT*1000 - (current_time - p_lcb->start_time_s))/1000;
int64_t current_time = esp_system_get_time() / 1000;
int64_t elapsed_ms = current_time - p_lcb->start_time_s;
int64_t timeout_ms = (int64_t)L2CAP_BLE_LINK_CONNECT_TOUT * 1000;
int64_t remaining_ms = timeout_ms - elapsed_ms;
if(link_timeout == 0 || link_timeout > L2CAP_BLE_LINK_CONNECT_TOUT) {
if (remaining_ms <= 0 || remaining_ms > timeout_ms) {
link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
} else {
link_timeout = (uint32_t)(remaining_ms / 1000);
if (link_timeout == 0) {
link_timeout = 1;
}
}
}
@@ -379,6 +379,9 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
} else {
#if (BLE_INCLUDED == TRUE)
tL2C_LINK_STATE link_state_temp = p_lcb->link_state;
#if ((BLE_42_ADV_EN == TRUE) || (GATTC_CONNECT_RETRY_EN == TRUE) || (BLE_50_EXTEND_ADV_EN == TRUE))
UINT8 link_role_temp = p_lcb->link_role;
#endif
#endif // (BLE_INCLUDED == TRUE)
/* There can be a case when we rejected PIN code authentication */
/* otherwise save a new reason */
@@ -469,6 +472,7 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
}
#endif
}
/* l2cu_create_conn must not release the LCB on failure */
if (l2cu_create_conn(p_lcb, transport)) {
lcb_is_free = FALSE; /* still using this lcb */
}
@@ -476,13 +480,15 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
p_lcb->p_pending_ccb = NULL;
#if (BLE_INCLUDED == TRUE)
if(p_lcb->transport == BT_TRANSPORT_LE) {
/* Use p_lcb->transport so BLE reconnection (slave adv restart / master retry) runs even when
* there was no pending CCB; 'transport' is only set when (p_first_ccb || p_pending_ccb). */
if (p_lcb->transport == BT_TRANSPORT_LE) {
// for legacy adv, adv restart in gatt_le_connect_cback->gatt_cleanup_upon_disc->BTM_Recovery_Pre_State
if (reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT) {
#if (BLE_42_FEATURE_SUPPORT == TRUE)
#if (BLE_42_ADV_EN == TRUE)
if(!btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE) {
if(!btm_ble_inter_get() && link_role_temp == HCI_ROLE_SLAVE) {
L2CAP_TRACE_DEBUG("slave resatrt adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason);
tBTM_STATUS start_adv_status = btm_ble_start_adv();
if (start_adv_status != BTM_SUCCESS) {
@@ -496,7 +502,7 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
if ((reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT) || (link_state_temp == LST_CONNECTING)) {
#if (GATTC_CONNECT_RETRY_EN == TRUE)
if(p_lcb->link_role == HCI_ROLE_MASTER && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) {
if(link_role_temp == HCI_ROLE_MASTER && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) {
L2CAP_TRACE_DEBUG("master retry connect, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason);
p_lcb->retry_create_con ++;
// create connection retry
@@ -513,7 +519,7 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
if ((reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT) || (link_state_temp == LST_DISCONNECTED)) {
#if (BLE_50_FEATURE_SUPPORT == TRUE)
#if (BLE_50_EXTEND_ADV_EN == TRUE)
if(btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE) {
if(btm_ble_inter_get() && link_role_temp == HCI_ROLE_SLAVE) {
L2CAP_TRACE_DEBUG("slave restart extend adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason);
tBTM_STATUS start_adv_status = BTM_BleStartExtAdvRestart(handle);
if (start_adv_status != BTM_SUCCESS) {
@@ -626,6 +632,7 @@ void l2c_link_timeout (tL2C_LCB *p_lcb)
#endif
/* Release the LCB */
l2cu_release_lcb (p_lcb);
return;
}
/* If link is connected, check for inactivity timeout */
@@ -1314,6 +1321,13 @@ static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf)
acl_data_size = controller->get_acl_data_size_classic();
xmit_window = l2cb.controller_xmit_window;
}
if (p_buf->len <= HCI_DATA_PREAMBLE_SIZE) {
L2CAP_TRACE_ERROR ("l2c_link_send_to_lower - bad buffer len: %u", p_buf->len);
osi_free(p_buf);
return FALSE;
}
num_segs = (p_buf->len - HCI_DATA_PREAMBLE_SIZE + acl_data_size - 1) / acl_data_size;
@@ -1395,15 +1409,26 @@ static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf)
** Returns void
**
*******************************************************************************/
void l2c_link_process_num_completed_pkts (UINT8 *p)
void l2c_link_process_num_completed_pkts (UINT8 *p, UINT8 evt_len)
{
UINT8 num_handles, xx;
UINT16 handle;
UINT16 num_sent;
tL2C_LCB *p_lcb;
if (evt_len < 1) {
L2CAP_TRACE_ERROR ("l2c_link_process_num_completed_pkts: evt too short (len=%u)", evt_len);
return;
}
STREAM_TO_UINT8 (num_handles, p);
if (num_handles > (evt_len - 1) / 4) {
L2CAP_TRACE_ERROR ("l2c_link_process_num_completed_pkts: num_handles %u exceeds evt_len %u, truncating",
num_handles, evt_len);
num_handles = (evt_len - 1) / 4;
}
for (xx = 0; xx < num_handles; xx++) {
STREAM_TO_UINT16 (handle, p);
STREAM_TO_UINT16 (num_sent, p);
@@ -150,7 +150,6 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
#if (!CONFIG_BT_STACK_NO_LOG)
UINT16 psm;
#endif
UINT16 credit;
/* Extract the handle */
STREAM_TO_UINT16 (handle, p);
@@ -292,6 +291,9 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
#if (CLASSIC_BT_INCLUDED == TRUE)
l2c_fcr_proc_pdu (p_ccb, p_msg);
#else
/* Classic FCR not compiled (e.g. BLE-only); free p_msg to avoid leak */
osi_free (p_msg);
#endif ///CLASSIC_BT_INCLUDED == TRUE
} else {
(*l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
@@ -310,31 +312,24 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
osi_free (p_msg);
} else {
if (p_lcb->transport == BT_TRANSPORT_LE) {
// Got a pkt, valid send out credits to the peer device
credit = L2CAP_LE_DEFAULT_CREDIT;
L2CAP_TRACE_DEBUG("%s Credits received %d",__func__, credit);
if((p_ccb->peer_conn_cfg.credits + credit) > L2CAP_LE_MAX_CREDIT) {
/* we have received credits more than max coc credits,
* so disconnecting the Le Coc Channel
*/
#if (BLE_INCLUDED == TRUE)
l2cble_send_peer_disc_req (p_ccb);
#endif ///BLE_INCLUDED == TRUE
} else {
p_ccb->peer_conn_cfg.credits += credit;
l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
}
l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
}
/* Basic mode packets go straight to the state machine */
if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
#if (CLASSIC_BT_INCLUDED == TRUE)
#if (L2CAP_COC_INCLUDED == TRUE)
l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_msg);
#endif ///CLASSIC_BT_INCLUDED == TRUE
#else
/* COC not included: state machine not compiled; free p_msg to avoid leak */
osi_free (p_msg);
#endif
} else {
/* eRTM or streaming mode, so we need to validate states first */
if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)) {
#if (CLASSIC_BT_INCLUDED == TRUE)
l2c_fcr_proc_pdu (p_ccb, p_msg);
#else
/* Classic FCR not compiled (e.g. BLE-only); free p_msg to avoid leak */
osi_free (p_msg);
#endif ///CLASSIC_BT_INCLUDED == TRUE
} else {
osi_free (p_msg);
@@ -423,14 +418,26 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
switch (cmd_code) {
case L2CAP_CMD_REJECT:
if (cmd_len < L2CAP_CMD_REJECT_LEN) {
L2CAP_TRACE_WARNING ("L2CAP - cmd reject too short, cmd_len: %d", cmd_len);
break;
}
STREAM_TO_UINT16 (rej_reason, p);
if (rej_reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
if (cmd_len < L2CAP_CMD_REJECT_LEN + 2) {
L2CAP_TRACE_WARNING ("L2CAP - MTU rej too short, cmd_len: %d", cmd_len);
break;
}
STREAM_TO_UINT16 (rej_mtu, p);
/* What to do with the MTU reject ? We have negotiated an MTU. For now */
/* we will ignore it and let a higher protocol timeout take care of it */
L2CAP_TRACE_WARNING ("L2CAP - MTU rej Handle: %d MTU: %d", p_lcb->handle, rej_mtu);
}
if (rej_reason == L2CAP_CMD_REJ_INVALID_CID) {
if (cmd_len < L2CAP_CMD_REJECT_LEN + 4) {
L2CAP_TRACE_WARNING ("L2CAP - CID rej too short, cmd_len: %d", cmd_len);
break;
}
STREAM_TO_UINT16 (rcid, p);
STREAM_TO_UINT16 (lcid, p);
@@ -1899,15 +1899,31 @@ void l2cu_disconnect_chnl (tL2C_CCB *p_ccb)
UINT16 local_cid = p_ccb->local_cid;
if (local_cid >= L2CAP_BASE_APPL_CID) {
tL2CA_DISCONNECT_IND_CB *p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
tL2CA_DISCONNECT_IND_CB *p_disc_cb = NULL;
if (p_ccb->p_rcb != NULL) {
p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
}
L2CAP_TRACE_WARNING ("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
l2cu_send_peer_disc_req (p_ccb);
/*
* l2cu_send_peer_disc_req drains xmit_hold_q in basic FCR mode.
* Free the queue and NULL it here to prevent l2cu_release_ccb from
* calling fixed_queue_free again on already-dequeued buffers.
*/
if (p_ccb->xmit_hold_q != NULL) {
fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
p_ccb->xmit_hold_q = NULL;
}
l2cu_release_ccb (p_ccb);
(*p_disc_cb)(local_cid, FALSE);
if (p_disc_cb) {
(*p_disc_cb)(local_cid, FALSE);
}
} else {
/* failure on the AMP channel, probably need to disconnect ACL */
L2CAP_TRACE_ERROR ("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
@@ -510,7 +510,7 @@ extern void smp_generate_passkey (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_compute_dhkey(tSMP_CB *p_cb);
extern BOOLEAN smp_compute_dhkey(tSMP_CB *p_cb);
extern void smp_calculate_local_commitment(tSMP_CB *p_cb);
extern void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf);
extern void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
@@ -274,7 +274,9 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p)
/* The function of the elliptic curve is y^2 = x^3 - 3x + b (mod q) ==>
y^2 = (x^2 - 3)*x + b (mod q),
so we calculate the x^2 - 3 value here */
x_x[0] -= 3;
DWORD three[2 * KEY_LENGTH_DWORDS_P256] = {0};
three[0] = 3;
multiprecision_sub(x_x, x_x, three, 2 * KEY_LENGTH_DWORDS_P256);
/* Using math relations. (a*b) % q = ((a%q)*(b%q)) % q ==>
(x^2 - 3)*x = (((x^2 - 3) % q) * x % q) % q */
multiprecision_fast_mod_P256(x_x_q, x_x);
@@ -262,7 +262,7 @@ void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
DWORD V;
U = V = W = 0;
multiprecision_init(c, keyLength);
multiprecision_init(c, 2 * keyLength);
//assume little endian right now
for (uint32_t i = 0; i < keyLength; i++) {
@@ -340,7 +340,7 @@ void multiprecision_fast_mod(DWORD *c, DWORD *a)
c[2] += V;
V = c[2] < V;
c[2] += U;
V = c[2] < U;
V += c[2] < U;
c[3] += V;
V = c[3] < V;
c[4] += V;
@@ -594,6 +594,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
{
DWORD u_local[KEY_LENGTH_DWORDS_P256];
DWORD v[KEY_LENGTH_DWORDS_P256];
DWORD A[KEY_LENGTH_DWORDS_P256 + 1];
DWORD C[KEY_LENGTH_DWORDS_P256 + 1];
@@ -605,14 +606,15 @@ void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
modp = curve.p;
}
multiprecision_copy(u_local, u, keyLength);
multiprecision_copy(v, modp, keyLength);
multiprecision_init(A, keyLength);
multiprecision_init(C, keyLength);
A[0] = 1;
while (!multiprecision_iszero(u, keyLength)) {
while (!(u[0] & 0x01)) { // u is even
multiprecision_rshift(u, u, keyLength);
while (!multiprecision_iszero(u_local, keyLength)) {
while (!(u_local[0] & 0x01)) { // u is even
multiprecision_rshift(u_local, u_local, keyLength);
if (!(A[0] & 0x01)) { // A is even
multiprecision_rshift(A, A, keyLength);
} else {
@@ -633,11 +635,11 @@ void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
}
}
if (multiprecision_compare(u, v, keyLength) >= 0) {
multiprecision_sub(u, u, v, keyLength);
if (multiprecision_compare(u_local, v, keyLength) >= 0) {
multiprecision_sub(u_local, u_local, v, keyLength);
multiprecision_sub_mod(A, A, C, keyLength);
} else {
multiprecision_sub(v, v, u, keyLength);
multiprecision_sub(v, v, u_local, keyLength);
multiprecision_sub_mod(C, C, A, keyLength);
}
}
@@ -406,7 +406,7 @@ void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
smp_send_cmd(SMP_OPCODE_ID_ADDR, p_cb);
#if (BLE_INCLUDED == TRUE)
tBTM_LE_KEY_VALUE le_key;
tBTM_LE_KEY_VALUE le_key = {0};
if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND)) {
btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LID,
&le_key, TRUE);
@@ -1420,7 +1420,9 @@ void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
if (smp_get_state() == SMP_STATE_BOND_PENDING) {
if (p_cb->derive_lk) {
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);
if (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED) &&
if (p_dev_rec == NULL) {
SMP_TRACE_WARNING("%s device record not found, skip LK derivation", __func__);
} else if (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED) &&
(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED)) {
SMP_TRACE_DEBUG("%s BREDR key is higher security than existing LE keys, "
"don't derive LK from LTK", __func__);
@@ -1678,7 +1680,11 @@ void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
SMP_TRACE_DEBUG("%s\n", __func__);
/* invokes DHKey computation */
smp_compute_dhkey(p_cb);
if (!smp_compute_dhkey(p_cb)) {
UINT8 reason = SMP_PAIR_INTERNAL_ERR;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
/* on slave side invokes sending local public key to the peer */
if (p_cb->role == HCI_ROLE_SLAVE) {
@@ -483,6 +483,10 @@ void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
return;
}
if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT) {
return;
}
/* Set local oob data when req_oob_type = SMP_OOB_BOTH */
memcpy(&p_oob->loc_oob_data, smp_get_local_oob_data(), sizeof(tSMP_LOC_OOB_DATA));
@@ -491,10 +495,6 @@ void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
__FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
p_oob->peer_oob_data.present);
if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT) {
return;
}
BOOLEAN data_missing = FALSE;
switch (p_cb->req_oob_type) {
case SMP_OOB_PEER:
@@ -153,6 +153,11 @@ static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 t
SMP_TRACE_EVENT ("cmac_aes_k_calculate ");
if (cmac_cb.round == 0) {
SMP_TRACE_ERROR("%s round is 0", __func__);
return FALSE;
}
while (i <= cmac_cb.round) {
smp_xor_128(&cmac_cb.text[(cmac_cb.round - i)*BT_OCTET16_LEN], x); /* Mi' := Mi (+) X */
@@ -304,6 +309,11 @@ BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
SMP_TRACE_EVENT ("%s", __func__);
if (tlen == 0 || tlen > BT_OCTET16_LEN) {
SMP_TRACE_ERROR("%s invalid tlen=%d", __func__, tlen);
return FALSE;
}
#if (SMP_CRYPTO_MBEDTLS == TRUE)
{
/*
@@ -672,10 +672,10 @@ BOOLEAN smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
** Description Generate Confirm/Compare Step2:
** p2 = padding || ia || ra
**
** Returns void
** Returns FALSE if remote address unavailable, TRUE otherwise
**
*******************************************************************************/
void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
BOOLEAN smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
{
UINT8 *p = (UINT8 *)p2;
BD_ADDR remote_bda;
@@ -683,7 +683,7 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
SMP_TRACE_DEBUG ("smp_gen_p2_4_confirm\n");
if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type)) {
SMP_TRACE_ERROR("can not generate confirm p2 for unknown device\n");
return;
return FALSE;
}
SMP_TRACE_DEBUG ("smp_gen_p2_4_confirm\n");
@@ -705,6 +705,7 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
SMP_TRACE_DEBUG("p2 = padding || ia || ra");
smp_debug_print_nbyte_little_endian(p2, (const UINT8 *)"p2", 16);
#endif
return TRUE;
}
/*******************************************************************************
@@ -768,7 +769,10 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p)
smp_debug_print_nbyte_little_endian (p->param_buf, (const UINT8 *)"C1", 16);
#endif
smp_gen_p2_4_confirm(p_cb, p2);
if (!smp_gen_p2_4_confirm(p_cb, p2)) {
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
return;
}
/* calculate p2 = (p1' XOR p2) */
smp_xor_128(p2, p->param_buf);
@@ -1217,6 +1221,7 @@ void smp_process_private_key(tSMP_CB *p_cb)
UINT8 priv_be[BT_OCTET32_LEN];
UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
size_t pub_len = 0;
BOOLEAN psa_ok = FALSE;
/* Convert private key from little-endian to big-endian */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
@@ -1250,11 +1255,16 @@ void smp_process_private_key(tSMP_CB *p_cb)
p_cb->loc_publ_key.x[i] = pub_be[1 + BT_OCTET32_LEN - 1 - i];
p_cb->loc_publ_key.y[i] = pub_be[33 + BT_OCTET32_LEN - 1 - i];
}
psa_ok = TRUE;
psa_pubkey_cleanup:
psa_destroy_key(key_id);
/* Clear sensitive data from stack */
memset(priv_be, 0, sizeof(priv_be));
memset(pub_be, 0, sizeof(pub_be));
if (!psa_ok) {
return;
}
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
UINT8 pub_key[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */
@@ -1315,10 +1325,10 @@ psa_pubkey_cleanup:
** key and peer public key;
** - saves the new public key x-coordinate as DHKey.
**
** Returns void
** Returns TRUE if DHKey was computed successfully, FALSE otherwise.
**
*******************************************************************************/
void smp_compute_dhkey (tSMP_CB *p_cb)
BOOLEAN smp_compute_dhkey (tSMP_CB *p_cb)
{
SMP_TRACE_DEBUG ("%s\n", __FUNCTION__);
@@ -1330,6 +1340,7 @@ void smp_compute_dhkey (tSMP_CB *p_cb)
UINT8 peer_pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
UINT8 shared_secret[BT_OCTET32_LEN];
size_t output_len = 0;
BOOLEAN psa_ok = FALSE;
/* Convert private key from little-endian to big-endian */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
@@ -1369,12 +1380,17 @@ void smp_compute_dhkey (tSMP_CB *p_cb)
for (int i = 0; i < BT_OCTET32_LEN; i++) {
p_cb->dhkey[i] = shared_secret[BT_OCTET32_LEN - 1 - i];
}
psa_ok = TRUE;
psa_dhkey_cleanup:
psa_destroy_key(key_id);
/* Clear sensitive data from stack */
memset(priv_be, 0, sizeof(priv_be));
memset(peer_pub_be, 0, sizeof(peer_pub_be));
memset(shared_secret, 0, sizeof(shared_secret));
if (!psa_ok) {
return FALSE;
}
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
UINT8 priv_be[BT_OCTET32_LEN];
@@ -1395,11 +1411,11 @@ psa_dhkey_cleanup:
/* Validate peer public key */
/* uECC_valid_public_key returns 0 if valid, negative value if invalid */
if (uECC_valid_public_key(peer_pub_be, uECC_secp256r1()) < 0) {
if (uECC_valid_public_key(peer_pub_be, uECC_secp256r1()) != 0) {
SMP_TRACE_ERROR("%s Invalid peer public key\n", __FUNCTION__);
memset(priv_be, 0, sizeof(priv_be));
memset(peer_pub_be, 0, sizeof(peer_pub_be));
return;
return FALSE;
}
/* Compute ECDH shared secret */
@@ -1409,7 +1425,7 @@ psa_dhkey_cleanup:
memset(priv_be, 0, sizeof(priv_be));
memset(peer_pub_be, 0, sizeof(peer_pub_be));
memset(shared_secret, 0, sizeof(shared_secret));
return;
return FALSE;
}
/* Convert shared secret from big-endian to little-endian for DHKey */
@@ -1430,9 +1446,16 @@ psa_dhkey_cleanup:
memcpy(peer_publ_key.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
memcpy(peer_publ_key.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);
if (!ECC_CheckPointIsInElliCur_P256(&peer_publ_key)) {
SMP_TRACE_ERROR("%s Invalid peer public key\n", __FUNCTION__);
memset(private_key, 0, sizeof(private_key));
return FALSE;
}
ECC_PointMult(&new_publ_key, &peer_publ_key, (DWORD *) private_key, KEY_LENGTH_DWORDS_P256);
memcpy(p_cb->dhkey, new_publ_key.x, BT_OCTET32_LEN);
memset(private_key, 0, sizeof(private_key));
#endif /* SMP_CRYPTO_MBEDTLS */
smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"DHKey",
@@ -1444,6 +1467,7 @@ psa_dhkey_cleanup:
BT_OCTET32_LEN);
smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.y, (const UINT8 *)"rem public(y)",
BT_OCTET32_LEN);
return TRUE;
}
/*******************************************************************************
@@ -118,8 +118,8 @@ static void smp_connect_callback (UINT16 channel, BD_ADDR bd_addr, BOOLEAN conne
if (memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0) {
SMP_TRACE_EVENT ("%s() for pairing BDA: %08x%04x Event: %s\n",
__FUNCTION__,
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
(bd_addr[4] << 8) + bd_addr[5],
((UINT32)bd_addr[0] << 24) + ((UINT32)bd_addr[1] << 16) + ((UINT32)bd_addr[2] << 8) + bd_addr[3],
((UINT32)bd_addr[4] << 8) + bd_addr[5],
(connected) ? "connected" : "disconnected");
if (connected) {
@@ -283,8 +283,8 @@ static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN con
SMP_TRACE_EVENT ("%s for pairing BDA: %08x%04x Event: %s\n",
__func__,
(bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3],
(bd_addr[4] << 8) + bd_addr[5],
((UINT32)bd_addr[0] << 24) + ((UINT32)bd_addr[1] << 16) + ((UINT32)bd_addr[2] << 8) + bd_addr[3],
((UINT32)bd_addr[4] << 8) + bd_addr[5],
(connected) ? "connected" : "disconnected");
if (connected) {
@@ -746,7 +746,7 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
/* lookup entry /w event & curr_state */
/* If entry is ignore, return.
* Otherwise, get state table (according to curr_state or all_state) */
if ((event <= SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE )) {
if ((event >= 1 && event <= SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE )) {
if (entry & SMP_ALL_TBL_MASK) {
entry &= ~SMP_ALL_TBL_MASK;
state_table = smp_all_table;
@@ -803,7 +803,7 @@ const char *smp_get_event_name(tSMP_EVENT event)
{
const char *p_str = smp_event_name[SMP_MAX_EVT];
if (event <= SMP_MAX_EVT) {
if (event >= 1 && event <= SMP_MAX_EVT) {
p_str = smp_event_name[event - 1];
}
return p_str;
@@ -351,7 +351,7 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
BOOLEAN sent = FALSE;
UINT8 failure = SMP_PAIR_INTERNAL_ERR;
SMP_TRACE_EVENT("smp_send_cmd on l2cap cmd_code=0x%x\n", cmd_code);
if ( cmd_code <= (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */) &&
if ( cmd_code < SMP_OPCODE_ARRAY_SIZE &&
smp_cmd_build_act[cmd_code] != NULL) {
p_buf = (*smp_cmd_build_act[cmd_code])(cmd_code, p_cb);
@@ -861,6 +861,11 @@ void smp_convert_string_to_tk(BT_OCTET16 tk, UINT32 passkey)
void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 *p_data)
{
SMP_TRACE_EVENT("smp_mask_enc_key\n");
if (loc_enc_size < SMP_ENCR_KEY_SIZE_MIN) {
SMP_TRACE_ERROR("smp_mask_enc_key: loc_enc_size %d below minimum %d\n",
loc_enc_size, SMP_ENCR_KEY_SIZE_MIN);
return;
}
if (loc_enc_size < BT_OCTET16_LEN) {
for (; loc_enc_size < BT_OCTET16_LEN; loc_enc_size ++) {
* (p_data + loc_enc_size) = 0;
@@ -1060,7 +1065,7 @@ BOOLEAN smp_command_has_invalid_parameters(tSMP_CB *p_cb)
SMP_TRACE_DEBUG("%s for cmd code 0x%02x\n", __func__, cmd_code);
if ((cmd_code > (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */)) ||
if ((cmd_code >= SMP_OPCODE_ARRAY_SIZE) ||
(cmd_code < SMP_OPCODE_MIN)) {
SMP_TRACE_WARNING("Somehow received command with the RESERVED code 0x%02x\n", cmd_code);
return TRUE;