android bluedroid 协议栈里面的各个组件之间的消息处理机制
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                android bluedroid 协议栈里面的各个组件之间的消息处理机制
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.                        
                                
                            
                            
                            
 
1. ?藍(lán)牙協(xié)議棧里面的各組件的通信是通過消息隊列,例如:
 
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初始化的時候,把這個隊列和相關(guān)的線程關(guān)聯(lián)起來,這樣發(fā)送完消息后,就可以通知相關(guān)的線程去隊列里面取消息并進(jìn)行處理 在文件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的消息通過調(diào)用如上的方法來發(fā)送消息,例如: HH的profile里面的添加一個虛擬的HID設(shè)備的時候, 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); } }
發(fā)送完消息到隊列后,相關(guān)聯(lián)的線程就會收到這個消息,就行處理, 在bt/stack/btu/btu_task.c中,在這個函數(shù)里面就出列,并把相關(guān)的消息就行處理,
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) // 假如調(diào)用相關(guān)的evt_hdlr成功,則free相關(guān)的buf { GKI_freebuf(p_msg); }
}
如上的(*bta_sys_cb.reg[id]->evt_hdlr)這個函數(shù)指針是在各個profile初始化的時候賦值的,
各個profile調(diào)用如下的函數(shù)來進(jìn)行注冊的,在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這個結(jié)構(gòu)體里面的bta_hh_hdl_event static?const?tBTA_SYS_REG?bta_hh_reg?= { bta_hh_hdl_event, BTA_HhDisable };
那么如上的bta_sys_event接受到HH發(fā)出的消息后就會調(diào)用bta_hh_hdl_event來解析消息并進(jìn)行處理 在文件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); }
有一部分的事件是在如上的函數(shù)bta_hh_hdl_event中處理的,而還有一部分的事件是在HH 的狀態(tài)機里面處理的, ?比如發(fā)送事件BTA_HH_API_WRITE_DEV_EVT,就是在狀態(tài)機里面處理的, 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); } }
首先要根據(jù)index?=?bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);找到index索引,然后再找到對應(yīng)的p_cb =?&bta_hh_cb.kdev[index];之后再調(diào)用狀態(tài)機進(jìn)行處理了,
** *******************************************************************************/ 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; }
最后會調(diào)用bta_hh_action這個函數(shù)數(shù)組里面的相關(guān)函數(shù),bta_hh_write_dev_act,這個函數(shù)執(zhí)行完成之后,就到
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) // 假如調(diào)用相關(guān)的evt_hdlr成功,則free相關(guān)的buf { GKI_freebuf(p_msg); }
}
=======>如上的BTA_HH_API_WRITE_DEV_EVT這個事件的調(diào)用流程如下:
1.?bta_sys_sendmsg(p_buf);先通過bta sys發(fā)送消息 2. 消息入列后調(diào)用了btu_bta_msg_ready將消息出列 3. 調(diào)用bta_sys_event(p_msg)處理消息 4. 根據(jù)不同的profile的消息會在bta sys系統(tǒng)里面尋找到相應(yīng)的事件處理器evt_hdlr,而如上的事件是HH的,那么HH在bta初始化的時候 會調(diào)用?bta_sys_register 注冊?bta_hh_reg的成員bta_hh_hdl_event作為evt_hdlr 5. ?bta_hh_hdl_event最后在狀態(tài)機里面調(diào)用了bta_hh_write_dev_act這個函數(shù),然后最后返回為true,即freebuf=true 6.?上面的調(diào)用完成后會free之前使用sendmsg申請的p_buf
 
 
 
 
 
 
 
 
 
 
=======================================================================================================
 
 
 
 
 
 
 
 
bta_hh_cb.p_cback這個結(jié)構(gòu)體成員變量的賦值是調(diào)用了如下的方法:
在文件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()方法又是如下的方法調(diào)用的,在文件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()這個方法發(fā)出的msg觸發(fā)的,
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()調(diào)用的,如下:
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函數(shù)指針?biāo)赶虻暮瘮?shù)就是bte_hh_evt,這個函數(shù)又是在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); }
之后就會調(diào)用static?void?btif_hh_upstreams_evt(UINT16?event,?char*?p_param)來通過回調(diào)(callback)上報告相關(guān)的事件,
 
 
 
 
 
 
 
 
 
 
 
 
                            
                        
                        
                        這個隊列的初始化在 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初始化的時候,把這個隊列和相關(guān)的線程關(guān)聯(lián)起來,這樣發(fā)送完消息后,就可以通知相關(guān)的線程去隊列里面取消息并進(jìn)行處理 在文件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的消息通過調(diào)用如上的方法來發(fā)送消息,例如: HH的profile里面的添加一個虛擬的HID設(shè)備的時候, 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); } }
