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 } }
我们还是分成几个部分来分析这个问题:
- GATT_Register
- BTA_GATTC_INT_START_IF_EVT
- 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的分析 就先到这里.