bluedroid中的start discovery代码流程

来源:互联网 发布:破解zip解压密码软件 编辑:程序博客网 时间:2024/06/03 14:28

    之前看到某位大神的博客android -- 蓝牙 bluetooth (三)搜索蓝牙,介绍了Android中蓝牙的搜索过程,从framework到service,再到JNI、bluetooth stack,大致的流程讲得很清楚。这里我了解了一下Android4.4中bluetooth stack中的代码流程,总结如下。

    在JNI层中调用startDiscoveryNative函数,最终指向stack层bluetoothInterface(bluetooth.c)结构的成员函数start_discovery,这便是stack层的入口。在btif_dm_start_discovery(btif_dm.c)函数中设置了discovery的相关参数,并调用BTA_DmSearch(&inq_params, services, bte_search_devices_evt)来执行。这个函数的内容如下:

void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback){    tBTA_DM_API_SEARCH    *p_msg;    if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL)    {        memset(p_msg, 0, sizeof(tBTA_DM_API_SEARCH));        p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;        memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));        p_msg->services = services;        p_msg->p_cback = p_cback;        p_msg->rs_res  = BTA_DM_RS_NONE;        bta_sys_sendmsg(p_msg);    }}
可以看到,该函数构造了一个消息p_msg,设置了事件类型以及回调函数。在这里,回调函数即前面的bte_search_devices_evt,它处理搜索的结果,并最终通过JNI提供的callback返回给上层。这个消息被发送到btu_task,由bta模块处理,代码如下:

BTA_API void bta_sys_event(BT_HDR *p_msg){    UINT8       id;    BOOLEAN     freebuf = TRUE;    APPL_TRACE_EVENT1("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_WARNING1("BTA got unregistered event id %d", id);    }    if (freebuf)    {        GKI_freebuf(p_msg);    }}
其内容很简单,就是暗中event的id来调相应的函数来处理。对于search过程来说,他的处理函数早在蓝牙初始化中调用函数BTA_EnableBluetooth中注册:

bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
从而,代码转入bta_dm_search_reg的成员函数bta_dm_search_sm_execute。它的实现跟上面的bta_sys_event很类似,根据不同的state来调用相应状态下的函数。代码如下:

BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg){    tBTA_DM_ST_TBL      state_table;    UINT8               action;    int                 i;    APPL_TRACE_EVENT2("bta_dm_search_sm_execute state:%d, event:0x%x",        bta_dm_search_cb.state, p_msg->event);    /* look up the state table for the current state */    state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];    bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];    /* execute action functions */    for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)    {        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)        {            (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);        }        else        {            break;        }    }    return TRUE;}
刚进入这个函数时,由于bta_dm_search_cb.state为0,故state_table为bta_dm_search_idle_st_table;由于前面在BTA_DmSearch中设置的event为BTA_DM_API_SEARCH_EVT(0x0200),从而第一个真正的执行函数为bta_dm_search_start。它的关键部分如下:

void bta_dm_search_start (tBTA_DM_MSG *p_data){    ......    /* save search params */    bta_dm_search_cb.p_search_cback = p_data->search.p_cback;    bta_dm_search_cb.services = p_data->search.services;    ......    result.status = BTM_StartInquiry(   (tBTM_INQ_PARMS*)&p_data->search.inq_params,                        bta_dm_inq_results_cb,                        (tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);    ......}
在第一部分,它注册了search的回调函数给全局变量bta_dm_search_cb的成员;同时,它在第二部分调用BTM_StartInquiry去执行inquiry(扯了这么多其实还没到真正发HCI command的地方)。同样的,将函数BTM_StartInquiry的关键部分贴在下面:

*******************************************************************************/tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,                              tBTM_CMPL_CB *p_cmpl_cb){    tBTM_STATUS  status = BTM_CMD_STARTED;    tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;    ......    /* Initialize the inquiry variables */    p_inq->state = BTM_INQ_ACTIVE_STATE;    p_inq->p_inq_cmpl_cb = p_cmpl_cb;    p_inq->p_inq_results_cb = p_results_cb;    p_inq->inq_cmpl_info.num_resp = 0;         /* Clear the results counter */    p_inq->inq_active = p_inqparms->mode;       ......}
很简单,它再次设置了bta_dm_search_cb的一些成员,最重要的即扫描结果的回调函数p_results_cb(即bta_dm_inq_results_cb)和扫描完成(超时或者收到results的数目超过设定)的处理函数p_cmpl_cb(即bta_dm_inq_cmpl_cb)。这样,在收到inquiry的results后便有相应的处理函数。在设置完这些参数后,函数后半段便要开始执行扫描了,最终通过btu_hcif_send_cmd将BR\EDR或者LE扫描的HCI指令发送给controller。同时,它还会对上层进行通知,告知执行已经执行,现在的状态是discovery_started。而当收到扫描的report时,调用callback函数上报device_found。只有当用于通过UI选择与某一个设备进行配对时,才会进入后面的配对鉴权、加密等过程,这些留待以后慢慢学习。









0 0
原创粉丝点击