發(fā)送完消息到隊列后,相關(guān)聯(lián)的線程就會收到這個消息,就行處理, 在bt/stack/btu/btu_task.c中,在這個函數(shù)里面就出列,并把相關(guān)的消息就行處理,
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) // 假如調(diào)用相關(guān)的evt_hdlr成功,則free相關(guān)的buf { GKI_freebuf(p_msg); }
}
如上的(*bta_sys_cb.reg[id]->evt_hdlr)這個函數(shù)指針是在各個profile初始化的時候賦值的,
各個profile調(diào)用如下的函數(shù)來進(jìn)行注冊的,在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這個結(jié)構(gòu)體里面的bta_hh_hdl_event static?const?tBTA_SYS_REG?bta_hh_reg?= { bta_hh_hdl_event, BTA_HhDisable };
那么如上的bta_sys_event接受到HH發(fā)出的消息后就會調(diào)用bta_hh_hdl_event來解析消息并進(jìn)行處理 在文件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); }
有一部分的事件是在如上的函數(shù)bta_hh_hdl_event中處理的,而還有一部分的事件是在HH 的狀態(tài)機里面處理的, ?比如發(fā)送事件BTA_HH_API_WRITE_DEV_EVT,就是在狀態(tài)機里面處理的, 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); } }
首先要根據(jù)index?=?bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);找到index索引,然后再找到對應(yīng)的p_cb =?&bta_hh_cb.kdev[index];之后再調(diào)用狀態(tài)機進(jìn)行處理了,
** *******************************************************************************/ 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; }
最后會調(diào)用bta_hh_action這個函數(shù)數(shù)組里面的相關(guān)函數(shù),bta_hh_write_dev_act,這個函數(shù)執(zhí)行完成之后,就到
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) // 假如調(diào)用相關(guān)的evt_hdlr成功,則free相關(guān)的buf { GKI_freebuf(p_msg); }
}
=======>如上的BTA_HH_API_WRITE_DEV_EVT這個事件的調(diào)用流程如下:
1.?bta_sys_sendmsg(p_buf);先通過bta sys發(fā)送消息 2. 消息入列后調(diào)用了btu_bta_msg_ready將消息出列 3. 調(diào)用bta_sys_event(p_msg)處理消息 4. 根據(jù)不同的profile的消息會在bta sys系統(tǒng)里面尋找到相應(yīng)的事件處理器evt_hdlr,而如上的事件是HH的,那么HH在bta初始化的時候 會調(diào)用?bta_sys_register 注冊?bta_hh_reg的成員bta_hh_hdl_event作為evt_hdlr 5. ?bta_hh_hdl_event最后在狀態(tài)機里面調(diào)用了bta_hh_write_dev_act這個函數(shù),然后最后返回為true,即freebuf=true 6.?上面的調(diào)用完成后會free之前使用sendmsg申請的p_buf
=======================================================================================================
bta_hh_cb.p_cback這個結(jié)構(gòu)體成員變量的賦值是調(diào)用了如下的方法:
在文件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()方法又是如下的方法調(diào)用的,在文件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()這個方法發(fā)出的msg觸發(fā)的,
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()調(diào)用的,如下:
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函數(shù)指針?biāo)赶虻暮瘮?shù)就是bte_hh_evt,這個函數(shù)又是在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); }
之后就會調(diào)用static?void?btif_hh_upstreams_evt(UINT16?event,?char*?p_param)來通過回調(diào)(callback)上報告相關(guān)的事件,
總結(jié)
以上是生活随笔為你收集整理的android bluedroid 协议栈里面的各个组件之间的消息处理机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: ASP.NET AES加密
- 下一篇: G31主板支持1440*900分辨率
