自适应调频技术是建立在自动信道质量分析基础上的一种频率自使用和功率自适应控制相结合的技术,他能使调频通信过程中自动避开被干扰的调频频点并以最小的发射功率、最低的被截获概率,达到在无干扰的调频信道上长时间保持优质通信的目的
蓝牙分层
蓝牙设备建立连接的过程
各种协议对比
蓝牙开发板的学习步骤
2和9引脚需要短接,这样才能烧写usb dongle
bluedroid
1、Android 4.2中BlueDroid的框架结构图:(Google官方提供)
init函数 文档里有讲解
init、enable函数主要实现的功能:
(1)、创建:btif_task/BTIF_TASK
(2)、初始化BTE
(3)、创建:btu_task/BTU_TASK
(4)、初始化HCI、串口相关,启动HCI工作主线程:bt_hc_callback,芯片上电、RF参数初始化、蓝牙地址名称相关设定;
interface->init函数 146行
stack_manager_get_interface()->init_stack();//会调用下面的_init_stack
const stack_manager_t* stack_manager_get_interface() {
ensure_manager_initialized();
management_thread = thread_new("stack_manager");
return &interface;
}
static const stack_manager_t interface = {init_stack, start_up_stack_async,
shut_down_stack_async, clean_up_stack,
get_stack_is_running};
thread_post(management_thread, event_init_stack, semaphore);
event_init_stack
btif_init_bluetooth();
void bte_main_boot_entry(void) {BTE MAIN API - Entry point for BTE chip/stack initialization
hci = hci_layer_get_interface();
packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//调用到C的相应接口函
packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
initNative函数的具体实现,通过bt_interface_t结构体,调用到C中的init函数实现。同时传入sBluetoothCallbacks回调函数结构体。这个函数结构体比较重要,底层的状态变化都是通过这个回调函数结构体中的函数实现。
3.1 协议栈初始化
协议栈初始化主要工作是初始化stackManager,创建stackManager工作线程,stackManager作为蓝牙协议栈的管理者,提供管理接口,主要工作即为初始化(init_stack)、打开(start_up_stack_async)、关闭(shut_down_stack_async)、清除协议栈(clean_up_stack)。每个操作会将消息发送到工作线程的工作队列中,在工作线程中执行。
init_stack进而会打开JNI工作线程(通过AttachCurrentThread将该线程连接到jvm中),该工作线程用于将底层消息回调(HAL_CBACK)到上层,sBluetoothCallbacks注册的回调。
hci_module_start_up
EXPORT_SYMBOL extern const module_t hci_module = {
.name = HCI_MODULE,
.init = NULL,
.start_up = hci_module_start_up,
.shut_down = hci_module_shut_down,
.clean_up = NULL,
.dependencies = {BTSNOOP_MODULE, NULL}};
// Interface functions
https://www.cnblogs.com/blogs-of-lxl/p/7010061.html
/*****************************************************************************
- Function BTU_StartUp
- Description Initializes the BTU control block.
NOTE: Must be called before creating any tasks
(RPC, BTU, HCIT, APPL, etc.)
- Returns void
*****************************************************************************/
void BTU_StartUp(void) {
//这个地方有关于11-01 15:52:52.869 11532 11532 D Avrcp : mVolumeStep = 4
packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/Avrcp.java:493:
bt_btif : enable: start restricted = 0
BluetoothAdapterService: startDiscovery
//bt\hci\src\hci_layer_android.cc
Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) {
LOG_DEBUG(LOG_TAG, "%s-->", __func__);
BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event);
hci_event_received(FROM_HERE, packet);
LOG_DEBUG(LOG_TAG, "%s<--", __func__);
谁来负责调用这个函数
//frameworks/base/core/java/android/bluetooth/BluetoothHeadset.java
int ret = sBluetoothInterface->start_discovery();
蓝牙搜索的流程
start_discovery函数
static int start_discovery(void) {
/* sanity check */
if (interface_ready() == false) return BT_STATUS_NOT_READY;
return btif_dm_start_discovery();
}
主要是执行这个btif_dm_start_discovery()函数
/*****************************************************************************
*
* btif api functions (no context switch)
*
****************************************************************************/
/*******************************************************************************
*
* Function btif_dm_start_discovery
*
* Description Start device discovery/inquiry
*
* Returns bt_status_t
*
******************************************************************************/
bt_status_t btif_dm_start_discovery(void) {
tBTA_DM_INQ inq_params;
tBTA_SERVICE_MASK services = 0;
BTIF_TRACE_EVENT("%s : pairing_cb.state: 0x%x", __FUNCTION__, pairing_cb.state);
/* We should not go for inquiry in BONDING STATE. */
if (pairing_cb.state == BT_BOND_STATE_BONDING)
return BT_STATUS_BUSY;
/* 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<btgatt_filt_param_setup_t>();
/* 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;
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
inq_params.intl_duration[0] = BTIF_DM_INTERLEAVE_DURATION_BR_ONE;
inq_params.intl_duration[1] = BTIF_DM_INTERLEAVE_DURATION_LE_ONE;
inq_params.intl_duration[2] = BTIF_DM_INTERLEAVE_DURATION_BR_TWO;
inq_params.intl_duration[3] = BTIF_DM_INTERLEAVE_DURATION_LE_TWO;
#endif
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;
}
主要是执行这个函数BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
/*******************************************************************************
*
* Function BTA_DmSearch
*
* Description This function searches for peer Bluetooth devices. It
* performs an inquiry and gets the remote name for devices.
* Service discovery is done if services is non zero
*
*
* Returns void
*
******************************************************************************/
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;//bte_search_devices_evt 函数
p_msg->rs_res = BTA_DM_RS_NONE;
bta_sys_sendmsg(p_msg);
}
上面的函数,填充了一个结构体,然后调用bta_sys_sendmsg(p_msg);函数
/*******************************************************************************
*
* Function bta_sys_sendmsg
*
* Description Send a GKI message to BTA. This function is designed to
* optimize sending of messages to BTA. It is called by BTA
* API functions and call-in functions.
*
* TODO (apanicke): Add location object as parameter for easier
* future debugging when doing alarm refactor
*
*
* Returns void
*
******************************************************************************/
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<BT_HDR*>(p_msg)));
}
有关base:bind的介绍
Chromium源码—base基础库说明
https://blog.csdn.net/developer1024/article/details/79875200
应该是调用bta_sys_event函数
/*******************************************************************************
*
* Function bta_sys_event
*
* Description BTA event handler; called from task event handler.
*
*
* Returns void
*
******************************************************************************/
void bta_sys_event(BT_HDR* p_msg) {
uint8_t id;
bool freebuf = true;
APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);
/* get subsystem id from event */
id = (uint8_t)(p_msg->event >> 8);
/* verify id and call subsystem event handler */
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
} else {
APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
}
if (freebuf) {
osi_free(p_msg);
}
}
主要是这个代码
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
谁会对上面的东西赋值
/*******************************************************************************
*
* Function bta_sys_register
*
* Description Called by other BTA subsystems to register their event
* handler.
*
*
* Returns void
*
******************************************************************************/
void bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg) {
bta_sys_cb.reg[id] = (tBTA_SYS_REG*)p_reg;
bta_sys_cb.is_reg[id] = true;
}
//使能蓝牙的时候注册的
define BTA_ID_DM_SEARCH 2 /* device manager search */
bta_sys_register(BTA_ID_DM_SEARCH, &bta_dm_search_reg);
主要是执行这个函数
/*******************************************************************************
*
* Function bta_dm_search_sm_execute
*
* Description State machine event handling function for DM
*
*
* Returns void
*
******************************************************************************/
bool bta_dm_search_sm_execute(BT_HDR* p_msg) {
tBTA_DM_ST_TBL state_table;
uint8_t action;
int i;
APPL_TRACE_EVENT("bta_dm_search_sm_execute state:%d, event:0x%x",
bta_dm_search_cb.state, p_msg->event);
/* look up the state table for the current state */
state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];
bta_dm_search_cb.state =
state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];
/* execute action functions */
for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++) {
action = state_table[p_msg->event & 0x00ff][i];
LOG_INFO(LOG_TAG, "%s: action:0x%x", __func__, action);
if (action < BTA_DM_SEARCH_IGNORE) {
(*bta_dm_search_action[action])((tBTA_DM_MSG*)p_msg);
} else {
break;
}
}
return true;
}
bta_dm_search_action 这是一个全局的变量,里面是一堆函数
/* action function list */
const tBTA_DM_ACTION bta_dm_search_action[] = {
bta_dm_search_start, /* 0 BTA_DM_API_SEARCH */
bta_dm_search_cancel, /* 1 BTA_DM_API_SEARCH_CANCEL */
bta_dm_discover, /* 2 BTA_DM_API_DISCOVER */
bta_dm_inq_cmpl, /* 3 BTA_DM_INQUIRY_CMPL */
bta_dm_rmt_name, /* 4 BTA_DM_REMT_NAME */
bta_dm_sdp_result, /* 5 BTA_DM_SDP_RESULT */
bta_dm_search_cmpl, /* 6 BTA_DM_SEARCH_CMPL */
bta_dm_free_sdp_db, /* 7 BTA_DM_FREE_SDP_DB */
bta_dm_disc_result, /* 8 BTA_DM_DISC_RESULT */
bta_dm_search_result, /* 9 BTA_DM_SEARCH_RESULT */
bta_dm_queue_search, /* 10 BTA_DM_QUEUE_SEARCH */
bta_dm_queue_disc, /* 11 BTA_DM_QUEUE_DISC */
bta_dm_search_clear_queue, /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
bta_dm_search_cancel_cmpl, /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
bta_dm_search_cancel_notify, /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL
*/
bta_dm_disc_rmt_name, /* 16 BTA_DM_DISC_RMT_NAME */
bta_dm_di_disc, /* 17 BTA_DM_API_DI_DISCOVER */
bta_dm_close_gatt_conn};
应该执行的是下面这个函数
/*******************************************************************************
*
* Function bta_dm_search_start
*
* Description Starts an inquiry
*
*
* Returns void
*
******************************************************************************/
void bta_dm_search_start(tBTA_DM_MSG* p_data) {
tBTM_INQUIRY_CMPL result;
size_t len = sizeof(tBT_UUID) * p_data->search.num_uuid;
bta_dm_gattc_register();
APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__,
p_bta_dm_cfg->avoid_scatter);
if (p_bta_dm_cfg->avoid_scatter &&
(p_data->search.rs_res == BTA_DM_RS_NONE) &&
bta_dm_check_av(BTA_DM_API_SEARCH_EVT)) {
memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
return;
}
BTM_ClearInqDb(NULL);
/* save search params */
bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
bta_dm_search_cb.services = p_data->search.services;
osi_free_and_reset((void**)&bta_dm_search_cb.p_srvc_uuid);
if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
p_data->search.p_uuid != NULL) {
bta_dm_search_cb.p_srvc_uuid = (tBT_UUID*)osi_malloc(len);
memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
}
result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb,
(tBTM_CMPL_CB*)bta_dm_inq_cmpl_cb);
APPL_TRACE_EVENT("%s status=%d", __func__, result.status);
if (result.status != BTM_CMD_STARTED) {
result.num_resp = 0;
bta_dm_inq_cmpl_cb((void*)&result);
}
}
重点关注下面这个函数
result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
bta_dm_inq_results_cb,
(tBTM_CMPL_CB*)bta_dm_inq_cmpl_cb);
/*******************************************************************************
*
* Function BTM_StartInquiry
*
* Description This function is called to start an inquiry.
*
* Parameters: p_inqparms - pointer to the inquiry information
* mode - GENERAL or LIMITED inquiry, BR/LE bit mask
* seperately
* duration - length in 1.28 sec intervals (If '0', the
* inquiry is CANCELLED)
* max_resps - maximum amount of devices to search for
* before ending the inquiry
* filter_cond_type - BTM_CLR_INQUIRY_FILTER,
* BTM_FILTER_COND_DEVICE_CLASS, or
* BTM_FILTER_COND_BD_ADDR
* filter_cond - value for the filter (based on
* filter_cond_type)
*
* p_results_cb - Pointer to the callback routine which gets
* called upon receipt of an inquiry result. If
* this field is NULL, the application is not
* notified.
*
* p_cmpl_cb - Pointer to the callback routine which gets
* called upon completion. If this field is
* NULL, the application is not notified when
* completed.
* Returns tBTM_STATUS
* BTM_CMD_STARTED if successfully initiated
* BTM_BUSY if already in progress
* BTM_ILLEGAL_VALUE if parameter(s) are out of range
* BTM_NO_RESOURCES if could not allocate resources to start
* the command
* BTM_WRONG_MODE if the device is not up.
*
******************************************************************************/
tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
tBTM_INQ_RESULTS_CB* p_results_cb,
tBTM_CMPL_CB* p_cmpl_cb) {
tBTM_STATUS status = BTM_CMD_STARTED;
tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
BTM_TRACE_API("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
p_inqparms->filter_cond_type);
/* Only one active inquiry is allowed in this implementation.
Also do not allow an inquiry if the inquiry filter is being updated */
if (p_inq->inq_active || p_inq->inqfilt_active) {
/*check if LE observe is already running*/
if (p_inq->scan_type == INQ_LE_OBSERVE &&
p_inq->p_inq_ble_results_cb != NULL) {
BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
p_inq->scan_type = INQ_GENERAL;
p_inq->inq_active = BTM_INQUIRY_INACTIVE;
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
btm_send_hci_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
} else {
BTM_TRACE_API("BTM_StartInquiry: return BUSY");
return (BTM_BUSY);
}
} else
p_inq->scan_type = INQ_GENERAL;
/*** Make sure the device is ready ***/
if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
(p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY &&
(p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY &&
(p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY)
return (BTM_ILLEGAL_VALUE);
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if (p_inq->next_state == BTM_FINISH) return BTM_ILLEGAL_VALUE;
#endif
/* Save the inquiry parameters to be used upon the completion of
* setting/clearing the inquiry filter */
p_inq->inqparms = *p_inqparms;
/* Initialize the inquiry variables */
p_inq->state = BTM_INQ_ACTIVE_STATE;
p_inq->p_inq_cmpl_cb = p_cmpl_cb;
p_inq->p_inq_results_cb = p_results_cb;
p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
p_inq->inq_active = p_inqparms->mode;
BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x",
p_inq->inq_active);
/* interleave scan minimal conditions */
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
/* check if both modes are present */
if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) &&
(p_inqparms->mode & BTM_BR_INQUIRY_MASK)) {
BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
p_inqparms->duration = p_inqparms->intl_duration[p_inq->next_state];
p_inq->inqparms.duration = p_inqparms->duration;
} else {
BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x",
p_inqparms->mode);
p_inq->next_state = BTM_NO_INTERLEAVING;
}
#endif
/* start LE inquiry here if requested */
if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
&&
(p_inq->next_state == BTM_BLE_ONE || p_inq->next_state == BTM_BLE_TWO ||
p_inq->next_state == BTM_NO_INTERLEAVING)
#endif
)
{
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
p_inqparms->duration,
(p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
#endif
if (!controller_get_interface()->supports_ble()) {
p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
status = BTM_ILLEGAL_VALUE;
}
/* BLE for now does not support filter condition for inquiry */
else {
status = btm_ble_start_inquiry(
(uint8_t)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
p_inqparms->duration);
if (status != BTM_CMD_STARTED) {
BTM_TRACE_ERROR("Err Starting LE Inquiry.");
p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
}
}
#if (BTA_HOST_INTERLEAVE_SEARCH == FALSE)
p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
#endif
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if (p_inq->next_state == BTM_NO_INTERLEAVING) {
p_inq->next_state = BTM_FINISH;
} else {
BTM_TRACE_API(
"BTM:Interleaving: started LE scan, Advancing to next state: %d",
p_inq->next_state + 1);
p_inq->next_state += 1;
}
/* reset next_state if status <> BTM_Started */
if (status != BTM_CMD_STARTED) p_inq->next_state = BTM_BR_ONE;
/* if interleave scan..return here */
return status;
#endif
BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
}
/* we're done with this routine if BR/EDR inquiry is not desired. */
if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
return status;
/* BR/EDR inquiry portion */
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if ((p_inq->next_state == BTM_BR_ONE || p_inq->next_state == BTM_BR_TWO ||
p_inq->next_state == BTM_NO_INTERLEAVING)) {
p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
#endif
/* If a filter is specified, then save it for later and clear the current
filter.
The setting of the filter is done upon completion of clearing of the
previous
filter.
*/
switch (p_inqparms->filter_cond_type) {
case BTM_CLR_INQUIRY_FILTER:
p_inq->state = BTM_INQ_SET_FILT_STATE;
break;
case BTM_FILTER_COND_DEVICE_CLASS:
case BTM_FILTER_COND_BD_ADDR:
/* The filter is not being used so simply clear it;
the inquiry can start after this operation */
p_inq->state = BTM_INQ_CLR_FILT_STATE;
p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
/* =============>>>> adding LE filtering here ????? */
break;
default:
return (BTM_ILLEGAL_VALUE);
}
/* Before beginning the inquiry the current filter must be cleared, so
* initiate the command */
status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
&p_inqparms->filter_cond);
if (status != BTM_CMD_STARTED) p_inq->state = BTM_INQ_INACTIVE_STATE;
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
if (p_inq->next_state == BTM_NO_INTERLEAVING)
p_inq->next_state = BTM_FINISH;
else {
BTM_TRACE_API(
"BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
p_inq->next_state + 1);
p_inq->next_state += 1;
}
}
if (status != BTM_CMD_STARTED) {
/* Some error beginning the scan process.
Reset the next_state parameter.. Do we need to reset the inq_active also?
*/
BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x",
status);
p_inq->next_state = BTM_BR_ONE;
}
#endif
return (status);
}
可以看一下这个函数的实现
status = btm_ble_start_inquiry(
btm_send_hci_set_scan_params(
btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
hci_layer_get_interface()->transmit_command(
p_buf, btu_hcif_command_complete_evt, btu_hcif_command_status_evt,
vsc_callback);
static void transmit_command(BT_HDR* command,
command_complete_cb complete_callback,
command_status_cb status_callback, void* context) {
hci_layer_get_interface()->transmit_command
hci/src/hci_layer.c: Android BlueDroid分析: OSI中的reactor的实现与使用分析 transmit_command->fixed_queue_enqueue event_command_ready(fixed_queue_dequeue)->"packet_fragmenter->fragment_and_dispatch"->transmit_fragment--->hal->transmit_data
hci/src/hci_hal_mct.c: transmit_data--->vendor
stack/include/hcidefs.h: Definitions for Link Control Commands
static int start_discovery(void) {
btif_dm_start_discovery()
bt_status_t btif_dm_start_discovery(void) {
/* Set inquiry params and call API inq_params 是构造出来的查询条件参数. */
inq_params.mode = BTA_DM_GENERAL_INQUIRY | BTA_BLE_GENERAL_INQUIRY;
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
inq_params.intl_duration[0] = BTIF_DM_INTERLEAVE_DURATION_BR_ONE;
inq_params.intl_duration[1] = BTIF_DM_INTERLEAVE_DURATION_LE_ONE;
inq_params.intl_duration[2] = BTIF_DM_INTERLEAVE_DURATION_BR_TWO;
inq_params.intl_duration[3] = BTIF_DM_INTERLEAVE_DURATION_LE_TWO;
#endif
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;
/*******************************************************************************
*
* Function BTA_DmSearch
*
* Description This function searches for peer Bluetooth devices. It
* performs an inquiry and gets the remote name for devices.
* Service discovery is done if services is non zero
*
*
* Returns void
*
******************************************************************************/
// BTA_DmSearch(&inq_params, services,bte_search_devices_evt);
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);
}
可以看到,该函数构造了一个消息p_msg,设置了事件类型以及回调函数。在这里,回调函数即前面的bte_search_devices_evt,它处理搜索的结果,并最终通过JNI提供的callback返回给上层。这个消息被发送到btu_task,由bta模块处理,代码如下
/*******************************************************************************
*
* Function bte_search_devices_evt
*
* Description Switches context from BTE to BTIF for DM search events
*
* Returns void
*
******************************************************************************/
//E:\code\phone_bsp\ocean\bt\btif\src\btif_dm.cc
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 && p_data->inq_res.p_eir) param_len += p_data->inq_res.eir_len;
} break;
case BTA_DM_DISC_RES_EVT: {
if (p_data && 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 (p_data && event == BTA_DM_INQ_RES_EVT) {
p_data->inq_res.remt_name_not_required =
check_eir_remote_name(p_data, NULL, NULL);
BTIF_TRACE_DEBUG("%s, name_not_required=%d", __func__,p_data->inq_res.remt_name_not_required);
}
//关键函数
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);
}
E:\code\phone_bsp\ocean\bt\btif\src\btif_dm.cc
/******************************************************************************
*
* 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;
bt_bdname_t alias;
memset(&alias, 0, sizeof(alias));
BTIF_DM_GET_REMOTE_PROP(&bdaddr, BT_PROPERTY_REMOTE_FRIENDLY_NAME,
&alias, sizeof(alias), properties[num_properties]);
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 */
/* send alias name as the name if alias name present */
if (alias.name[0] != '\0') {
BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
BT_PROPERTY_BDNAME,
strlen((char *)alias.name), &alias);
num_properties++;
} else if (bdname.name[0]) {
if((check_eir_is_remote_name_short(p_search_data) == TRUE) &&
(btif_storage_is_device_bonded(&bdaddr) == BT_STATUS_SUCCESS)) {
BTIF_TRACE_DEBUG("%s Don't update about the device name ", __FUNCTION__);
} else {
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 == false) {
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;
}
}
//
void bta_dm_search_start(tBTA_DM_MSG* p_data) {
//来自于这个结构体
/* action function list */
const tBTA_DM_ACTION bta_dm_search_action[] = {
bta_dm_search_start, /* 0 BTA_DM_API_SEARCH */
bta_dm_search_cancel, /* 1 BTA_DM_API_SEARCH_CANCEL */
bta_dm_discover, /* 2 BTA_DM_API_DISCOVER */
bta_dm_inq_cmpl, /* 3 BTA_DM_INQUIRY_CMPL */
bta_dm_rmt_name, /* 4 BTA_DM_REMT_NAME */
bta_dm_sdp_result, /* 5 BTA_DM_SDP_RESULT */
bta_dm_search_cmpl, /* 6 BTA_DM_SEARCH_CMPL */
bta_dm_free_sdp_db, /* 7 BTA_DM_FREE_SDP_DB */
bta_dm_disc_result, /* 8 BTA_DM_DISC_RESULT */
bta_dm_search_result, /* 9 BTA_DM_SEARCH_RESULT */
bta_dm_queue_search, /* 10 BTA_DM_QUEUE_SEARCH */
bta_dm_queue_disc, /* 11 BTA_DM_QUEUE_DISC */
bta_dm_search_clear_queue, /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
bta_dm_search_cancel_cmpl, /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
bta_dm_search_cancel_notify, /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL
*/
bta_dm_disc_rmt_name, /* 16 BTA_DM_DISC_RMT_NAME */
bta_dm_di_disc, /* 17 BTA_DM_API_DI_DISCOVER */
bta_dm_close_gatt_conn};
bool bta_dm_search_sm_execute(BT_HDR* p_msg) {
static const tBTA_SYS_REG bta_dm_search_reg = {bta_dm_search_sm_execute,
bta_dm_search_sm_disable};
tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK* p_cback) {
/* Bluetooth disabling is in progress */
if (bta_dm_cb.disabling) return BTA_FAILURE;
bta_sys_register(BTA_ID_DM, &bta_dm_reg);
bta_sys_register(BTA_ID_DM_SEARCH, &bta_dm_search_reg);
上面的结构体注册在这个地方
static const tBTA_SYS_REG bta_dm_search_reg = {bta_dm_search_sm_execute,
bta_dm_search_sm_disable};
蓝牙配对的流程
BlueDroid 蓝牙底层通信
https://www.meiwen.com.cn/subject/ptoiqxtx.html
create_bond函数, 主要参考下面这篇文章
A: How to do the createBond operation? B: Let me show you
https://www.jianshu.com/p/df2d959a8a77
static int create_bond(const RawAddress* bd_addr, int transport) {
/* sanity check */
if (interface_ready() == false) return BT_STATUS_NOT_READY;
return btif_dm_create_bond(bd_addr, transport);
}
重点关注下面这个函数btif_dm_create_bond, 看注释表示的是与一个特定设备建立连接,他做了哪些操作?
此处的btif_dm_create_bond函数不会进行实际bond操作,只是将事件抛出去,由其他的线程进行处理;
此处的设计很巧妙,因为如果上层所有的蓝牙相关操作事件下发下来,在此就进行处理,在实际编码中必然要加上很多的互斥操作,这就增加了设计的复杂性。
03-16 17:16:52.604 8727 8751 I bt_btif : btif_dm_create_bond: bd_addr=20:74:cf:0b:ef:7d, transport=0
获取了设备的类型
bt_btif_config: btif_get_device_type: Device [20:74:cf:0b:ef:7d] type 1
返回值是1,表示是传统蓝牙
system_bt_osi::device_type_t device_type;
switch (type) {
case BT_DEVICE_TYPE_BREDR:
device_type = system_bt_osi::DEVICE_TYPE_BREDR;
break;
case BT_DEVICE_TYPE_BLE:
device_type = system_bt_osi::DEVICE_TYPE_LE;
break;
case BT_DEVICE_TYPE_DUMO:
device_type = system_bt_osi::DEVICE_TYPE_DUMO;
/*******************************************************************************
*
* Function btif_dm_create_bond
*
* Description Initiate bonding with the specified device
*
* Returns bt_status_t
*
******************************************************************************/
bt_status_t btif_dm_create_bond(const RawAddress* bd_addr, int transport) {
btif_dm_create_bond_cb_t create_bond_cb;
create_bond_cb.transport = transport;
create_bond_cb.bdaddr = *bd_addr;
BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
bd_addr->ToString().c_str(), transport);
if (pairing_cb.state != BT_BOND_STATE_NONE) return BT_STATUS_BUSY;
btif_stats_add_bond_event(*bd_addr, BTIF_DM_FUNC_CREATE_BOND,
pairing_cb.state);
btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_CREATE_BOND,
(char*)&create_bond_cb,
sizeof(btif_dm_create_bond_cb_t), NULL);
return BT_STATUS_SUCCESS;
}
将这个消息发送出去,
03-16 17:16:52.604 8727 8751 D bt_btif : btif_transfer_context event 33026, len 7
那么谁来接受这个消息呢?
D bt_btif : btif task fetched event a001
/*******************************************************************************
*
* Function btif_task
*
* Description BTIF task handler managing all messages being passed
* Bluetooth HAL and BTA.
*
* Returns void
*
******************************************************************************/
static void bt_jni_msg_ready(void* context) {
BT_HDR* p_msg = (BT_HDR*)context;
BTIF_TRACE_VERBOSE("btif task fetched event %x", p_msg->event);
switch (p_msg->event) {
case BT_EVT_CONTEXT_SWITCH_EVT:
btif_context_switched(p_msg);
break;
default:
BTIF_TRACE_ERROR("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK);
break;
}
osi_free(p_msg);
}
btif_dm_generic_evt函数会接收这个事件并进行后续处理;
bt_btif : btif_dm_generic_evt: event=33026
/*******************************************************************************
*
* Function btif_dm_generic_evt
*
* Description Executes non-BTA upstream events in BTIF context
*
* Returns void
*
******************************************************************************/
static void btif_dm_generic_evt(uint16_t event, char* p_param) {
BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
switch (event) {
case BTIF_DM_CB_DISCOVERY_STARTED: {
HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
BT_DISCOVERY_STARTED);
} break;
case BTIF_DM_CB_CREATE_BOND: {
pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
btif_dm_create_bond_cb_t* create_bond_cb =
(btif_dm_create_bond_cb_t*)p_param;
btif_dm_cb_create_bond(create_bond_cb->bdaddr, create_bond_cb->transport);
} break;
case BTIF_DM_CB_REMOVE_BOND: {
btif_dm_cb_remove_bond((RawAddress*)p_param);
} break;
case BTIF_DM_CB_HID_REMOTE_NAME: {
btif_dm_cb_hid_remote_name((tBTM_REMOTE_DEV_NAME*)p_param);
} break;
case BTIF_DM_CB_BOND_STATE_BONDING: {
bond_state_changed(BT_STATUS_SUCCESS, *((RawAddress*)p_param),
BT_BOND_STATE_BONDING);
} break;
case BTIF_DM_CB_LE_TX_TEST:
case BTIF_DM_CB_LE_RX_TEST: {
uint8_t status;
STREAM_TO_UINT8(status, p_param);
HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
(status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
} break;
case BTIF_DM_CB_LE_TEST_END: {
uint8_t status;
uint16_t count = 0;
STREAM_TO_UINT8(status, p_param);
if (status == 0) STREAM_TO_UINT16(count, p_param);
HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
(status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, count);
} break;
default: {
BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
} break;
}
}
应该走的是下面这个case语句
case BTIF_DM_CB_CREATE_BOND: {
pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
btif_dm_create_bond_cb_t* create_bond_cb =
(btif_dm_create_bond_cb_t*)p_param;
btif_dm_cb_create_bond(create_bond_cb->bdaddr,
btif_dm_cb_create_bond函数会对绑定事件进行处理,此处对HID设备进行了特别的处理;
bt_btif : bond_state_changed: state=1, prev_state=0, sdp_attempts = 0
状态表
55 static final int BT_BOND_STATE_NONE = 0x00;
56 static final int BT_BOND_STATE_BONDING = 0x01;
57 static final int BT_BOND_STATE_BONDED = 0x02;
/*******************************************************************************
*
* Function btif_dm_cb_create_bond
*
* Description Create bond initiated from the BTIF thread context
* Special handling for HID devices
*
* Returns void
*
******************************************************************************/
static void btif_dm_cb_create_bond(const RawAddress& bd_addr,
tBTA_TRANSPORT transport) {
bool is_hid = check_cod(&bd_addr, COD_HID_POINTING);
if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE ) {
BTIF_TRACE_DEBUG("%s: btm_cb.pairing_state = %d, one pairing in progress ",
__func__, btm_cb.pairing_state);
LOG_INFO(LOG_TAG, "%s: btm_cb.pairing_state = %d, one pairing in progress ",
__func__, btm_cb.pairing_state);
return;
}
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
int device_type;
int addr_type;
std::string addrstr = bd_addr.ToString();
const char* bdstr = addrstr.c_str();
if (transport == BT_TRANSPORT_LE) {
if (!btif_config_get_int(bdstr, "DevType", &device_type)) {
btif_config_set_int(bdstr, "DevType", BT_DEVICE_TYPE_BLE);
}
if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) !=
BT_STATUS_SUCCESS) {
// Try to read address type. OOB pairing might have set it earlier, but
// didn't store it, it defaults to BLE_ADDR_PUBLIC
uint8_t tmp_dev_type;
uint8_t tmp_addr_type;
BTM_ReadDevInfo(bd_addr, &tmp_dev_type, &tmp_addr_type);
addr_type = tmp_addr_type;
btif_storage_set_remote_addr_type(&bd_addr, addr_type);
}
}
if ((btif_config_get_int(bdstr, "DevType", &device_type) &&
(btif_storage_get_remote_addr_type(&bd_addr, &addr_type) ==
BT_STATUS_SUCCESS) &&
(device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) ||
(transport == BT_TRANSPORT_LE)) {
BTA_DmAddBleDevice(bd_addr, addr_type, device_type);
}
if (is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0) {
bt_status_t status;
status = (bt_status_t)btif_hh_connect(&bd_addr);
if (status != BT_STATUS_SUCCESS)
bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
} else {
BTA_DmBondByTransport(bd_addr, transport);
}
/* Track originator of bond creation */
pairing_cb.is_local_initiated = true;
}
主要的函数就是这个 BTA_DmBondByTransports
这个函数的主要功能就是发送了一条消息出去
/*******************************************************************************
*
* Function BTA_DmBondByTransports
*
* Description This function initiates a bonding procedure with a peer
* device
*
*
* Returns void
*
******************************************************************************/
void BTA_DmBondByTransport(const RawAddress& bd_addr,
tBTA_TRANSPORT transport) {
tBTA_DM_API_BOND* p_msg =
(tBTA_DM_API_BOND*)osi_malloc(sizeof(tBTA_DM_API_BOND));
p_msg->hdr.event = BTA_DM_API_BOND_EVT;
p_msg->bd_addr = bd_addr;
p_msg->transport = transport;
bta_sys_sendmsg(p_msg);
}
谁来处理这个消息
/*******************************************************************************
*
* Function bta_sys_event
*
* Description BTA event handler; called from task event handler.
*
*
* Returns void
*
******************************************************************************/
void bta_sys_event(BT_HDR* p_msg) {
uint8_t id;
bool freebuf = true;
APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);
LOG_INFO(LOG_TAG, "%s: p_msg->event:0x%x", __func__, p_msg->event);
/* get subsystem id from event */
id = (uint8_t)(p_msg->event >> 8);
/* verify id and call subsystem event handler */
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
} else {
APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
}
if (freebuf) {
osi_free(p_msg);
}
}
之后调用的是哪一个函数, id = (0x107 >> 8) = 1;
bt_btif : bta_sys_event: Event 0x107
bt_btif : bta_dm_sm_execute event:0x7
static const tBTA_SYS_REG bta_dm_reg = {bta_dm_sm_execute, bta_dm_sm_disable};
bta_sys_register(BTA_ID_DM, &bta_dm_reg);
根据event调用不同的处理函数。event = 7;
/*******************************************************************************
*
* Function bta_dm_sm_execute
*
* Description State machine event handling function for DM
*
*
* Returns void
*
******************************************************************************/
bool bta_dm_sm_execute(BT_HDR* p_msg) {
uint16_t event = p_msg->event & 0x00ff;
APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event);
/* execute action functions */
if (event < BTA_DM_NUM_ACTIONS) {
(*bta_dm_action[event])((tBTA_DM_MSG*)p_msg);
}
return true;
}
调用下面的这个函数
/*******************************************************************************
*
* Function bta_dm_bond
*
* Description Bonds with peer device
*
*
* Returns void
*
******************************************************************************/
void bta_dm_bond(tBTA_DM_MSG* p_data) {
这个函数做了哪些工作, 发现设备的类型
/*******************************************************************************
*
* Function BTM_ReadDevInfo
*
* Description This function is called to read the device/address type
* of BD address.
*
* Parameter remote_bda: remote device address
* p_dev_type: output parameter to read the device type.
* p_addr_type: output parameter to read the address type.
*
******************************************************************************/
void BTM_ReadDevInfo(const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type,
tBLE_ADDR_TYPE* p_addr_type) {
*p_dev_type = BT_DEVICE_TYPE_BREDR;
*p_addr_type = BLE_ADDR_PUBLIC;
然后使用下面这个函数进行第二阶段传输
/*******************************************************************************
*
* Function btm_sec_bond_by_transport
*
* Description this is the bond function that will start either SSP or SMP.
*
* Parameters: bd_addr - Address of the device to bond
* pin_len - length in bytes of the PIN Code
* p_pin - pointer to array with the PIN Code
* trusted_mask - bitwise OR of trusted services
* (array of uint32_t)
*
* Note: After 2.1 parameters are not used and preserved here not to change API
******************************************************************************/
tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
tBT_TRANSPORT transport, uint8_t pin_len,
uint8_t* p_pin, uint32_t trusted_mask[]) {
这个函数做了哪些工作
/*******************************************************************************
*
* Function btm_find_or_alloc_dev
*
* Description Look for the record in the device database for the record
* with specified BD address
*
* Returns Pointer to the record or NULL
*
******************************************************************************/
tBTM_SEC_DEV_REC* btm_find_or_alloc_dev(const RawAddress& bd_addr) {
tBTM_SEC_DEV_REC* p_dev_rec;
BTM_TRACE_EVENT("btm_find_or_alloc_dev");
p_dev_rec = btm_find_dev(bd_addr);
if (p_dev_rec == NULL) {
/* Allocate a new device record or reuse the oldest one */
p_dev_rec = btm_sec_alloc_dev(bd_addr);
}
return (p_dev_rec);
}
/*******************************************************************************
*
* Function btm_sec_alloc_dev
*
* Description Look for the record in the device database for the record
* with specified address
*
* Returns Pointer to the record or NULL
*
******************************************************************************/
tBTM_SEC_DEV_REC* btm_sec_alloc_dev(const RawAddress& bd_addr) {
tBTM_INQ_INFO* p_inq_info;
BTM_TRACE_EVENT("btm_sec_alloc_dev");
tBTM_SEC_DEV_REC* p_dev_rec = btm_sec_allocate_dev_rec();
/* Check with the BT manager if details about remote device are known */
/* outgoing connection */
p_inq_info = BTM_InqDbRead(bd_addr);
if (p_inq_info != NULL) {
memcpy(p_dev_rec->dev_class, p_inq_info->results.dev_class, DEV_CLASS_LEN);
p_dev_rec->device_type = p_inq_info->results.device_type;
p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
} else if (bd_addr == btm_cb.connecting_bda)
memcpy(p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
/* update conn params, use default value for background connection params */
memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
p_dev_rec->bd_addr = bd_addr;
p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);
return (p_dev_rec);
}
建立连接, 蓝牙链路分两种同步链路(SCO)和异步链路(ACL)。A2DP(Advanced Audio Distribution Profile 高级音频传输模型)是跑在ACL链路上去高品质音频协议。A2DP定义了ACL(Asynchronous Connectionless 异步无连接)信道上传送单声道或立体声等高质量音A2DP 功能频信息的协议和过程
p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);
这些都是在一个函数里面
tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
status = BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG("State:%s sm4: 0x%x sec_state:%d",
btm_pair_state_descr(btm_cb.pairing_state), p_dev_rec->sm4,
p_dev_rec->sec_state);
最后的逻辑在这个地方接收
/*******************************************************************************
*
* Function btm_sec_rmt_host_support_feat_evt
*
* Description This function is called when the
* HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT is received
*
* Returns void
*
******************************************************************************/
void btm_sec_rmt_host_support_feat_evt(uint8_t* p) {
tBTM_SEC_DEV_REC* p_dev_rec;
RawAddress bd_addr; /* peer address */
BD_FEATURES features;
STREAM_TO_BDADDR(bd_addr, p);
p_dev_rec = btm_find_or_alloc_dev(bd_addr);
BTM_TRACE_EVENT("btm_sec_rmt_host_support_feat_evt sm4: 0x%x p[0]: 0x%x",
p_dev_rec->sm4, p[0]);
if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
p_dev_rec->sm4 = BTM_SM4_KNOWN;
STREAM_TO_ARRAY(features, p, HCI_FEATURE_BYTES_PER_PAGE);
if (HCI_SSP_HOST_SUPPORTED(features)) {
p_dev_rec->sm4 = BTM_SM4_TRUE;
}
BTM_TRACE_EVENT(
"btm_sec_rmt_host_support_feat_evt sm4: 0x%x features[0]: 0x%x",
p_dev_rec->sm4, features[0]);
}
}
上面这个函数被谁调用
btu_hcif_host_support_evt
上面这个函数谁调用
void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) {
谁来调用这个函数
void btu_hci_msg_process(BT_HDR* p_msg) {
获取到了对端的设备的名称调用哪个函数
/*******************************************************************************
*
* Function btm_sec_rmt_name_request_complete
*
* Description This function is called when remote name was obtained from
* the peer device
*
* Returns void
*
******************************************************************************/
void btm_sec_rmt_name_request_complete(const RawAddress* p_bd_addr,
uint8_t* p_bd_name, uint8_t status) {
a2dp协议学习
L2CAP基于信道的概念,信道的每一个端点被称为信道标识符(CID) 不同设备间CID可复用,但本地设备CID不可复用
以下是CID ACL-U和AMP-U链路的name space(LE-U未列出)
2)A2DP的连接:
AVDTP连接的建立首先依赖于L2CAP连接的建立,它会在同一条ACL Link上建立两条L2CAP Channel,一条是用来Signaling,另一条用来进行Stream,report和recovery的传输。
(1)Signaling的主要过程为:1.DISCOVER 2.GET_CAPABILITIES 3.SET_CONFIGURATION 4.OPEN 5.START。
a2dp profile 播放音频的流程
init_src函数
/*******************************************************************************
*
* Function init_src
*
* Description Initializes the AV interface for source mode
*
* Returns bt_status_t
*
******************************************************************************/
static bt_status_t init_src(
btav_source_callbacks_t* callbacks,
std::vector<btav_a2dp_codec_config_t> codec_priorities,
int max_a2dp_connections, int a2dp_multicast_state) {
bt_status_t status = BT_STATUS_FAIL;
BTIF_TRACE_EVENT("%s() with max conn = %d", __func__, max_a2dp_connections);
char value[PROPERTY_VALUE_MAX] = {'\0'};
osi_property_get("persist.vendor.bt.enable.splita2dp", value, "true");
BTIF_TRACE_ERROR("split_a2dp_status = %s",value);
bt_split_a2dp_enabled = (strcmp(value, "true") == 0);
BTIF_TRACE_ERROR("split_a2dp_status = %d",bt_split_a2dp_enabled);
if (bt_av_sink_callbacks != NULL)
// already did btif_av_init()
status = BT_STATUS_SUCCESS;
else {
if (a2dp_multicast_state && !bt_split_a2dp_enabled)
is_multicast_supported = true;
btif_max_av_clients = max_a2dp_connections;
for (int i = 0; i < btif_max_av_clients; i++)
btif_av_cb[i].codec_priorities = codec_priorities;
if (codec_config_update_enabled != false) {
BTIF_TRACE_IMP("%s: Codec cfg update enabled changed to false", __func__);
codec_config_update_enabled = false;
}
status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
if (status == BT_STATUS_SUCCESS) bt_av_src_callbacks = callbacks;
}
return status;
}
bta_sys_event方法里面没有实际的处理消息的方法。根据消息id,查询是否存在注册该id的回调函数,存在则调用回调函数处理该消息。
//bt\bta\sys\bta_sys_main.cc
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);//检查是否有相应的处理函数
} else {
APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
}
/* registration structure /
typedef struct {
tBTA_SYS_EVT_HDLR evt_hdlr;
tBTA_SYS_DISABLE* disable;
} tBTA_SYS_REG;
tBTM_STATUS btm_ble_start_inquiry(uint8_t mode, uint8_t duration) {
//发送一个bta_sys信息
bta_sys_sendmsg(p_msg);//bta_sys_event处理
这个里面讲解了base::bind的介绍
https://www.jianshu.com/writer#/notebooks/32840582/notes/39138896/preview