蓝牙配对流程梳理
http://www.cnblogs.com/libs-liu/p/10175949.html
蓝牙扫描
https://blog.csdn.net/xubin341719/article/details/38584469
3.static int start_discovery流程
static int start_discovery(void) {
/* sanity check */
if (!interface_ready()) return BT_STATUS_NOT_READY;
return btif_dm_start_discovery();
}
返回btif_dm_start_discovery(),关注该函数实现
bt_status_t btif_dm_start_discovery(void) {
tBTA_DM_INQ inq_params;
tBTA_SERVICE_MASK services = 0;
BTIF_TRACE_EVENT("%s", __func__);
/* Cleanup anything remaining on index 0 */
do_in_bta_thread(
FROM_HERE,
base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
auto adv_filt_param = std::make_unique();
/* Add an allow-all filter on index 0*/
adv_filt_param->dely_mode = IMMEDIATE_DELY_MODE;
adv_filt_param->feat_seln = ALLOW_ALL_FILTER;
adv_filt_param->filt_logic_type = BTA_DM_BLE_PF_FILT_LOGIC_OR;
adv_filt_param->list_logic_type = BTA_DM_BLE_PF_LIST_LOGIC_OR;
adv_filt_param->rssi_low_thres = LOWEST_RSSI_VALUE;
adv_filt_param->rssi_high_thres = LOWEST_RSSI_VALUE;
do_in_bta_thread(
FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_ADD,
0, base::Passed(&adv_filt_param),
base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
/* TODO: Do we need to handle multiple inquiries at the same time? */
/* Set inquiry params and call API */
inq_params.mode = BTA_DM_GENERAL_INQUIRY | BTA_BLE_GENERAL_INQUIRY;
inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;
inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
inq_params.report_dup = true;
inq_params.filter_type = BTA_DM_INQ_CLR;
/* TODO: Filter device by BDA needs to be implemented here */
/* Will be enabled to true once inquiry busy level has been received */
btif_dm_inquiry_in_progress = false;
/* find nearby devices */
BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
return BT_STATUS_SUCCESS;
}
1.do_in_bta_thread:Post a closure to be ran in the bta thread
2.BTA_DmSearch
搜索蓝牙设备,执行查询并获取设备的远程名称.
void BTA_DmSearch(tBTA_DM_INQ* p_dm_inq, tBTA_SERVICE_MASK services,
tBTA_DM_SEARCH_CBACK* p_cback) {
tBTA_DM_API_SEARCH* p_msg =
(tBTA_DM_API_SEARCH*)osi_calloc(sizeof(tBTA_DM_API_SEARCH));
p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
p_msg->services = services;
p_msg->p_cback = p_cback;//将函数指针赋值
p_msg->rs_res = BTA_DM_RS_NONE;
bta_sys_sendmsg(p_msg);//将该结构体变量发送
}
bta_sys_sendmsg
void bta_sys_sendmsg(void* p_msg) {
base::MessageLoop* bta_message_loop = get_message_loop();
if (!bta_message_loop || !bta_message_loop->task_runner().get()) {
APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
return;
}
bta_message_loop->task_runner()->PostTask(
FROM_HERE, base::Bind(&bta_sys_event, static_cast(p_msg)));
}
回到BTA_DmSearch,传入的函数指针是bte_search_devices_evt,关注一下这个函数
关于这个函数的注释:
从BTE切换到BTIF,进行DM搜索
/*******************************************************************************
*
* Function bte_search_devices_evt
*
* Description Switches context from BTE to BTIF for DM search events
*
* Returns void
*
******************************************************************************/
static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event,
tBTA_DM_SEARCH* p_data) {
uint16_t param_len = 0;
if (p_data) param_len += sizeof(tBTA_DM_SEARCH);
/* Allocate buffer to hold the pointers (deep copy). The pointers will point
* to the end of the tBTA_DM_SEARCH */
switch (event) {
case BTA_DM_INQ_RES_EVT: {
if (p_data->inq_res.p_eir) param_len += p_data->inq_res.eir_len;
} break;
case BTA_DM_DISC_RES_EVT: {
if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data)
param_len += p_data->disc_res.raw_data_size;
} break;
}
BTIF_TRACE_DEBUG("%s event=%s param_len=%d", __func__,
dump_dm_search_event(event), param_len);
/* if remote name is available in EIR, set teh flag so that stack doesnt
* trigger RNR */
if (event == BTA_DM_INQ_RES_EVT)
p_data->inq_res.remt_name_not_required =
check_eir_remote_name(p_data, NULL, NULL);
btif_transfer_context(
btif_dm_search_devices_evt, (uint16_t)event, (char*)p_data, param_len,
(param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);
}
关注btif_transfer_context功能
/*******************************************************************************
*
* Function btif_transfer_context
*
* Description This function switches context to btif task
*
* p_cback : callback used to process message in btif context
* event : event id of message
* p_params : parameter area passed to callback (copied)
* param_len : length of parameter area
* p_copy_cback : If set this function will be invoked for deep
* copy
*
* Returns void
*
******************************************************************************/
bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event,
char* p_params, int param_len,
tBTIF_COPY_CBACK* p_copy_cback) {
tBTIF_CONTEXT_SWITCH_CBACK* p_msg = (tBTIF_CONTEXT_SWITCH_CBACK*)osi_malloc(
sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len);
BTIF_TRACE_VERBOSE("btif_transfer_context event %d, len %d", event,
param_len);
/* allocate and send message that will be executed in btif context */
p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; /* internal event */
p_msg->p_cb = p_cback;
p_msg->event = event; /* callback event */
/* check if caller has provided a copy callback to do the deep copy */
if (p_copy_cback) {
p_copy_cback(event, p_msg->p_param, p_params);
} else if (p_params) {
memcpy(p_msg->p_param, p_params, param_len); /* callback parameter data */
}
btif_sendmsg(p_msg);
return BT_STATUS_SUCCESS;
}
该函数将传进来的函数指针赋值给p_msg->p_cb = p_cback;
并通过btif_sendmsg(p_msg),将该结构体变量发送
所以可以关注该函数传进来的函数指针内的内容
btif_transfer_context(
btif_dm_search_devices_evt, (uint16_t)event, (char*)p_data, param_len,
(param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);
其中btif_dm_search_devices_evt函数
在btif目录中执行搜索设备回调事件
/******************************************************************************
*
* Function btif_dm_search_devices_evt
*
* Description Executes search devices callback events in btif context
*
* Returns void
*
*****************************************************************************/
static void btif_dm_search_devices_evt(uint16_t event, char* p_param) {
tBTA_DM_SEARCH* p_search_data;
BTIF_TRACE_EVENT("%s event=%s", __func__, dump_dm_search_event(event));
switch (event) {
case BTA_DM_DISC_RES_EVT: {
p_search_data = (tBTA_DM_SEARCH*)p_param;
/* Remote name update */
if (strlen((const char*)p_search_data->disc_res.bd_name)) {
bt_property_t properties[1];
bt_status_t status;
properties[0].type = BT_PROPERTY_BDNAME;
properties[0].val = p_search_data->disc_res.bd_name;
properties[0].len = strlen((char*)p_search_data->disc_res.bd_name);
RawAddress& bdaddr = p_search_data->disc_res.bd_addr;
status =
btif_storage_set_remote_device_property(&bdaddr, &properties[0]);
ASSERTC(status == BT_STATUS_SUCCESS,
"failed to save remote device property", status);
HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, status, &bdaddr,
1, properties);
}
/* TODO: Services? */
} break;
case BTA_DM_INQ_RES_EVT: {
/* inquiry result */
bt_bdname_t bdname;
uint8_t remote_name_len;
tBTA_SERVICE_MASK services = 0;
p_search_data = (tBTA_DM_SEARCH*)p_param;
RawAddress& bdaddr = p_search_data->inq_res.bd_addr;
BTIF_TRACE_DEBUG("%s() %s device_type = 0x%x\n", __func__,
bdaddr.ToString().c_str(),
p_search_data->inq_res.device_type);
bdname.name[0] = 0;
if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len))
check_cached_remote_name(p_search_data, bdname.name, &remote_name_len);
/* Check EIR for remote name and services */
if (p_search_data->inq_res.p_eir) {
BTA_GetEirService(p_search_data->inq_res.p_eir,
p_search_data->inq_res.eir_len, &services);
BTIF_TRACE_DEBUG("%s()EIR BTA services = %08X", __func__,
(uint32_t)services);
/* TODO: Get the service list and check to see which uuids we got and
* send it back to the client. */
}
{
bt_property_t properties[5];
bt_device_type_t dev_type;
uint32_t num_properties = 0;
bt_status_t status;
int addr_type = 0;
memset(properties, 0, sizeof(properties));
/* RawAddress */
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr);
num_properties++;
/* BD_NAME */
/* Don't send BDNAME if it is empty */
if (bdname.name[0]) {
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
BT_PROPERTY_BDNAME,
strlen((char*)bdname.name), &bdname);
num_properties++;
}
/* DEV_CLASS */
uint32_t cod = devclass2uint(p_search_data->inq_res.dev_class);
BTIF_TRACE_DEBUG("%s cod is 0x%06x", __func__, cod);
if (cod != 0) {
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod),
&cod);
num_properties++;
}
/* DEV_TYPE */
/* FixMe: Assumption is that bluetooth.h and BTE enums match */
/* Verify if the device is dual mode in NVRAM */
int stored_device_type = 0;
if (btif_get_device_type(bdaddr, &stored_device_type) &&
((stored_device_type != BT_DEVICE_TYPE_BREDR &&
p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BREDR) ||
(stored_device_type != BT_DEVICE_TYPE_BLE &&
p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE))) {
dev_type = (bt_device_type_t)BT_DEVICE_TYPE_DUMO;
} else {
dev_type = (bt_device_type_t)p_search_data->inq_res.device_type;
}
if (p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE)
addr_type = p_search_data->inq_res.ble_addr_type;
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type),
&dev_type);
num_properties++;
/* RSSI */
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
BT_PROPERTY_REMOTE_RSSI, sizeof(int8_t),
&(p_search_data->inq_res.rssi));
num_properties++;
status =
btif_storage_add_remote_device(&bdaddr, num_properties, properties);
ASSERTC(status == BT_STATUS_SUCCESS,
"failed to save remote device (inquiry)", status);
status = btif_storage_set_remote_addr_type(&bdaddr, addr_type);
ASSERTC(status == BT_STATUS_SUCCESS,
"failed to save remote addr type (inquiry)", status);
/* Callback to notify upper layer of device */
HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties);
}
} break;
case BTA_DM_INQ_CMPL_EVT: {
do_in_bta_thread(
FROM_HERE,
base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
} break;
case BTA_DM_DISC_CMPL_EVT: {
HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
BT_DISCOVERY_STOPPED);
} break;
case BTA_DM_SEARCH_CANCEL_CMPL_EVT: {
/* if inquiry is not in progress and we get a cancel event, then
* it means we are done with inquiry, but remote_name fetches are in
* progress
*
* if inquiry is in progress, then we don't want to act on this
* cancel_cmpl_evt
* but instead wait for the cancel_cmpl_evt via the Busy Level
*
*/
if (!btif_dm_inquiry_in_progress) {
btgatt_filt_param_setup_t adv_filt_param;
memset(&adv_filt_param, 0, sizeof(btgatt_filt_param_setup_t));
do_in_bta_thread(
FROM_HERE,
base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
BT_DISCOVERY_STOPPED);
}
} break;
}
}
找到回调事件的宏列表
/* Search callback events */
#define BTA_DM_INQ_RES_EVT 0 /* Inquiry result for a peer device. */
#define BTA_DM_INQ_CMPL_EVT 1 /* Inquiry complete. */
#define BTA_DM_DISC_RES_EVT 2 /* Discovery result for a peer device. */
#define BTA_DM_DISC_BLE_RES_EVT \
3 /* Discovery result for BLE GATT based servoce on a peer device. */
#define BTA_DM_DISC_CMPL_EVT 4 /* Discovery complete. */
#define BTA_DM_DI_DISC_CMPL_EVT 5 /* Discovery complete. */
#define BTA_DM_SEARCH_CANCEL_CMPL_EVT 6 /* Search cancelled */
evet=BTA_DM_DISC_RES_EVT时