蓝牙协议栈里面组件之间通过队列进行消息通信。
方法
与队列相关的方法
- fixed_queue_register_dequeue 注册队列,关联队列和处理消息方法
- fixed_queue_enqueue 消息入队方法
- fixed_queue_dequeue是出队方法
例如在btu_init.c btu_task.c
// Communication queue between btu_task and bta.
//btu_task和bta 关联队列
extern fixed_queue_t *btu_bta_msg_queue;
// Communication queue between btu_task and hci.
//btu_task 和hci 关联队列
extern fixed_queue_t *btu_hci_msg_queue;
btu_hci_msg_queue
btu_hci_msg_queue队列初始化在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);
......省略.......
}
有了消息队列,就需要相应的方法来读取消息队列中的消息,bluedroid中通过**fixed_queue_register_dequeue**方法来关联消息队列和读取线程。
在btu task启动的时候,会关联相应的队列,如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 消息队列
//bt_workqueue_thread 工作线程
//btu_bta_msg_ready 消息处理方法,
//发送到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队列和btu_hci_msg_ready方法关联起来,
当btu_bta_msg_queue队列中有数据时,btu_bta_msg_ready便会读取数据,并处理
消息发送
消息入队方法 fixed_queue_enqueue方法,发送消息可以调用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队列的方法
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);
}
获取队列消息后由btu_hci_msg_process方法处理。
btu_bta_msg_queue
btu_bta_msg_queue队列初始化在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之间关联队列
btu_bta_msg_queue = fixed_queue_new(SIZE_MAX);
if (btu_bta_msg_queue == NULL)
goto error_exit;
..........
}
与btu_hci_msg_queue一样,队列关联是在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);
消息发送
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方法调用fixed_queue_enqueue实现消息的入队。
bta消息一般都是btif事件产生,比如启动蓝牙EnableBluetooth,就会发送事件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;
//发送一个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 */
//获取对应的时间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的回调函数处理该事件
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
}
else
{
APPL_TRACE_WARNING("BTA got unregistered event id %d", id);
}
if (freebuf)
{ //释放内存
GKI_freebuf(p_msg);
}
}
bta_sys_event方法里面没有实际的处理消息的方法。根据消息id,查询是否存在注册该id的回调函数,存在则调用回调函数处理该消息。
回调函数在何时被注册?
函数指针的赋值在一般在各个profile初始化的时候,调用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;
}
在蓝牙启动的时候注册,即方法BTA_EnableBluetooth
bta_sys_register (BTA_ID_DM, &bta_dm_reg );
static const tBTA_SYS_REG bta_dm_reg =
{ //状态机处理消息
bta_dm_sm_execute,
bta_dm_sm_disable
};
当发送消息类型为BTA_ID_DM时,交由bta_dm_sm_execute方法处理,bta_dm_sm_execute里面会使用状态机处理各类消息。
BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),BTA_SYS_EVT_START会将数字左移8位;方法bta_sys_event首先将id右移8位,BTA_DM_API_ENABLE_EVT经过移位后是BTA_ID_DM,调用bta_dm_sm_execute处理,BTA_DM_API_ENABLE_EVT经过& 0x00ff得到bta_dm_action数组中对应的方法,即bta_dm_enable方法。
一些数据结构
tBTA_DM_SEARCH_CB 在bta层
tBTM_CB 在btm层,里面包含回调指针函数
cb含义是control block
事件传递
BTIF->BTA->BTM->BTU->HCI
获取数据后
HCI->BTU->BTM->BTA->BTIF层层上传,将数据传传递到上层。
BlueDroid入口函数bte_main.c中 bte_main_enable方法。
类
- bta_sys_main.c BTA 系统管理实现
参考
- http://blog.csdn.net/ljp1205/article/details/53869566?utm_source=itdadao&utm_medium=referral
- http://blog.csdn.net/yanli0084/article/details/51824060