概述
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);
}
}
它会注册一个
evt_hdlr,那就是
bta_hh_reg这个结构体里面的bta_hh_hdl_event
static const tBTA_SYS_REG bta_hh_reg =
{
bta_hh_hdl_event,
BTA_HhDisable
};
那么如上的bta_sys_event接受到HH发出的消息后就会调用bta_hh_hdl_event来
解析消息并进行处理
在文件bt/bta/hh/bta_hh_main.c中,
BOOLEAN
bta_hh_hdl_event(BT_HDR *p_msg)
{
UINT8 index = BTA_HH_IDX_INVALID;
tBTA_HH_DEV_CB *p_cb = NULL;
switch (p_msg->event)
{
case BTA_HH_API_ENABLE_EVT:
bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
break;
case BTA_HH_API_DISABLE_EVT:
bta_hh_api_disable();
break;
case BTA_HH_DISC_CMPL_EVT: /* disable complete */
bta_hh_disc_cmpl();
break;
default:
/* all events processed in state machine need to find corresponding
CB before proceed */
if (p_msg->event == BTA_HH_API_OPEN_EVT)
{
index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
}
else if (p_msg->event ==
BTA_HH_API_MAINT_DEV_EVT)
{
/* if add device */
if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event ==
BTA_HH_ADD_DEV_EVT)
{
index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
}
else /* else remove device by handle */
{
index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
// btla-specific ++
/* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
* then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
* cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
* So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
* force the index to be IDX_INVALID
*/
if ((index != BTA_HH_IDX_INVALID) &&
(bta_hh_cb.kdev[index].in_use == FALSE)) {
index = BTA_HH_IDX_INVALID;
}
// btla-specific --
}
}
else if (p_msg->event == BTA_HH_INT_OPEN_EVT)
{
index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
}
else
index =
bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
if (index != BTA_HH_IDX_INVALID)
p_cb = &bta_hh_cb.kdev[index];
#if BTA_HH_DEBUG
APPL_TRACE_DEBUG("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
#endif
bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
}
return (TRUE);
}
有一部分的事件是在如上的函数
bta_hh_hdl_event中处理的,而还有一部分的事件是在HH 的状态机里面处理的,
比如发送事件BTA_HH_API_WRITE_DEV_EVT,就是在状态机里面处理的,
static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
UINT16 data, UINT8 rpt_id, BT_HDR *p_data)
{
tBTA_HH_CMD_DATA *p_buf;
UINT16 len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );
if ((
p_buf = (tBTA_HH_CMD_DATA *)
GKI_getbuf(len))!= NULL)
{
memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));
p_buf->hdr.event =
BTA_HH_API_WRITE_DEV_EVT;
p_buf->hdr.layer_specific = (UINT16) dev_handle;
p_buf->t_type = t_type;
p_buf->data = data;
p_buf->param = param;
p_buf->p_data = p_data;
p_buf->rpt_id = rpt_id;
bta_sys_sendmsg(
p_buf);
}
}
首先要根据
index =
bta_hh_dev_handle_to_cb_idx
((UINT8)p_msg->layer_specific);找到index索引,然后再找到对应的p_cb = &bta_hh_cb.kdev[index];之后再调用状态机进行处理了,
**
*******************************************************************************/
void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16
event, tBTA_HH_DATA * p_data)
{
tBTA_HH_ST_TBL state_table;
UINT8 action;
tBTA_HH cback_data;
tBTA_HH_EVT cback_event = 0;
#if BTA_HH_DEBUG == TRUE
tBTA_HH_STATE in_state ;
UINT16 debug_event = event;
#endif
memset(&cback_data, 0, sizeof(tBTA_HH));
/* handle exception, no valid control block was found */
if (!p_cb)
{
/* BTA HH enabled already? otherwise ignore the event although it's bad*/
if (bta_hh_cb.p_cback != NULL)
{
switch (event)
{
/* no control block available for new connection */
case BTA_HH_API_OPEN_EVT:
cback_event = BTA_HH_OPEN_EVT;
/* build cback data */
bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
cback_data.conn.status = BTA_HH_ERR_DB_FULL;
cback_data.conn.handle = BTA_HH_INVALID_HANDLE;
break;
/* DB full, BTA_HhAddDev */
case BTA_HH_API_MAINT_DEV_EVT:
cback_event = p_data->api_maintdev.sub_event;
if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT)
{
bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
cback_data.dev_info.status = BTA_HH_ERR_DB_FULL;
cback_data.dev_info.handle = BTA_HH_INVALID_HANDLE;
}
else
{
cback_data.dev_info.status = BTA_HH_ERR_HDL;
cback_data.dev_info.handle = (UINT8)p_data->api_maintdev.hdr.layer_specific;
}
break;
case BTA_HH_API_WRITE_DEV_EVT:
cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
BTA_HH_FST_TRANS_CB_EVT;
if (p_data->api_sndcmd.p_data != NULL)
{
GKI_freebuf(p_data->api_sndcmd.p_data);
}
if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE)
{
cback_data.dev_status.status = BTA_HH_ERR_HDL;
cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
}
else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
{
cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
cback_data.hs_data.status = BTA_HH_ERR_HDL;
/* hs_data.rsp_data will be all zero, which is not valid value */
}
else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
{
cback_data.status = BTA_HH_ERR_HDL;
cback_event = BTA_HH_VC_UNPLUG_EVT;
}
else
cback_event = 0;
break;
case BTA_HH_API_CLOSE_EVT:
cback_event = BTA_HH_CLOSE_EVT;
cback_data.dev_status.status = BTA_HH_ERR_HDL;
cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
break;
default:
/* invalid handle, call bad API event */
APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific);
/* Free the callback buffer now */
if (p_data != NULL && p_data->hid_cback.p_data != NULL)
{
GKI_freebuf(p_data->hid_cback.p_data);
p_data->hid_cback.p_data = NULL;
}
break;
}
if (cback_event)
(*
bta_hh_cb.p_cback)(cback_event, &cback_data);
}
}
/* corresponding CB is found, go to state machine */
else
{
#if BTA_HH_DEBUG == TRUE
in_state = p_cb->state;
APPL_TRACE_EVENT("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
in_state, bta_hh_state_code(in_state),
bta_hh_evt_code(debug_event));
#endif
if ((p_cb->state == BTA_HH_NULL_ST) || (p_cb->state >= BTA_HH_INVALID_ST))
{
APPL_TRACE_ERROR("bta_hh_sm_execute: Invalid state State = 0x%x, Event = %d",
p_cb->state,event);
return;
}
state_table =
bta_hh_st_tbl[p_cb->state - 1];
event &= 0xff;
p_cb->state =
state_table[
event][BTA_HH_NEXT_STATE] ;
if ((
action = state_table[
event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
{
(*
bta_hh_action[action])(p_cb, p_data);
}
#if BTA_HH_DEBUG == TRUE
if (in_state != p_cb->state)
{
APPL_TRACE_DEBUG("HH State Change: [%s] -> [%s] after Event [%s]",
bta_hh_state_code(in_state),
bta_hh_state_code(p_cb->state),
bta_hh_evt_code(debug_event));
}
#endif
}
return;
return;
}
最后会调用bta_hh_action这个函数数组里面的相关函数,
bta_hh_write_dev_act,这个函数执行完成之后,就到
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_HH_API_WRITE_DEV_EVT这个事件的调用流程如下:
1. bta_sys_sendmsg(p_buf);先通过bta sys发送消息
2. 消息入列后调用了btu_bta_msg_ready将消息出列
3. 调用bta_sys_event(p_msg)处理消息
4. 根据不同的profile的消息会在bta sys系统里面寻找到相应的事件处理器evt_hdlr,而如上的事件是HH的,那么HH在bta初始化的时候
会调用 bta_sys_register 注册 bta_hh_reg的成员bta_hh_hdl_event作为evt_hdlr
5.
bta_hh_hdl_event
最后在状态机里面调用了
bta_hh_write_dev_act这个函数,
然后最后返回为
true
,即
freebuf=true
6.
上面的调用完成后会
free之前
使用
sendmsg
申请的p_buf
=======================================================================================================
bta_hh_cb.p_cback这个结构体成员变量的赋值是调用了如下的方法:
在文件bta_hh_act.c中,
void bta_hh_api_enable(tBTA_HH_DATA *
p_data)
{
tBTA_HH_STATUS status = BTA_HH_ERR;
UINT8 xx;
/* initialize BTE HID */
HID_HostInit();
memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);
/* Register with L2CAP */
if ( HID_HostRegister (bta_hh_cback) == HID_SUCCESS)
{
/* store parameters */
bta_hh_cb.p_cback =
p_data->api_enable.p_cback;
status = BTA_HH_OK;
/* initialize device CB */
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
{
bta_hh_cb.kdev[xx].state = BTA_HH_IDLE_ST;
bta_hh_cb.kdev[xx].hid_handle = BTA_HH_INVALID_HANDLE;
bta_hh_cb.kdev[xx].index = xx;
}
/* initialize control block map */
for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
bta_hh_cb.cb_index[xx] = BTA_HH_IDX_INVALID;
}
#if (BTA_HH_LE_INCLUDED == TRUE)
if (status == BTA_HH_OK)
{
bta_hh_le_enable();
}
else
#endif
/* signal BTA call back event */
(* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
}
那bta_hh_api_enable()方法又是如下的方法调用的,在文件bta_hh_main.c中,
BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
{
UINT8 index = BTA_HH_IDX_INVALID;
tBTA_HH_DEV_CB *p_cb = NULL;
switch (p_msg->event)
{
case
BTA_HH_API_ENABLE_EVT:
bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
break;
那上面的case又是
BTA_HhEnable()这个方法
发出的
msg触发的,
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);
}
}
上面的BTA_HhEnable的方法又是btif/src/btif_hh.c里面的方法
btif_hh_execute_service()调用的,如下:
bt_status_t btif_hh_execute_service(BOOLEAN b_enable)
{
if (b_enable)
{
/* Enable and register with BTA-HH */
BTA_HhEnable(BTUI_HH_SECURITY,
bte_hh_evt);
}
else {
/* Disable HH */
BTA_HhDisable();
}
return BT_STATUS_SUCCESS;
}
那么可以看出那个
bta_hh_cb.p_cback函数指针所指向的函数就是bte_hh_evt,这个函数又是在btif/src/btif_hh.c里面的定义的,
static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data)
{
bt_status_t status;
int param_len = 0;
if (BTA_HH_ENABLE_EVT == event)
param_len = sizeof(tBTA_HH_STATUS);
else if (BTA_HH_OPEN_EVT == event)
param_len = sizeof(tBTA_HH_CONN);
else if (BTA_HH_DISABLE_EVT == event)
param_len = sizeof(tBTA_HH_STATUS);
else if (BTA_HH_CLOSE_EVT == event)
param_len = sizeof(tBTA_HH_CBDATA);
else if (BTA_HH_GET_DSCP_EVT == event)
param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event)|| (BTA_HH_GET_IDLE_EVT == event))
param_len = sizeof(tBTA_HH_HSDATA);
else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) || (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
param_len = sizeof(tBTA_HH_CBDATA);
else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event) )
param_len = sizeof(tBTA_HH_DEV_INFO);
else if (BTA_HH_API_ERR_EVT == event)
param_len = 0;
/* switch context to btif task context (copy full union size for convenience) */
status = btif_transfer_context(
btif_hh_upstreams_evt, (uint16_t)event, (void*)p_data, param_len, NULL);
/* catch any failed context transfers */
ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}
之后就会调用
static void btif_hh_upstreams_evt(UINT16 event, char* p_param)来通过回调(callback)上报告相关的事件,
最后
以上就是爱笑花生为你收集整理的android bluedroid 协议栈里面的各个组件之间的消息处理机制的全部内容,希望文章能够帮你解决android bluedroid 协议栈里面的各个组件之间的消息处理机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复