为了分析ESP32的蓝牙接口,是如何在协议栈上运行的,现在以最简单的启动广播为例,分析Bluedroid蓝牙协议栈整体流程。
具体数据发生过程如下:
esp_ble_gap_start_advertising()
esp_err_t esp_ble_gap_start_advertising(esp_ble_adv_params_t *adv_params)
{
btc_msg_t msg;
btc_ble_gap_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GAP_BLE;
msg.act = BTC_GAP_BLE_ACT_START_ADV;//执行事件
memcpy(&arg.start_adv.adv_params, adv_params, sizeof(esp_ble_adv_params_t));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
//函数走向
btc_transfer_context()
---------->>btc_task_post()
----------------------->>> btc_thread_handler()
----------------------------->>profile_tab()
------------------------------->>>>btc_gap_ble_call_handler()
------------------------------------>>>btc_ble_start_advertising()
-------------------------------------------BTA_DmSetBleAdvParamsAll()
//传递事件,调用响应函数进行数据下发
void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own,
tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol,
tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb)
{
p_msg->hdr.event = BTA_DM_API_BLE_ADV_PARAM_All_EVT;
...
p_msg->p_start_adv_cback = p_start_adv_cb;
...
bta_sys_sendmsg(p_msg);
}
bta_sys_sendmsg()
---------->>>>>btu_task_post()
------------->>>>>osi_thread_post(btu_thread, bta_sys_event, param, 0, timeout);
------------------------>>>>>bta_sys_event()
void bta_sys_event(void * param)
{
BT_HDR *p_msg = (BT_HDR *)param;
UINT8 id;
BOOLEAN freebuf = TRUE;
APPL_TRACE_EVENT("BTA got event 0x%x\n", p_msg->event);
/* get subsystem id from event */
id = (UINT8) (p_msg->event >> 8); //事件ID 通过BTA_DM_API_BLE_ADV_PARAM_All_EVT映射传递
/* 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("BTA got unregistered event id %d\n", id);
}
if (freebuf) {
osi_free(p_msg);
}
}
bta_sys_cb是函数指针集,这个函数指针的初始化在使能BT时会被初始化到。
<bta_sys_main.c>
void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{
bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
bta_sys_cb.is_reg[id] = TRUE;
}
//sm的意思是statemachine,状态机管理穿插在整个蓝牙管理中。
static const tBTA_SYS_REG bta_dm_reg =
{
bta_dm_sm_execute,
bta_dm_sm_disable
};
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)
{
...
memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
bta_sys_register (BTA_ID_DM, &bta_dm_reg );
bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
...
}
根据之前传递的事件ID = BTA_DM_API_BLE_ADV_PARAM_All_EVT 其调用bta_dm_sm_execute处理消息.
根据事件的不同会调用不同的注册函数。如果是事件ID BTA_DM_API_SEARCH_EVT将调用 bta_dm_search_sm_execute
//映射分配事件处理函数
BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
{
UINT16 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;
}
const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
bta_dm_ble_set_adv_params_all, /* BTA_DM_API_BLE_ADV_PARAM_All_EVT */
}
根据数据传递相关信息 广播事件也即bta_dm_ble_set_adv_params_all
bta_dm_ble_set_adv_params_all()
--------->>>>>BTM_BleStartAdv()
------------------>>>>>>>>btm_ble_start_adv()
------------------------------>>>>btsnd_hcic_ble_set_adv_enable()
------------------------------>>>> btu_hcif_send_cmd ();
-------------------------------------->>>>hci_layer_get_interface()->transmit_command();
------------------------------------直接操作HCI接口进行发送处理。
关于广播事件注册esp_ble_gap_register_callback(esp_gap_cb)) 事件回调分析如下:
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_err_t err;
switch (event) {
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:{
esp_ble_gap_start_advertising(&ble_adv_params);
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
break;
}
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
//scan start complete event to indicate scan start successfully or failed
if ((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(DEMO_TAG, "Scan start failed: %s", esp_err_to_name(err));
}
break;
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
//adv start complete event to indicate adv start successfully or failed
if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
ESP_LOGE(DEMO_TAG, "Adv start failed: %s", esp_err_to_name(err));
}
break;
case ESP_GAP_BLE_SCAN_RESULT_EVT: {
break;
default:
break;
}
break;
}
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
if ((err = param->scan_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS){
ESP_LOGE(DEMO_TAG, "Scan stop failed: %s", esp_err_to_name(err));
}
else {
ESP_LOGI(DEMO_TAG, "Stop scan successfully");
}
break;
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
if ((err = param->adv_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS){
ESP_LOGE(DEMO_TAG, "Adv stop failed: %s", esp_err_to_name(err));
}
else {
ESP_LOGI(DEMO_TAG, "Stop adv successfully");
}
break;
default:
break;
}
}
----------------------------------------------------------------------------------------
//注册广播事件:
//register the scan callback function to the gap module
if ((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK) {
ESP_LOGE(DEMO_TAG, "gap register error: %s", esp_err_to_name(status));
return;
}
-----------------------------------111111------------------------------------------------
注册BTC_PID_GAP_BLE事件第一步,引入用户层处理函数 callback =esp_gap_cb:
esp_err_t esp_ble_gap_register_callback(esp_gap_ble_cb_t callback)
{
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_GAP_BLE, callback) == 0 ? ESP_OK : ESP_FAIL);
}
-----------------------------------2222222222222--------------------------------------
将用户回调继续传递到下一层数据处理中
static inline void btc_gap_ble_cb_to_app(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
esp_gap_ble_cb_t btc_gap_ble_cb = (esp_gap_ble_cb_t)btc_profile_cb_get(BTC_PID_GAP_BLE);
if (btc_gap_ble_cb) {
btc_gap_ble_cb(event, param);
}
}
-------------------------------------------333333333-------------------------------------
传递到BTC层回调处理中:
void btc_gap_ble_cb_handler(btc_msg_t *msg)
{
esp_ble_gap_cb_param_t *param = (esp_ble_gap_cb_param_t *)msg->arg;
if (msg->act < ESP_GAP_BLE_EVT_MAX) {
btc_gap_ble_cb_to_app(msg->act, param);
} else {
BTC_TRACE_ERROR("%s, unknow msg->act = %d", __func__, msg->act);
}
btc_gap_ble_cb_deep_free(msg);
}
-----------------------------4444444444444444---------------------------------
btc_gap_ble_cb_handler被引用在profile_tab数组事件处理中:
static const btc_func_t profile_tab[BTC_PID_NUM] =
{
[BTC_PID_GAP_BLE] = {btc_gap_ble_call_handler, btc_gap_ble_cb_handler },
}
当触发BTC_SIG_API_CB消息就会进入btc_gap_ble_cb_handler 处理数据回调返回用户层
static void btc_thread_handler(void *arg)
{
btc_msg_t *msg = (btc_msg_t *)arg;
...
switch (msg->sig) {
case BTC_SIG_API_CALL:
profile_tab[msg->pid].btc_call(msg);
break;
case BTC_SIG_API_CB:
profile_tab[msg->pid].btc_cb(msg);
break;
default:
break;
}
...
}
-------------------------------55555555555555------------------------------------
由于上面讲广播指令下方会触发 BTC_SIG_API_CALL的事件,并触发响应事件如下:
oid btc_gap_ble_call_handler(btc_msg_t *msg)
{
case BTC_GAP_BLE_ACT_START_ADV:
btc_ble_start_advertising(&arg->start_adv.adv_params, btc_start_adv_callback);
}
启动广播后状态变化会触发 btc_start_adv_callback回调函数。
static void btc_start_adv_callback(uint8_t status)
{
esp_ble_gap_cb_param_t param;
bt_status_t ret;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_GAP_BLE;
msg.act = ESP_GAP_BLE_ADV_START_COMPLETE_EVT;
param.adv_start_cmpl.status = btc_hci_to_esp_status(status);
ret = btc_transfer_context(&msg, ¶m,
sizeof(esp_ble_gap_cb_param_t), NULL);
if (ret != BT_STATUS_SUCCESS) {
BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__);
}
}
--------------------------------666666666666------------------------
此时就会携带用户层事件:ESP_GAP_BLE_ADV_START_COMPLETE_EVT向上层传递。
//函数走向
btc_transfer_context()
---------->>btc_task_post()
----------------------->>> btc_thread_handler()
----------------------------->>profile_tab()
------------------------------->>>>btc_gap_ble_cb_handler() 与广播不同。
在结合第33333333333333333步骤中的过程。就能回溯到事件到用户层。
(仅供参考,如有问题请留言)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)