// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "common/bt_target.h" #include #include #include "btc/btc_common.h" #include "btc/btc_dm.h" #include "btc/btc_main.h" #include "common/bt_trace.h" #include "common/bt_target.h" #include "btc/btc_storage.h" #include "btc/btc_ble_storage.h" #include "btc_gap_ble.h" #include "btm_int.h" #include "bta/bta_api.h" #include "bta/bta_gatt_api.h" #include "osi/allocator.h" #include "btc/btc_manage.h" #if (BTC_GAP_BT_INCLUDED == TRUE) #include "btc_gap_bt.h" #endif /* BTC_GAP_BT_INCLUDED == TRUE */ /****************************************************************************** ** Constants & Macros ******************************************************************************/ #define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) /****************************************************************************** ** Static variables ******************************************************************************/ static tBTA_SERVICE_MASK btc_enabled_services = 0; #if (SMP_INCLUDED == TRUE) static btc_dm_pairing_cb_t pairing_cb; static btc_dm_local_key_cb_t ble_local_key_cb; #endif /****************************************************************************** ** Static functions ******************************************************************************/ /****************************************************************************** ** Externs ******************************************************************************/ #if BTC_AV_INCLUDED extern bt_status_t btc_av_source_execute_service(BOOLEAN b_enable); extern bt_status_t btc_av_sink_execute_service(BOOLEAN b_enable); #endif #if BTC_HF_CLIENT_INCLUDED extern bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable); #endif /****************************************************************************** ** Functions ******************************************************************************/ static void btc_dm_sec_arg_deep_free(btc_msg_t *msg) { btc_dm_sec_args_t *arg = (btc_dm_sec_args_t *)(msg->arg); if (msg->act == BTA_DM_BLE_KEY_EVT) { osi_free(arg->sec.ble_key.p_key_value); } } void btc_dm_sec_arg_deep_copy(btc_msg_t *msg, void *dst, void *src) { tBTA_DM_SEC *dst_dm_sec = (tBTA_DM_SEC *)dst; tBTA_DM_SEC *src_dm_sec = (tBTA_DM_SEC *)src; if (!src_dm_sec) { return; } assert(dst_dm_sec); memcpy(dst_dm_sec, src_dm_sec, sizeof(tBTA_DM_SEC)); if (msg->act == BTA_DM_BLE_KEY_EVT) { dst_dm_sec->ble_key.p_key_value = osi_malloc(sizeof(tBTM_LE_KEY_VALUE)); assert(src_dm_sec->ble_key.p_key_value); assert(dst_dm_sec->ble_key.p_key_value); memcpy(dst_dm_sec->ble_key.p_key_value, src_dm_sec->ble_key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); } } /******************************************************************************* ** ** Function btc_dm_evt ** ** Description Switches context from BTE to BTC for all DM events ** ** Returns void ** *******************************************************************************/ void btc_dm_sec_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *data) { btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_DM_SEC; msg.act = event; btc_transfer_context(&msg, (btc_dm_sec_args_t *)data, sizeof(btc_dm_sec_args_t), btc_dm_sec_arg_deep_copy); } static void btc_enable_bluetooth_evt(tBTA_STATUS status) { if (status == BTA_SUCCESS) { future_ready(*btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE), FUTURE_SUCCESS); } else { future_ready(*btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE), FUTURE_FAIL); } } static void btc_disable_bluetooth_evt(void) { BTC_TRACE_DEBUG("%s", __FUNCTION__); future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_SUCCESS); } #if (SMP_INCLUDED == TRUE) void btc_dm_load_ble_local_keys(void) { memset(&ble_local_key_cb, 0, sizeof(btc_dm_local_key_cb_t)); if (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_ER,(char*)&ble_local_key_cb.er[0], BT_OCTET16_LEN)== BT_STATUS_SUCCESS) { ble_local_key_cb.is_er_rcvd = TRUE; BTC_TRACE_DEBUG("%s BLE ER key loaded",__func__ ); } if ((btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IR,(char*)&ble_local_key_cb.id_keys.ir[0], BT_OCTET16_LEN)== BT_STATUS_SUCCESS )&& (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IRK, (char*)&ble_local_key_cb.id_keys.irk[0], BT_OCTET16_LEN)== BT_STATUS_SUCCESS)&& (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_DHK,(char*)&ble_local_key_cb.id_keys.dhk[0], BT_OCTET16_LEN)== BT_STATUS_SUCCESS)) { ble_local_key_cb.is_id_keys_rcvd = TRUE; BTC_TRACE_DEBUG("%s BLE ID keys loaded", __func__); } } void btc_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er, tBTA_BLE_LOCAL_ID_KEYS *p_id_keys) { if (ble_local_key_cb.is_er_rcvd ) { memcpy(&er[0], &ble_local_key_cb.er[0], sizeof(BT_OCTET16)); *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ER; } if (ble_local_key_cb.is_id_keys_rcvd) { memcpy(&p_id_keys->ir[0], &ble_local_key_cb.id_keys.ir[0], sizeof(BT_OCTET16)); memcpy(&p_id_keys->irk[0], &ble_local_key_cb.id_keys.irk[0], sizeof(BT_OCTET16)); memcpy(&p_id_keys->dhk[0], &ble_local_key_cb.id_keys.dhk[0], sizeof(BT_OCTET16)); *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID; } BTC_TRACE_DEBUG("%s *p_key_mask=0x%02x",__func__, *p_key_mask); } static void btc_dm_remove_ble_bonding_keys(void) { bt_bdaddr_t bd_addr; BTC_TRACE_DEBUG("%s\n",__func__); bdcpy(bd_addr.address, pairing_cb.bd_addr); btc_storage_remove_remote_addr_type(&bd_addr, false); btc_storage_remove_ble_dev_auth_mode(&bd_addr, false); btc_storage_remove_ble_dev_type(&bd_addr, false); btc_storage_remove_ble_bonding_keys(&bd_addr); } static void btc_dm_save_ble_bonding_keys(void) { if (!(pairing_cb.ble.is_penc_key_rcvd || pairing_cb.ble.is_pid_key_rcvd || pairing_cb.ble.is_pcsrk_key_rcvd || pairing_cb.ble.is_lenc_key_rcvd || pairing_cb.ble.is_lcsrk_key_rcvd || pairing_cb.ble.is_lidk_key_rcvd)) { return ; } bt_bdaddr_t bd_addr; bdcpy(bd_addr.address, pairing_cb.bd_addr); btc_storage_set_ble_dev_type(&bd_addr, false); BTC_TRACE_DEBUG("%s, penc = %d, pid = %d", __func__, pairing_cb.ble.is_penc_key_rcvd, pairing_cb.ble.is_pid_key_rcvd); if (pairing_cb.ble.is_penc_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, (char *) &pairing_cb.ble.penc_key, BTM_LE_KEY_PENC, sizeof(tBTM_LE_PENC_KEYS)); pairing_cb.ble.is_penc_key_rcvd = false; } if (pairing_cb.ble.is_pid_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, (char *) &pairing_cb.ble.pid_key, BTM_LE_KEY_PID, sizeof(tBTM_LE_PID_KEYS)); pairing_cb.ble.is_pid_key_rcvd = false; } if (pairing_cb.ble.is_pcsrk_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, (char *) &pairing_cb.ble.pcsrk_key, BTM_LE_KEY_PCSRK, sizeof(tBTM_LE_PCSRK_KEYS)); pairing_cb.ble.is_pcsrk_key_rcvd = false; } if (pairing_cb.ble.is_lenc_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, (char *) &pairing_cb.ble.lenc_key, BTM_LE_KEY_LENC, sizeof(tBTM_LE_LENC_KEYS)); pairing_cb.ble.is_lenc_key_rcvd = false; } if (pairing_cb.ble.is_lcsrk_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, (char *) &pairing_cb.ble.lcsrk_key, BTM_LE_KEY_LCSRK, sizeof(tBTM_LE_LCSRK_KEYS)); pairing_cb.ble.is_lcsrk_key_rcvd = false; } if (pairing_cb.ble.is_lidk_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, NULL, BTM_LE_KEY_LID, 0); pairing_cb.ble.is_lidk_key_rcvd = false; } } static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) { /* Save link key, if not temporary */ BTC_TRACE_DEBUG("%s, status = %d", __func__, p_auth_cmpl->success); bt_status_t status = BT_STATUS_FAIL; int addr_type; bt_bdaddr_t bdaddr; bdcpy(bdaddr.address, p_auth_cmpl->bd_addr); bdcpy(pairing_cb.bd_addr, p_auth_cmpl->bd_addr); if (p_auth_cmpl->success) { status = BT_STATUS_SUCCESS; BTC_TRACE_DEBUG ("%s, - p_auth_cmpl->bd_addr: %08x%04x", __func__, (p_auth_cmpl->bd_addr[0] << 24) + (p_auth_cmpl->bd_addr[1] << 16) + (p_auth_cmpl->bd_addr[2] << 8) + p_auth_cmpl->bd_addr[3], (p_auth_cmpl->bd_addr[4] << 8) + p_auth_cmpl->bd_addr[5]); BTC_TRACE_DEBUG ("%s, - pairing_cb.bd_addr: %08x%04x", __func__, (pairing_cb.bd_addr[0] << 24) + (pairing_cb.bd_addr[1] << 16) + (pairing_cb.bd_addr[2] << 8) + pairing_cb.bd_addr[3], (pairing_cb.bd_addr[4] << 8) + pairing_cb.bd_addr[5]); // Check if need to save BLE keys if((p_auth_cmpl->auth_mode & SMP_AUTH_GEN_BOND) == 0) { return; } if (btc_storage_get_remote_addr_type(&bdaddr, &addr_type) != BT_STATUS_SUCCESS) { btc_storage_set_remote_addr_type(&bdaddr, p_auth_cmpl->addr_type, true); } btc_storage_set_ble_dev_auth_mode(&bdaddr, p_auth_cmpl->auth_mode, true); btc_dm_save_ble_bonding_keys(); } else { /*Map the HCI fail reason to bt status */ switch (p_auth_cmpl->fail_reason) { case BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL: case BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL: btc_dm_remove_ble_bonding_keys(); status = BT_STATUS_AUTH_FAILURE; break; case BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT: status = BT_STATUS_AUTH_REJECTED; break; default: btc_dm_remove_ble_bonding_keys(); status = BT_STATUS_FAIL; break; } } #if (CONFIG_BT_STACK_NO_LOG) (void) status; #endif BTC_TRACE_DEBUG("%s, authentication status = %x", __func__, status); return; } #endif ///SMP_INCLUDED == TRUE static void btc_dm_link_up_evt(tBTA_DM_LINK_UP *p_link_up) { BD_ADDR bd_addr; bt_bdaddr_t bt_bdaddr; if (p_link_up->sc_downgrade == 1) { memcpy(bt_bdaddr.address, p_link_up->bd_addr, sizeof(BD_ADDR)); if (btc_storage_remove_bonded_device(&bt_bdaddr) == BT_STATUS_SUCCESS) { memcpy(bd_addr, p_link_up->bd_addr, sizeof(BD_ADDR)); if (BTA_DmRemoveDevice(bd_addr, BT_TRANSPORT_BR_EDR) == BTA_SUCCESS) { BTC_TRACE_EVENT(" %s() Bonding information removed.", __FUNCTION__); } else { BTC_TRACE_ERROR(" %s() BTA_DmRemoveDevice error", __FUNCTION__); } } else { BTC_TRACE_ERROR(" %s() btc_storage_remove_bonded_device error", __FUNCTION__); } } } static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) { /* Save link key, if not temporary */ bt_bdaddr_t bd_addr; bt_status_t status; BTC_TRACE_DEBUG("%s: bond state success %d, present %d, type%d\n", __func__, p_auth_cmpl->success, p_auth_cmpl->key_present, p_auth_cmpl->key_type); bdcpy(bd_addr.address, p_auth_cmpl->bd_addr); if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) ) { #if 0 if ((p_auth_cmpl->key_type < HCI_LKEY_TYPE_DEBUG_COMB) || (p_auth_cmpl->key_type == HCI_LKEY_TYPE_AUTH_COMB) || (p_auth_cmpl->key_type == HCI_LKEY_TYPE_CHANGED_COMB) || (p_auth_cmpl->key_type == HCI_LKEY_TYPE_AUTH_COMB_P_256) ) #endif if (1) { bt_status_t ret; BTC_TRACE_DEBUG("%s: Storing link key. key_type=0x%x", __FUNCTION__, p_auth_cmpl->key_type); ret = btc_storage_add_bonded_device(&bd_addr, p_auth_cmpl->key, p_auth_cmpl->key_type, 16, p_auth_cmpl->sc_support); BTC_ASSERTC(ret == BT_STATUS_SUCCESS, "storing link key failed", ret); } else { BTC_TRACE_DEBUG("%s: Temporary key. Not storing. key_type=0x%x", __FUNCTION__, p_auth_cmpl->key_type); } } // Skip SDP for certain HID Devices if (p_auth_cmpl->success) { status = BT_STATUS_SUCCESS; } else { // Map the HCI fail reason to bt status switch (p_auth_cmpl->fail_reason) { case HCI_ERR_PAGE_TIMEOUT: BTC_TRACE_WARNING("%s() - Pairing timeout; retrying () ...", __FUNCTION__); return; /* Fall-through */ case HCI_ERR_CONNECTION_TOUT: status = BT_STATUS_RMT_DEV_DOWN; break; case HCI_ERR_PAIRING_NOT_ALLOWED: status = BT_STATUS_AUTH_REJECTED; break; case HCI_ERR_LMP_RESPONSE_TIMEOUT: status = BT_STATUS_AUTH_FAILURE; break; /* map the auth failure codes, so we can retry pairing if necessary */ case HCI_ERR_AUTH_FAILURE: case HCI_ERR_KEY_MISSING: btc_storage_remove_bonded_device(&bd_addr); case HCI_ERR_HOST_REJECT_SECURITY: case HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE: case HCI_ERR_UNIT_KEY_USED: case HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED: case HCI_ERR_INSUFFCIENT_SECURITY: case HCI_ERR_PEER_USER: case HCI_ERR_UNSPECIFIED: BTC_TRACE_ERROR(" %s() Authentication fail reason %d", __FUNCTION__, p_auth_cmpl->fail_reason); /* if autopair attempts are more than 1, or not attempted */ status = BT_STATUS_AUTH_FAILURE; break; default: status = BT_STATUS_FAIL; } } #if (BTC_GAP_BT_INCLUDED == TRUE) esp_bt_gap_cb_param_t param; bt_status_t ret; btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_AUTH_CMPL_EVT; param.auth_cmpl.stat = status; memcpy(param.auth_cmpl.bda, p_auth_cmpl->bd_addr, ESP_BD_ADDR_LEN); memcpy(param.auth_cmpl.device_name, p_auth_cmpl->bd_name, ESP_BT_GAP_MAX_BDNAME_LEN + 1); ret = btc_inter_profile_call(&msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } #endif /// BTC_GAP_BT_INCLUDED == TRUE (void) status; } static void btc_dm_pin_req_evt(tBTA_DM_PIN_REQ *p_pin_req) { #if (BTC_GAP_BT_INCLUDED == TRUE) esp_bt_gap_cb_param_t param; bt_status_t ret; btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_PIN_REQ_EVT; param.pin_req.min_16_digit = p_pin_req->min_16_digit; memcpy(param.pin_req.bda, p_pin_req->bd_addr, ESP_BD_ADDR_LEN); ret = btc_inter_profile_call(&msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } #endif /// BTC_GAP_BT_INCLUDED == TRUE } #if (BT_SSP_INCLUDED == TRUE) static void btc_dm_sp_cfm_req_evt(tBTA_DM_SP_CFM_REQ *p_cfm_req) { #if (BTC_GAP_BT_INCLUDED == TRUE) if (p_cfm_req->just_works) { // just work, not show to users. BTA_DmConfirm(p_cfm_req->bd_addr, true); return; } esp_bt_gap_cb_param_t param; bt_status_t ret; btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_CFM_REQ_EVT; param.cfm_req.num_val = p_cfm_req->num_val; memcpy(param.cfm_req.bda, p_cfm_req->bd_addr, ESP_BD_ADDR_LEN); ret = btc_inter_profile_call(&msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } #endif /// BTC_GAP_BT_INCLUDED == TRUE } static void btc_dm_sp_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_key_notif) { #if (BTC_GAP_BT_INCLUDED == TRUE) esp_bt_gap_cb_param_t param; bt_status_t ret; btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_KEY_NOTIF_EVT; param.key_notif.passkey = p_key_notif->passkey; memcpy(param.key_notif.bda, p_key_notif->bd_addr, ESP_BD_ADDR_LEN); ret = btc_inter_profile_call(&msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } #endif /// BTC_GAP_BT_INCLUDED == TRUE } static void btc_dm_sp_key_req_evt(tBTA_DM_SP_KEY_REQ *p_key_req) { #if (BTC_GAP_BT_INCLUDED == TRUE) esp_bt_gap_cb_param_t param; bt_status_t ret; btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_KEY_REQ_EVT; memcpy(param.key_req.bda, p_key_req->bd_addr, ESP_BD_ADDR_LEN); ret = btc_inter_profile_call(&msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } #endif /// BTC_GAP_BT_INCLUDED == TRUE } #endif /// BT_SSP_INCLUDED == TRUE static void btc_dm_dev_unpaired_evt(tBTA_DM_LINK_DOWN *p_link_down) { esp_bt_gap_cb_param_t param; BTC_TRACE_DEBUG("%s",__func__); memcpy(param.remove_bond_dev_cmpl.bda, p_link_down->bd_addr, ESP_BD_ADDR_LEN); btm_set_bond_type_dev(p_link_down->bd_addr, BOND_TYPE_UNKNOWN); if (p_link_down->status == HCI_SUCCESS) { //remove the bonded key in the config and nvs flash. param.remove_bond_dev_cmpl.status = btc_storage_remove_bonded_device((bt_bdaddr_t *)param.remove_bond_dev_cmpl.bda); } else { param.remove_bond_dev_cmpl.status = ESP_BT_STATUS_FAIL; } #if (BTC_GAP_BT_INCLUDED == TRUE) bt_status_t ret; btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_REMOVE_BOND_DEV_COMPLETE_EVT; ret = btc_inter_profile_call(&msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } #endif /// BTC_GAP_BT_INCLUDED == TRUE } tBTA_SERVICE_MASK btc_get_enabled_services_mask(void) { return btc_enabled_services; } void btc_clear_services_mask(void) { btc_enabled_services = 0; } static bt_status_t btc_in_execute_service_request(tBTA_SERVICE_ID service_id, BOOLEAN b_enable) { BTC_TRACE_DEBUG("%s service_id: %d\n", __FUNCTION__, service_id); /* Check the service_ID and invoke the profile's BT state changed API */ switch (service_id) { #if BTC_AV_INCLUDED case BTA_A2DP_SOURCE_SERVICE_ID: btc_av_source_execute_service(b_enable); break; case BTA_A2DP_SINK_SERVICE_ID: btc_av_sink_execute_service(b_enable); break; #endif #if BTC_HF_CLIENT_INCLUDED case BTA_HFP_HS_SERVICE_ID: btc_hf_client_execute_service(b_enable); break; #endif /* #if BTC_HF_CLIENT_INCLUDED */ default: BTC_TRACE_ERROR("%s: Unknown service being enabled\n", __FUNCTION__); return BT_STATUS_FAIL; } return BT_STATUS_SUCCESS; } void btc_dm_execute_service_request(BOOLEAN enable, char *p_param) { btc_in_execute_service_request(*((tBTA_SERVICE_ID *)p_param), enable); } bt_status_t btc_dm_enable_service(tBTA_SERVICE_ID service_id) { tBTA_SERVICE_ID *p_id = &service_id; btc_enabled_services |= (1 << service_id); BTC_TRACE_DEBUG("%s: current services:0x%x", __FUNCTION__, btc_enabled_services); btc_dm_execute_service_request(TRUE, (char *)p_id); return BT_STATUS_SUCCESS; } bt_status_t btc_dm_disable_service(tBTA_SERVICE_ID service_id) { tBTA_SERVICE_ID *p_id = &service_id; btc_enabled_services &= (tBTA_SERVICE_MASK)(~(1 << service_id)); BTC_TRACE_DEBUG("%s: Current Services:0x%x", __FUNCTION__, btc_enabled_services); btc_dm_execute_service_request(FALSE, (char *)p_id); return BT_STATUS_SUCCESS; } void btc_dm_sec_cb_handler(btc_msg_t *msg) { btc_dm_sec_args_t *arg = (btc_dm_sec_args_t *)(msg->arg); tBTA_DM_SEC *p_data = &(arg->sec); esp_ble_gap_cb_param_t param = {0}; btc_msg_t ble_msg = {0}; bool rsp_app = false; bt_status_t ret = BT_STATUS_SUCCESS; ble_msg.sig = BTC_SIG_API_CB; ble_msg.pid = BTC_PID_GAP_BLE; // tBTA_SERVICE_MASK service_mask; BTC_TRACE_DEBUG("btc_dm_upstreams_cback ev: %d\n", msg->act); switch (msg->act) { case BTA_DM_ENABLE_EVT: { btc_clear_services_mask(); #if (SMP_INCLUDED == TRUE) btc_storage_load_bonded_devices(); //load the bonding device to the btm layer btc_storage_load_bonded_ble_devices(); #endif ///SMP_INCLUDED == TRUE /* Set initial device name, it can be overwritten later */ if (p_data->enable.status == BTA_SUCCESS) { const char *initial_device_name = "ESP32"; BTA_DmSetDeviceName(initial_device_name); } btc_enable_bluetooth_evt(p_data->enable.status); break; } 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))) { btc_in_execute_service_request(i, FALSE); } } btc_disable_bluetooth_evt(); break; } case BTA_DM_PIN_REQ_EVT: BTC_TRACE_DEBUG("BTA_DM_PIN_REQ_EVT"); btc_dm_pin_req_evt(&p_data->pin_req); break; case BTA_DM_AUTH_CMPL_EVT: btc_dm_auth_cmpl_evt(&p_data->auth_cmpl); break; case BTA_DM_BOND_CANCEL_CMPL_EVT: BTC_TRACE_DEBUG("BTA_DM_BOND_CANCEL_CMPL_EVT"); break; #if (BT_SSP_INCLUDED == TRUE) case BTA_DM_SP_CFM_REQ_EVT: btc_dm_sp_cfm_req_evt(&p_data->cfm_req); break; case BTA_DM_SP_KEY_NOTIF_EVT: btc_dm_sp_key_notif_evt(&p_data->key_notif); break; case BTA_DM_SP_KEY_REQ_EVT: btc_dm_sp_key_req_evt(&p_data->key_req); break; case BTA_DM_SP_RMT_OOB_EVT: BTC_TRACE_DEBUG("BTA_DM_SP_RMT_OOB_EVT"); break; case BTA_DM_SP_KEYPRESS_EVT: BTC_TRACE_DEBUG("BTA_DM_SP_KEYPRESS_EVT"); break; #endif ///BT_SSP_INCLUDED == TRUE case BTA_DM_DEV_UNPAIRED_EVT: { btc_dm_dev_unpaired_evt(&p_data->link_down); break; } case BTA_DM_BLE_DEV_UNPAIRED_EVT: { #if (SMP_INCLUDED == TRUE) bt_bdaddr_t bd_addr; rsp_app = true; BTC_TRACE_DEBUG("BTA_DM_BLE_DEV_UNPAIRED_EVT"); memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR)); btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN); param.remove_bond_dev_cmpl.status = ESP_BT_STATUS_FAIL; if (p_data->link_down.status == HCI_SUCCESS) { //remove the bonded key in the config and nvs flash. btc_storage_remove_ble_dev_type(&bd_addr, false); btc_storage_remove_remote_addr_type(&bd_addr, false); btc_storage_remove_ble_dev_auth_mode(&bd_addr, false); param.remove_bond_dev_cmpl.status = btc_storage_remove_ble_bonding_keys(&bd_addr); } ble_msg.act = ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT; memcpy(param.remove_bond_dev_cmpl.bd_addr, p_data->link_down.bd_addr, sizeof(BD_ADDR)); #endif /* #if (SMP_INCLUDED == TRUE) */ break; } case BTA_DM_BUSY_LEVEL_EVT: #if (BTC_GAP_BT_INCLUDED == TRUE) { if (p_data->busy_level.level_flags & BTM_BL_INQUIRY_PAGING_MASK) { btc_gap_bt_busy_level_updated(p_data->busy_level.level_flags); } break; } #endif /* BTC_GAP_BT_INCLUDED == TRUE */ case BTA_DM_LINK_DOWN_EVT: case BTA_DM_HW_ERROR_EVT: BTC_TRACE_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); break; case BTA_DM_LINK_UP_EVT: btc_dm_link_up_evt(&p_data->link_up); break; #if ((BLE_INCLUDED == TRUE) && (SMP_INCLUDED == TRUE)) case BTA_DM_BLE_AUTH_CMPL_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_AUTH_CMPL_EVT; param.ble_security.auth_cmpl.addr_type = p_data->auth_cmpl.addr_type; param.ble_security.auth_cmpl.dev_type = p_data->auth_cmpl.dev_type; param.ble_security.auth_cmpl.key_type = p_data->auth_cmpl.key_type; param.ble_security.auth_cmpl.fail_reason = p_data->auth_cmpl.fail_reason; param.ble_security.auth_cmpl.success = p_data->auth_cmpl.success ? true : false; param.ble_security.auth_cmpl.key_present = p_data->auth_cmpl.key_present; memcpy(param.ble_security.auth_cmpl.bd_addr, p_data->auth_cmpl.bd_addr, sizeof(BD_ADDR)); memcpy(param.ble_security.auth_cmpl.key, p_data->auth_cmpl.key, sizeof(LINK_KEY)); param.ble_security.auth_cmpl.auth_mode = p_data->auth_cmpl.auth_mode; btc_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl); break; } case BTA_DM_BLE_KEY_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_KEY_EVT; param.ble_security.ble_key.key_type = p_data->ble_key.key_type; memcpy(param.ble_security.ble_key.bd_addr, p_data->ble_key.bd_addr, BD_ADDR_LEN); switch (p_data->ble_key.key_type) { case BTM_LE_KEY_PENC: { BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_PENC"); pairing_cb.ble.is_penc_key_rcvd = TRUE; pairing_cb.ble.penc_key = p_data->ble_key.p_key_value->penc_key; memcpy(&pairing_cb.ble.penc_key, &p_data->ble_key.p_key_value->penc_key, sizeof(tBTM_LE_PENC_KEYS)); memcpy(¶m.ble_security.ble_key.p_key_value.penc_key, &p_data->ble_key.p_key_value->penc_key, sizeof(tBTM_LE_PENC_KEYS)); break; } case BTM_LE_KEY_PID: { BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_PID"); pairing_cb.ble.is_pid_key_rcvd = TRUE; memcpy(&pairing_cb.ble.pid_key, &p_data->ble_key.p_key_value->pid_key, sizeof(tBTM_LE_PID_KEYS)); //Note: The memory size of the addr_type in ble_security.ble_key.p_key_value.pid_key is different from that of p_data->ble_key.p_key_value->pid_key. memcpy(¶m.ble_security.ble_key.p_key_value.pid_key.irk, &p_data->ble_key.p_key_value->pid_key.irk, ESP_BT_OCTET16_LEN); param.ble_security.ble_key.p_key_value.pid_key.addr_type = p_data->ble_key.p_key_value->pid_key.addr_type; memcpy(¶m.ble_security.ble_key.p_key_value.pid_key.static_addr, &p_data->ble_key.p_key_value->pid_key.static_addr, ESP_BD_ADDR_LEN); break; } case BTM_LE_KEY_PCSRK: { BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_PCSRK"); pairing_cb.ble.is_pcsrk_key_rcvd = TRUE; memcpy(&pairing_cb.ble.pcsrk_key, &p_data->ble_key.p_key_value->pcsrk_key, sizeof(tBTM_LE_PCSRK_KEYS)); memcpy(¶m.ble_security.ble_key.p_key_value.pcsrk_key, &p_data->ble_key.p_key_value->pcsrk_key, sizeof(tBTM_LE_PCSRK_KEYS)); break; } case BTM_LE_KEY_LENC: { BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_LENC"); pairing_cb.ble.is_lenc_key_rcvd = TRUE; memcpy(&pairing_cb.ble.lenc_key, &p_data->ble_key.p_key_value->lenc_key, sizeof(tBTM_LE_LENC_KEYS)); memcpy(¶m.ble_security.ble_key.p_key_value.lenc_key, &p_data->ble_key.p_key_value->lenc_key, sizeof(tBTM_LE_LENC_KEYS)); break; } case BTM_LE_KEY_LCSRK: { BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_LCSRK"); pairing_cb.ble.is_lcsrk_key_rcvd = TRUE; memcpy(&pairing_cb.ble.lcsrk_key, &p_data->ble_key.p_key_value->lcsrk_key, sizeof(tBTM_LE_LCSRK_KEYS)); memcpy(¶m.ble_security.ble_key.p_key_value.lcsrk_key, &p_data->ble_key.p_key_value->lcsrk_key, sizeof(tBTM_LE_LCSRK_KEYS)); break; } case BTM_LE_KEY_LID: { BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_LID"); pairing_cb.ble.is_lidk_key_rcvd = TRUE; break; } default: break; } break; } case BTA_DM_BLE_SEC_REQ_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_SEC_REQ_EVT; memcpy(param.ble_security.ble_req.bd_addr, p_data->ble_req.bd_addr, BD_ADDR_LEN); break; } case BTA_DM_BLE_PASSKEY_NOTIF_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_PASSKEY_NOTIF_EVT; param.ble_security.key_notif.passkey = p_data->key_notif.passkey; memcpy(param.ble_security.key_notif.bd_addr, p_data->ble_req.bd_addr, BD_ADDR_LEN); break; } case BTA_DM_BLE_PASSKEY_REQ_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_PASSKEY_REQ_EVT; memcpy(param.ble_security.ble_req.bd_addr, p_data->ble_req.bd_addr, BD_ADDR_LEN); break; } case BTA_DM_BLE_OOB_REQ_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_OOB_REQ_EVT; memcpy(param.ble_security.ble_req.bd_addr, p_data->ble_req.bd_addr, BD_ADDR_LEN); break; } case BTA_DM_BLE_LOCAL_IR_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_LOCAL_IR_EVT; memcpy(¶m.ble_security.ble_id_keys, &p_data->ble_id_keys, sizeof(tBTA_BLE_LOCAL_ID_KEYS)); BTC_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. "); ble_local_key_cb.is_id_keys_rcvd = TRUE; memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16)); memcpy(&ble_local_key_cb.id_keys.ir[0], &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16)); memcpy(&ble_local_key_cb.id_keys.dhk[0], &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16)); btc_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.irk[0], BTC_LE_LOCAL_KEY_IRK, BT_OCTET16_LEN); btc_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.ir[0], BTC_LE_LOCAL_KEY_IR, BT_OCTET16_LEN); btc_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.dhk[0], BTC_LE_LOCAL_KEY_DHK, BT_OCTET16_LEN); break; } case BTA_DM_BLE_LOCAL_ER_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_LOCAL_ER_EVT; memcpy(¶m.ble_security.ble_id_keys, &p_data->ble_id_keys, sizeof(tBTA_BLE_LOCAL_ID_KEYS)); BTC_TRACE_DEBUG("BTA_DM_BLE_LOCAL_ER_EVT. "); ble_local_key_cb.is_er_rcvd = TRUE; memcpy(&ble_local_key_cb.er[0], &p_data->ble_er[0], sizeof(BT_OCTET16)); btc_storage_add_ble_local_key( (char *)&ble_local_key_cb.er[0], BTC_LE_LOCAL_KEY_ER, BT_OCTET16_LEN); break; } case BTA_DM_BLE_NC_REQ_EVT: { rsp_app = true; ble_msg.act = ESP_GAP_BLE_NC_REQ_EVT; memcpy(param.ble_security.key_notif.bd_addr, p_data->key_notif.bd_addr, BD_ADDR_LEN); param.ble_security.key_notif.passkey = p_data->key_notif.passkey; break; } #endif case BTA_DM_AUTHORIZE_EVT: case BTA_DM_SIG_STRENGTH_EVT: case BTA_DM_ROLE_CHG_EVT: BTC_TRACE_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); break; default: BTC_TRACE_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); break; } if (rsp_app) { ret = btc_inter_profile_call(&ble_msg, ¶m); if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_inter_profile_call failed\n", __func__); } } btc_dm_sec_arg_deep_free(msg); }