Bluedroid 函数分析:bta_dm_gattc_register

我们先来看看在bluedroid 里面有多少地方调用到这里:

可以看出除了 它自己声明的地方,有三处 调用到这个函数。

一处是 进行discovery,一处是进行search的时候,还有一次是bta_dm_sys_hw_cback 中,这个在bta_dm_enable的时候就已经注册了,所有其实最先注册的地方就是bta_dm_sys_hw_cback ,以后即使有地方调用该函数进行GATT 注册,也不会真正的再次注册。

另外 这个函数 其实是BTA_GATTC_AppRegister的包装,但是它限定了app_uuid 全部为0x87,由此我们得知此uuid  标识device manager 模块注册到gatt 中情况。

下面进行函数的分析:

/*******************************************************************************
**
** Function         bta_dm_gattc_register
**
** Description      Register with GATTC in DM if BLE is needed.
**
**
** Returns          void
**
*******************************************************************************/
static void bta_dm_gattc_register(void)
{
    tBT_UUID                app_uuid = {LEN_UUID_128,{0}};

    if (bta_dm_search_cb.client_if == BTA_GATTS_INVALID_IF)
    {
        memset (&app_uuid.uu.uuid128, 0x87, LEN_UUID_128);
        BTA_GATTC_AppRegister(&app_uuid, bta_dm_gattc_callback);//回调
    }
}

 首先组建了一个uuid 的结构,然后调用了BTA_GATTC_AppRegister 来进一步注册,继续看:

bta_dm_gattc_callback 这个函数是注册到DM 模块的回调函数,初步看一下,该函数主要处理的事件:BTA_GATTC_REG_EVT、BTA_GATTC_OPEN_EVT、BTA_GATTC_SEARCH_RES_EVT、BTA_GATTC_SEARCH_CMPL_EVT、BTA_GATTC_CLOSE_EVT。

下面我们看看bta_dm_gattc_register的具体的实现:

/*******************************************************************************
**
** Function         BTA_GATTC_AppRegister
**
** Description      This function is called to register application callbacks
**                    with BTA GATTC module.
**
** Parameters       p_app_uuid - applicaiton UUID
**                  p_client_cb - pointer to the application callback function.
**
** Returns          None
**
*******************************************************************************/
void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
{
    tBTA_GATTC_API_REG  *p_buf;

    if (bta_sys_is_register(BTA_ID_GATTC) == FALSE)
    {
        bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);//如果BTA GATTC模块没有注册到BTA,那么先注册
    }

    if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL)
    {
        p_buf->hdr.event    = BTA_GATTC_API_REG_EVT;//发送事件注册到BTA——GATTC
        if (p_app_uuid != NULL)
            memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
        p_buf->p_cback      = p_client_cb;

        bta_sys_sendmsg(p_buf);
    }
    return;
}

 我们看到是发送event BTA_GATTC_API_REG_EVT 到btu task来处理,可以预想,这个工作结束之后肯定是调用bta_dm_gattc_callback处理的event 是应该是BTA_GATTC_REG_EVT,

我们继续看看,btu  task 对这个event 的处理:

BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
{
    tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
    tBTA_GATTC_CLCB *p_clcb = NULL;
    tBTA_GATTC_RCB      *p_clreg;
    BOOLEAN             rt = TRUE;
    switch (p_msg->event)
    {
        case BTA_GATTC_API_DISABLE_EVT:
            bta_gattc_disable(p_cb);
            break;

        case BTA_GATTC_API_REG_EVT:
            bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
            break;
...

 

BTA_ID_GATTC 注册到sys 里面的注册信息, 对应的handler 就是bta_gattc_hdl_event ,我们继续看对 注册 的实质性操作:

/*******************************************************************************
**
** Function         bta_gattc_register
**
** Description      Register a GATT client application with BTA.
**
** Returns          void
**
*******************************************************************************/
void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
{
    tBTA_GATTC               cb_data;
    UINT8                    i;
    tBT_UUID                 *p_app_uuid = &p_data->api_reg.app_uuid;//拿出uuid
    tBTA_GATTC_INT_START_IF  *p_buf;
    tBTA_GATT_STATUS         status = BTA_GATT_NO_RESOURCES;

    APPL_TRACE_DEBUG("bta_gattc_register state %d",p_cb->state);//gattc 模块的状态
    memset(&cb_data, 0, sizeof(cb_data));
    cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES;
...
    /* todo need to check duplicate uuid */
    for (i = 0; i < BTA_GATTC_CL_MAX; i ++)//gattc 模块里面有32个slot可供注册
    {
        if (!p_cb->cl_rcb[i].in_use)//找一个没有被use的slot
        {
            if ((p_app_uuid == NULL) || (p_cb->cl_rcb[i].client_if = GATT_Register(p_app_uuid, &bta_gattc_cl_cback)) == 0)//注册到stack-gatt
            {
                APPL_TRACE_ERROR("Register with GATT stack failed.");
                status = BTA_GATT_ERROR;
            }
            else//注册成功,那么在BTA的模块中记录注册的相关的信息
            {
                p_cb->cl_rcb[i].in_use = TRUE;
                p_cb->cl_rcb[i].p_cback = p_data->api_reg.p_cback;//就是
                memcpy(&p_cb->cl_rcb[i].app_uuid, p_app_uuid, sizeof(tBT_UUID));//保存相应的uuid

                /* BTA use the same client interface as BTE GATT statck */
                cb_data.reg_oper.client_if = p_cb->cl_rcb[i].client_if;//client_if,该值在BTE和BTA里面的值是一样的

                if ((p_buf = (tBTA_GATTC_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTC_INT_START_IF))) != NULL)
                {
                    p_buf->hdr.event    = BTA_GATTC_INT_START_IF_EVT;//再次向btu task 发送任务
                    p_buf->client_if    = p_cb->cl_rcb[i].client_if;

                    bta_sys_sendmsg(p_buf);
                    status = BTA_GATT_OK;
                }
                else
                {
                    GATT_Deregister(p_cb->cl_rcb[i].client_if);

                    status = BTA_GATT_NO_RESOURCES;
                    memset( &p_cb->cl_rcb[i], 0 , sizeof(tBTA_GATTC_RCB));
                }
                break;
            }
        }
    }

    /* callback with register event */
    if (p_data->api_reg.p_cback)
    {
        if (p_app_uuid != NULL)
            memcpy(&(cb_data.reg_oper.app_uuid),p_app_uuid,sizeof(tBT_UUID));

        cb_data.reg_oper.status = status;
        (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT,  (tBTA_GATTC *)&cb_data);//调用回调,果然还是上报BTA_GATTC_REG_EVT 这个event
    }
}

 

 我们还是分成几个部分来分析这个问题:

  1. GATT_Register
  2. BTA_GATTC_INT_START_IF_EVT
  3. p_data->api_reg.p_cback---BTA_GATTC_REG_EVT

下面先看

GATT_Register的实现:

 这里发现 GATT_register 这个注册到BTE 模块也有一个callback 函数:bta_gattc_cl_cback ,这个回调 就是汇报状态到BTA 层面,其是一簇函数:

static tGATT_CBACK bta_gattc_cl_cback =
{
    bta_gattc_conn_cback,
    bta_gattc_cmpl_cback,
    bta_gattc_disc_res_cback,
    bta_gattc_disc_cmpl_cback,
    NULL,
    bta_gattc_enc_cmpl_cback,
    bta_gattc_cong_cback
};

 

从名字上面 大概都能看出其功能。我们看看 GATT_register:

/*******************************************************************************
**
** Function         GATT_Register
**
** Description      This function is called to register an  application
**                  with GATT
**
** Parameter        p_app_uuid128: Application UUID
**                  p_cb_info: callback functions.
**
** Returns          0 for error, otherwise the index of the client registered with GATT
**
*******************************************************************************/
tGATT_IF GATT_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info)
{
    tGATT_REG    *p_reg;
    UINT8        i_gatt_if=0;
    tGATT_IF     gatt_if=0;

    gatt_dbg_display_uuid(*p_app_uuid128);

    for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++)//注册到BTE GATT的大本营是gatt_cb
    {
        if (p_reg->in_use  && !memcmp(p_app_uuid128->uu.uuid128, p_reg->app_uuid128.uu.uuid128, LEN_UUID_128))
        {
            GATT_TRACE_ERROR("application already registered.");
            return 0;
        }
    }

    for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++)
    {
        if (!p_reg->in_use)
        {
            memset(p_reg, 0 , sizeof(tGATT_REG));
            i_gatt_if++;              /* one based number  从开始计数*/
            p_reg->app_uuid128 =  *p_app_uuid128;
            gatt_if            =
            p_reg->gatt_if     = (tGATT_IF)i_gatt_if;//发现这个gatt_if就是reg结构在gatt_cb中index+1
            p_reg->app_cb      = *p_cb_info;//回调的函数簇 保存在reg结构里面
            p_reg->in_use      = TRUE;

            break;
        }
    }
    return gatt_if;
}

 

