zoukankan      html  css  js  c++  java
  • 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的分析 就先到这里.

  • 相关阅读:
    如何自动生成图片用于测试 pytorch(No image? No need image)
    深度学习中Dropout原理解析
    关于深度学习中的batch_size
    每日一问
    flask中使用ajax 处理前端请求,每隔一段时间请求不通的接口,结果展示同一页面
    flask中使用ajax 处理前端请求,每隔一段时间请求一次
    flask中使用ajax 处理前端请求,结果展示在同一页面,不点击页面不展示
    appium 使用name 定位报错 Locator Strategy 'name' is not supported for this session
    robot framework 中一条用例执行失败,终止其他用例执行
    python 实现定时任务
  • 原文地址:https://www.cnblogs.com/libs-liu/p/9346883.html
Copyright © 2011-2022 走看看