1. 蓝牙协议栈里面的各组件的通信是通过消息队列,例如:
btu_task 和bta直接就是通过队列bt/stack/btu/btu_task.c
// Communication queue between btu_task and bta.
extern fixed_queue_t *
btu_bta_msg_queue;
这个队列的初始化在
bt/stack/btu/btu_init.c
void BTU_StartUp(void)
{
memset (&btu_cb, 0, sizeof (tBTU_CB));
btu_cb.trace_level = HCI_INITIAL_TRACE_LEVEL;
btu_bta_msg_queue =
fixed_queue_new(SIZE_MAX);
if (btu_bta_msg_queue == NULL)
goto error_exit;
之后需要在btu初始化的时候,把这个队列和相关的线程关联起来,这样发送完消息后,就可以通知相关的线程去队列里面取消息并进行处理
在文件bt/stack/btu/btu_task.c,
void btu_task_start_up(UNUSED_ATTR void *context) {
..................
fixed_queue_register_dequeue(btu_bta_msg_queue,
thread_get_reactor(bt_workqueue_thread),
btu_bta_msg_ready,
NULL);
然后在各个profile使用的话就是通过入列的方式
在bt/bta/sys/bta_sys_main.c中,
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);
}
一般一些profile的消息通过调用如上的方法来发送消息,例如:
HH的profile里面的添加一个虚拟的HID设备的时候,
void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
{
tBTA_HH_MAINT_DEV *p_buf;
UINT16 len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;
p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf(len);
if (p_buf != NULL)
{
memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
p_buf->hdr.event =
BTA_HH_API_MAINT_DEV_EVT;
p_buf->sub_event =
BTA_HH_ADD_DEV_EVT;
p_buf->hdr.layer_specific = BTA_HH_INVALID_HANDLE;
p_buf->attr_mask = (UINT16) attr_mask;
p_buf->sub_class = sub_class;
p_buf->app_id = app_id;
bdcpy(p_buf->bda, bda);
memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list)
{
p_buf->dscp_info.descriptor.dl_len = dscp_info.descriptor.dl_len;
p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
}
else
{
p_buf->dscp_info.descriptor.dsc_list = NULL;
p_buf->dscp_info.descriptor.dl_len = 0;
}
bta_sys_sendmsg(p_buf);
}
}
发送完消息到队列后,相关联的线程就会收到这个消息,就行处理,
在bt/stack/btu/btu_task.c中,在这个函数里面就出列,并把相关的消息就行处理,
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);
}
在bt/bta/sys/bta_sys_main.c中,
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 = (UINT8) (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("BTA got unregistered event id %d", id);
}
if (
freebuf) // 假如调用相关的evt_hdlr成功,则free相关的buf
{
GKI_freebuf(p_msg);
}
}
如上的
(*
bta_sys_cb
.
reg
[id]->
evt_hdlr
)这个函数指针是在各个profile初始化的时候赋值的,
各个profile调用如下的函数来进行注册的,在bt/bta/sys/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;
}
比如HH的,在bt/bta/hh/bta_hh_api.c中,
void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
{
tBTA_HH_API_ENABLE *p_buf;
/* register with BTA system manager */
bta_sys_register(BTA_ID_HH, &
bta_hh_reg);
LOG_INFO("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback);
p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));
if (p_buf != NULL)
{
memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
p_buf->p_cback = p_cback;
p_buf->sec_mask = sec_mask;
bta_sys_sendmsg(p_buf);
}
}
它会注册一个