基于ESP32的Bluedroid蓝牙协议栈架构分析(2)--- ADV广播流程分析

2023-05-16

 为了分析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, &param,
                               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(使用前将#替换为@)

基于ESP32的Bluedroid蓝牙协议栈架构分析(2)--- ADV广播流程分析 的相关文章

随机推荐