Bluedroid 函数分析:bta_dm_gattc_register

时间:2024-05-13 00:07:49

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

Bluedroid 函数分析:bta_dm_gattc_register

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

一处是 进行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,{}}; 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, , sizeof(cb_data));
cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES;
...
/* todo need to check duplicate uuid */
for (i = ; 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)) == )//注册到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], , 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=;
tGATT_IF gatt_if=; gatt_dbg_display_uuid(*p_app_uuid128); for (i_gatt_if = , 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 ;
}
} for (i_gatt_if = , 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, , 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 = ;
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, , 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的分析 就先到这里.