这个函数很简单,正如注释描述:“This function is called to register an application with GATT”

之前比较困惑的gatt_if,其实就是注册的结构体在gatt_cb 里面的index+1,那这个gatt_if 和保存在bta_gattc_cb中注册信息的index 有什么关系?没有关系。bta_gattc_cb.cl_rcb[index_bta].client_if = gatt_if

下面分析一下第三点:

p_data->api_reg.p_cback---BTA_GATTC_REG_EVT

 

/*******************************************************************************
**
** Function         bta_dm_gattc_callback
**
** Description      This is GATT client callback function used in DM.
**
** Parameters:
**
*******************************************************************************/
static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
{
    switch (event)
    {
        case BTA_GATTC_REG_EVT:
            if (p_data->reg_oper.status == BTA_GATT_OK)
                bta_dm_search_cb.client_if = p_data->reg_oper.client_if;//保存gatt_if在bta_dm_search_cb结构中
            else
                bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF;
            break;

 

该回调非常的简单,就是上报了gatt_if 给bta_dm_search_cb结构。其实到这里可以说 注册的流程已经走完了。

下面看 

BTA_GATTC_INT_START_IF_EVT的处理

 

BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
{
...
        case BTA_GATTC_INT_START_IF_EVT:
            bta_gattc_start_if(p_cb, (tBTA_GATTC_DATA *) p_msg);
            break;
...

 

程序走到当前的状态,其实 是已经配对完成了,在做GATT相关的处理,

/*******************************************************************************
**
** Function         bta_gattc_start_if
**
** Description      start an application interface.
**
** Returns          none.
**
*******************************************************************************/
void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
{
    UNUSED(p_cb);

    if (bta_gattc_cl_get_regcb(p_msg->int_start_if.client_if) !=NULL )//找到bta 层的reg,这里的client_if不是reg的index,是根据client_if的匹配来查找的
    {
        GATT_StartIf(p_msg->int_start_if.client_if);
    }
    else
    {
        APPL_TRACE_ERROR("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if );
    }
}

 

/*******************************************************************************
**
** Function         GATT_StartIf
**
** Description      This function is called after registration to start receiving
**                  callbacks for registered interface.  Function may call back
**                  with connection status and queued notifications
**
** Parameter        gatt_if: applicaiton interface.
**
** Returns          None.
**
*******************************************************************************/
void GATT_StartIf (tGATT_IF gatt_if)
{
    tGATT_REG   *p_reg;
    tGATT_TCB   *p_tcb;
    BD_ADDR     bda;
    UINT8       start_idx, found_idx;
    UINT16      conn_id;
    tGATT_TRANSPORT transport ;

    if ((p_reg = gatt_get_regcb(gatt_if)) != NULL)
    {
        start_idx = 0;
        while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport))//查找已经连的设备
        {
            p_tcb = gatt_find_tcb_by_addr(bda, transport);
            if (p_reg->app_cb.p_conn_cb && p_tcb)
            {
                conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);//tcb_idx是tcb 在gatt_cb里面的index
                (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0, transport);//回调
            }
            start_idx = ++found_idx;//继续查找
        }
    }
}

 

目前还不清楚conn_id 有什么作用,先分析其构成:

#define GATT_CREATE_CONN_ID(tcb_idx, gatt_if)  ((UINT16) ((((UINT8)(tcb_idx) ) << 8) | ((UINT8) (gatt_if))))

 

tcb的index 是高八位,gatt_if是第八位

如果是刚刚注册的case,那么这里应是不会查找到已经连的设备.

关于gatt registeration的分析 就先到这里.

 

posted @ 2018-07-25 11:03  雪山飞燕  阅读(1545)  评论(0编辑  收藏  举报