藍(lán)牙協(xié)議棧里面組件之間通過隊(duì)列進(jìn)行消息通信。
方法
與隊(duì)列相關(guān)的方法
- fixed_queue_register_dequeue 注冊隊(duì)列,關(guān)聯(lián)隊(duì)列和處理消息方法
- fixed_queue_enqueue 消息入隊(duì)方法
- fixed_queue_dequeue是出隊(duì)方法
例如在btu_init.c btu_task.c
// Communication queue between btu_task and bta.
//btu_task和bta 關(guān)聯(lián)隊(duì)列
extern fixed_queue_t *btu_bta_msg_queue;
// Communication queue between btu_task and hci.
//btu_task 和hci 關(guān)聯(lián)隊(duì)列
extern fixed_queue_t *btu_hci_msg_queue;
btu_hci_msg_queue
btu_hci_msg_queue隊(duì)列初始化在bte_main.c的bte_main_boot_entry方法
void bte_main_boot_entry(void)
{
module_init(get_module(GKI_MODULE));
module_init(get_module(COUNTER_MODULE));
hci = hci_layer_get_interface();
if (!hci)
LOG_ERROR("%s could not get hci layer interface.", __func__);
btu_hci_msg_queue = fixed_queue_new(SIZE_MAX);
......省略.......
}
有了消息隊(duì)列,就需要相應(yīng)的方法來讀取消息隊(duì)列中的消息,bluedroid中通過**fixed_queue_register_dequeue**方法來關(guān)聯(lián)消息隊(duì)列和讀取線程。
在btu task啟動的時候,會關(guān)聯(lián)相應(yīng)的隊(duì)列,如btu_bta_msg_queue、btu_hci_msg_queue、btu_general_alarm_queue、btu_oneshot_alarm_queue、btu_l2cap_alarm_queue
```java
void btu_task_start_up(UNUSED_ATTR void *context) {
BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API,
"btu_task pending for preload complete event");
LOG_INFO("Bluetooth chip preload is complete");
BT_TRACE(TRACE_LAYER_BTU, TRACE_TYPE_API,
"btu_task received preload complete event");
/* Initialize the mandatory core stack control blocks
初始化核心堆棧控制塊
(BTU, BTM, L2CAP, and SDP)
*/
btu_init_core();
/* Initialize any optional stack components */
BTE_InitStack();
bta_sys_init();
/* Initialise platform trace levels at this point as BTE_InitStack() and bta_sys_init()
* reset the control blocks and preset the trace level with XXX_INITIAL_TRACE_LEVEL
*/
#if ( BT_USE_TRACES==TRUE )
module_init(get_module(BTE_LOGMSG_MODULE));
#endif
// Inform the bt jni thread initialization is ok.
btif_transfer_context(btif_init_ok, 0, NULL, 0, NULL);
//btu_bta_msg_queue 消息隊(duì)列
//bt_workqueue_thread 工作線程
//btu_bta_msg_ready 消息處理方法,
//發(fā)送到btu_bta_msg_queue消息,會被btu_bta_msg_ready讀取
//btu_hci_msg_ready 消息處理方法
fixed_queue_register_dequeue(btu_bta_msg_queue,
thread_get_reactor(bt_workqueue_thread),
btu_bta_msg_ready,
NULL);
fixed_queue_register_dequeue(btu_hci_msg_queue,
thread_get_reactor(bt_workqueue_thread),
btu_hci_msg_ready,
NULL);
.........省略.............
}
fixed_queue_register_dequeue方法將btu_hci_msg_queue隊(duì)列和btu_hci_msg_ready方法關(guān)聯(lián)起來,
當(dāng)btu_bta_msg_queue隊(duì)列中有數(shù)據(jù)時,btu_bta_msg_ready便會讀取數(shù)據(jù),并處理
消息發(fā)送
消息入隊(duì)方法 fixed_queue_enqueue方法,發(fā)送消息可以調(diào)用btu_hcif_command_complete_evt或btu_hcif_command_status_evt方法。
static void btu_hcif_command_status_evt(uint8_t status, BT_HDR *command, void *context)
{
BT_HDR *event = osi_calloc(sizeof(BT_HDR) + sizeof(command_status_hack_t));
command_status_hack_t *hack = (command_status_hack_t *)&event->data[0];
hack->callback = btu_hcif_command_status_evt_on_task;
hack->status = status;
hack->command = command;
hack->context = context;
event->event = BTU_POST_TO_TASK_NO_GOOD_HORRIBLE_HACK;
fixed_queue_enqueue(btu_hci_msg_queue, event);
}
消息處理
btu_hci_msg_ready會取出存入btu_hci_msg_queue隊(duì)列的方法
void btu_hci_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
btu_hci_msg_process(p_msg);
}
獲取隊(duì)列消息后由btu_hci_msg_process方法處理。
btu_bta_msg_queue
btu_bta_msg_queue隊(duì)列初始化在btu_init.c的方法BTU_StartUp
void BTU_StartUp(void)
{
memset (&btu_cb, 0, sizeof (tBTU_CB));
btu_cb.trace_level = HCI_INITIAL_TRACE_LEVEL;
//初始化btu_task and bta之間關(guān)聯(lián)隊(duì)列
btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);
if (btu_bta_msg_queue == NULL)
goto error_exit;
..........
}
與btu_hci_msg_queue一樣,隊(duì)列關(guān)聯(lián)是在btu task啟動的時候,即方法btu_task_start_up;
fixed_queue_register_dequeue(btu_bta_msg_queue,
thread_get_reactor(bt_workqueue_thread),
btu_bta_msg_ready,
NULL);
消息發(fā)送
void bta_sys_sendmsg(void *p_msg)
{
// There is a race condition that occurs if the stack is shut down while
// there is a procedure in progress that can schedule a task via this
// message queue. This causes |btu_bta_msg_queue| to get cleaned up before
// it gets used here; hence we check for NULL before using it.
if (btu_bta_msg_queue)
fixed_queue_enqueue(btu_bta_msg_queue, p_msg);
}
bta_sys_sendmsg方法調(diào)用fixed_queue_enqueue實(shí)現(xiàn)消息的入隊(duì)。
bta消息一般都是btif事件產(chǎn)生,比如啟動藍(lán)牙EnableBluetooth,就會發(fā)送事件id為BTA_DM_API_ENABLE_EVT的消息
tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
{
tBTA_DM_API_ENABLE *p_msg;
/* Bluetooth disabling is in progress */
if (bta_dm_cb.disabling)
return BTA_FAILURE;
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 );
/* if UUID list is not provided as static data */
bta_sys_eir_register(bta_dm_eir_update_uuid);
if ((p_msg = (tBTA_DM_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE))) != NULL)
{
p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;
p_msg->p_sec_cback = p_cback;
//發(fā)送一個bta_sys信息
bta_sys_sendmsg(p_msg);
return BTA_SUCCESS;
}
return BTA_FAILURE;
}
消息處理
下面btu_bta_msg_ready方法,如何處理消息
void btu_bta_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
bta_sys_event(p_msg);
}
btu_bta_msg_ready取出最新消息后,交由方法bta_sys_event處理
void bta_sys_event(BT_HDR *p_msg)
{
UINT8 id;
BOOLEAN freebuf = TRUE;
APPL_TRACE_EVENT("BTA got event 0x%x", p_msg->event);
/* get subsystem id from event */
//獲取對應(yīng)的時間id
id = (UINT8) (p_msg->event >> 8);
/* verify id and call subsystem event handler */
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
{
//交由事件id的回調(diào)函數(shù)處理該事件
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
}
else
{
APPL_TRACE_WARNING("BTA got unregistered event id %d", id);
}
if (freebuf)
{ //釋放內(nèi)存
GKI_freebuf(p_msg);
}
}
bta_sys_event方法里面沒有實(shí)際的處理消息的方法。根據(jù)消息id,查詢是否存在注冊該id的回調(diào)函數(shù),存在則調(diào)用回調(diào)函數(shù)處理該消息。
回調(diào)函數(shù)在何時被注冊?
函數(shù)指針的賦值在一般在各個profile初始化的時候,調(diào)用bta_sys_main.c的方法bta_sys_register賦值
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;
}
在藍(lán)牙啟動的時候注冊,即方法BTA_EnableBluetooth
bta_sys_register (BTA_ID_DM, &bta_dm_reg );
static const tBTA_SYS_REG bta_dm_reg =
{ //狀態(tài)機(jī)處理消息
bta_dm_sm_execute,
bta_dm_sm_disable
};
當(dāng)發(fā)送消息類型為BTA_ID_DM時,交由bta_dm_sm_execute方法處理,bta_dm_sm_execute里面會使用狀態(tài)機(jī)處理各類消息。
BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),BTA_SYS_EVT_START會將數(shù)字左移8位;方法bta_sys_event首先將id右移8位,BTA_DM_API_ENABLE_EVT經(jīng)過移位后是BTA_ID_DM,調(diào)用bta_dm_sm_execute處理,BTA_DM_API_ENABLE_EVT經(jīng)過& 0x00ff得到bta_dm_action數(shù)組中對應(yīng)的方法,即bta_dm_enable方法。
一些數(shù)據(jù)結(jié)構(gòu)
tBTA_DM_SEARCH_CB 在bta層
tBTM_CB 在btm層,里面包含回調(diào)指針函數(shù)
cb含義是control block
事件傳遞
BTIF->BTA->BTM->BTU->HCI
獲取數(shù)據(jù)后
HCI->BTU->BTM->BTA->BTIF層層上傳,將數(shù)據(jù)傳傳遞到上層。
BlueDroid入口函數(shù)bte_main.c中 bte_main_enable方法。
類
- bta_sys_main.c BTA 系統(tǒng)管理實(shí)現(xiàn)