GATT服务搜索流程(二)
关于bta_dm_cb.p_sec_cback,这里我们之前已经分析过,他就是bte_dm_evt ,最终调用的函数btif_dm_upstreams_evt :
static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
{
tBTA_DM_SEC *p_data = (tBTA_DM_SEC*)p_param;
tBTA_SERVICE_MASK service_mask;
uint32_t i;
bt_bdaddr_t bd_addr;
...
case BTA_DM_BLE_AUTH_CMPL_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_AUTH_CMPL_EVT. ");
btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
break;
...
}
继续看:
/*******************************************************************************
**
** Function btif_dm_ble_auth_cmpl_evt
**
** Description Executes authentication complete event in btif context
**
** Returns void
**
*******************************************************************************/
static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
{
/* Save link key, if not temporary */
bt_bdaddr_t bd_addr;
bt_status_t status = BT_STATUS_FAIL;
bt_bond_state_t state = BT_BOND_STATE_NONE; bdcpy(bd_addr.address, p_auth_cmpl->bd_addr);
if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) )
{
/* store keys */
}
if (p_auth_cmpl->success)
{
status = BT_STATUS_SUCCESS;
state = BT_BOND_STATE_BONDED;
int addr_type;
bt_bdaddr_t bdaddr;
bdcpy(bdaddr.address, p_auth_cmpl->bd_addr);
if (btif_storage_get_remote_addr_type(&bdaddr, &addr_type) != BT_STATUS_SUCCESS)
btif_storage_set_remote_addr_type(&bdaddr, p_auth_cmpl->addr_type); /* Test for temporary bonding */
if (btm_get_bond_type_dev(p_auth_cmpl->bd_addr) == BOND_TYPE_TEMPORARY) {
...
} else {
btif_dm_save_ble_bonding_keys();//保存key 到config
BTA_GATTC_Refresh(bd_addr.address);//refresh
btif_dm_get_remote_services_by_transport(&bd_addr, BTA_GATT_TRANSPORT_LE);//继续获取服务
}
else
{
...
}
bond_state_changed(status, &bd_addr, state);//上报状态
}
btif_dm_save_ble_bonding_keys 很简单,就是保存SMP相关的key 到config文件,bond_state_changed也很简单,就是 上报状态,下面着重看看BTA_GATTC_Refresh和btif_dm_get_remote_services_by_transport
首先看看BTA_GATTC_Refresh:简单的地方会一带而过:
/*******************************************************************************
**
** Function BTA_GATTC_Refresh
**
** Description Refresh the server cache of the remote device
**
** Parameters remote_bda: remote device BD address.
**
** Returns void
**
*******************************************************************************/
void BTA_GATTC_Refresh(BD_ADDR remote_bda)
{
tBTA_GATTC_API_OPEN *p_buf; if ((p_buf = (tBTA_GATTC_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_OPEN))) != NULL)
{
p_buf->hdr.event = BTA_GATTC_API_REFRESH_EVT;//发送事件 memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN); bta_sys_sendmsg(p_buf);
}
return;
}
处理这个事件的函数是: bta_gattc_process_api_refresh:
/*******************************************************************************
**
** Function bta_gattc_process_api_refresh
**
** Description process refresh API to delete cache and start a new discovery
** if currently connected.
**
** Returns None.
**
*******************************************************************************/
void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
{
tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_conn.remote_bda);//查找cache
tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
BOOLEAN found = FALSE;
UINT8 i;
UNUSED(p_cb); if (p_srvc_cb != NULL)//找到cache
{
/* try to find a CLCB */
if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0)
{
for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
{
if (p_clcb->in_use && p_clcb->p_srcb == p_srvc_cb)
{
found = TRUE;//找到对应的clcb
break;
}
}
if (found)
{
bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);//继续搜索
return;
}
}
/* in all other cases, mark it and delete the cache */
if (p_srvc_cb->p_srvc_cache != NULL)//没有找到对应clcb,那么这个cache也没有存在的价值了,直接删除
{
while (!GKI_queue_is_empty(&p_srvc_cb->cache_buffer))
GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer)); p_srvc_cb->p_srvc_cache = NULL;
}
}
/* used to reset cache in application */
bta_gattc_co_cache_reset(p_msg->api_conn.remote_bda);//删除/data/misc/bluedroid/gatt_cache_* 文件 }
这个函数的作用:
- 如果找到cache,并且找到clcb,那么继续进行服务搜索,
- 否则删除cache,包括data/misc/bluedroid/下面的文件,重新开始。
我们这里只分析第一次配对之后的服务搜索。
下面继续看btif_dm_get_remote_services_by_transport :
/*******************************************************************************
**
** Function btif_dm_get_remote_services_transport
**
** Description Start SDP to get remote services by transport
**
** Returns bt_status_t
**
*******************************************************************************/
bt_status_t btif_dm_get_remote_services_by_transport(bt_bdaddr_t *remote_addr, const int transport)
{
/* Set the mask extension */
tBTA_SERVICE_MASK_EXT mask_ext;
mask_ext.num_uuid = 0;//搜索全部服务
mask_ext.p_uuid = NULL;
mask_ext.srvc_mask = BTA_ALL_SERVICE_MASK; BTA_DmDiscoverByTransport(remote_addr->address, &mask_ext,
bte_dm_search_services_evt, TRUE, transport);
//bte_dm_search_services_evt回调函数
return BT_STATUS_SUCCESS;
}
看看BTA_DmDiscoverByTransport:
/*******************************************************************************
**
** Function BTA_DmDiscoverByTransport
**
** Description This function does service discovery on particular transport
** for services of a
** peer device. When services.num_uuid is 0, it indicates all
** GATT based services are to be searched; otherwise a list of
** UUID of interested services should be provided through
** p_services->p_uuid.
**
**
**
** Returns void
**
*******************************************************************************/
void BTA_DmDiscoverByTransport(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
tBTA_TRANSPORT transport)
{
#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
bta_dm_discover_send_msg(bd_addr, p_services, p_cback, sdp_search, transport);
#endif
}
继续往下看:
/*******************************************************************************
**
** Function bta_dm_discover_send_msg
**
** Description This function send discover message to BTA task.
**
** Returns void
**
*******************************************************************************/
#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
static void bta_dm_discover_send_msg(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search,
tBTA_TRANSPORT transport)
{
tBTA_DM_API_DISCOVER *p_msg;
UINT16 len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) +
sizeof(tBT_UUID) * p_services->num_uuid) :
sizeof(tBTA_DM_API_DISCOVER); if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(len)) != NULL)
{
memset(p_msg, 0, len); p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;//发送该事件
bdcpy(p_msg->bd_addr, bd_addr);
p_msg->p_cback = p_cback;
p_msg->sdp_search = sdp_search;
p_msg->transport = transport;
这里发现他发送了事件到BTA task进行搜索的流程:函数功能正如注释“This function send discover message to BTA task.”
最终BTA执行的函数是:
/*******************************************************************************
**
** Function bta_dm_discover
**
** Description Discovers services on a remote device
**
**
** Returns void
**
*******************************************************************************/
void bta_dm_discover (tBTA_DM_MSG *p_data)
{
#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->discover.num_uuid);
#endif
/* save the search condition */
bta_dm_search_cb.services = p_data->discover.services; #if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
bta_dm_gattc_register();
utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
if ((bta_dm_search_cb.num_uuid = p_data->discover.num_uuid) != &&
p_data->discover.p_uuid != NULL)
{
if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
{
p_data->discover.p_cback(BTA_DM_DISC_CMPL_EVT, NULL);
return;
}
memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->discover.p_uuid, len);
}
bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
#endif bta_dm_search_cb.p_search_cback = p_data->discover.p_cback;
bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;//mask
bta_dm_search_cb.service_index = ;
bta_dm_search_cb.services_found = ;
bta_dm_search_cb.peer_name[] = ;
bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
bta_dm_search_cb.p_btm_inq_info = BTM_InqDbRead (p_data->discover.bd_addr);
bta_dm_search_cb.transport = p_data->discover.transport; bta_dm_search_cb.name_discover_done = FALSE;
memcpy(&bta_dm_search_cb.uuid, &p_data->discover.uuid, sizeof(tSDP_UUID));
bta_dm_discover_device(p_data->discover.bd_addr);//action
}
这里注意bta_dm_search_cb.p_search_cback = p_data->discover.p_cback = bte_dm_search_services_evt,后期搜索到结果的相关的处理,肯定会调用到这个回调函数。这里要非常注意的是当进行服务搜索的时候bta_dm_search_cb.p_search_cback = bte_dm_search_services_evt,当进行设备搜索的时候bta_dm_search_cb.p_search_cback = bte_search_devices_evt,注意不要搞混。
bta_dm_discover 主要做了三件事:
- bta_dm_gattc_register ,这里其实在蓝牙enable的时候就已经注册好了,关于该函数分析:bta_dm_gattc_register
- 组建bta_dm_search_cb 结构
- bta_dm_discover_device
下面分别来分析:
下面来看一下bta_dm_discover_device :
这是一个 服务发现的总的函数接口,涉及 到BREDR 以及BLE 的部分,我们这里只关注BLE的情况:
if (transport == BT_TRANSPORT_LE)
{
if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK)
{
//set the raw data buffer here
memset(g_disc_raw_data_buf, , sizeof(g_disc_raw_data_buf));
bta_dm_search_cb.p_ble_rawdata = g_disc_raw_data_buf; bta_dm_search_cb.ble_raw_size = MAX_DISC_RAW_DATA_BUF;
bta_dm_search_cb.ble_raw_used = ; /* start GATT for service discovery */
btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr);//进行GATT 搜索
return;
}
}
继续看btm_dm_start_gatt_discovery:
/*******************************************************************************
**
** Function btm_dm_start_gatt_discovery
**
** Description This is GATT initiate the service search by open a GATT connection
** first.
**
** Parameters:
**
*******************************************************************************/
void btm_dm_start_gatt_discovery (BD_ADDR bd_addr)
{
bta_dm_search_cb.gatt_disc_active = TRUE; /* connection is already open */
if (bdcmp(bta_dm_search_cb.pending_close_bda, bd_addr) == &&
bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
{
memset(bta_dm_search_cb.pending_close_bda, , BD_ADDR_LEN);
bta_sys_stop_timer(&bta_dm_search_cb.gatt_close_timer);
btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id);//如果已经打开,那么直接进行搜索
}
else
BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE, BTA_GATT_TRANSPORT_LE);//打开GATT 通道
}
这是一个服务搜索的函数,但是当 GATT 通道没有打开的时候,我们只要调用 BTA_GATTC_Open就可以了,那说明这个函数在打开GATT通道之后会自动进行搜索。
那这里关于BTA_GATTC_Open的流程分析,请参考:这里
GATT服务搜索流程(二)的更多相关文章
- GATT服务搜索流程(一)
GATT的规范阅读起来还是比较简答, 但是这样的规范在代码上是如何实现的呢?下面就分析一下bluedroid 协议栈关于GATT的代码流程. BLE的设备都是在SMP之后进行ATT的流程的交互.从代码 ...
- SDP服务搜索流程源码分析
BREDR的设备 在进行配对完成之后,进行;连接之前都要进行服务的搜索,服务搜索走的流程是SDP,这篇文章就分析一下,bluedroid中SDP的代码流程,我们从配对完成的回调函数开始分析: /*** ...
- 【Android Developers Training】 77. 使用Wi-Fi P2P进行服务搜索
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【微服务】之二:从零开始,轻松搞定SpringCloud微服务系列--注册中心(一)
微服务体系,有效解决项目庞大.互相依赖的问题.目前SpringCloud体系有强大的一整套针对微服务的解决方案.本文中,重点对微服务体系中的服务发现注册中心进行详细说明.本篇中的注册中心,采用Netf ...
- Android系统分析之运营商显示流程分析之运营商信息的读取流程二
运营商显示流程分析之运营商信息的读取流程 一. SIM卡运营商信息的读取 从前面的 运营商信息的获取和赋值 可以知道SIM卡运营商的赋值最终是在 SIMRecords 中完成的, 而SIM卡信息的相关 ...
- 基于asp.net + easyui框架,一步步学习easyui-datagrid——实现分页和搜索(二)
http://blog.csdn.net/jiuqiyuliang/article/details/19967031 目录: 基于asp.net + easyui框架,一步步学习easyui-data ...
- Solr系列五:solr搜索详解(solr搜索流程介绍、查询语法及解析器详解)
一.solr搜索流程介绍 1. 前面我们已经学习过Lucene搜索的流程,让我们再来回顾一下 流程说明: 首先获取用户输入的查询串,使用查询解析器QueryParser解析查询串生成查询对象Query ...
- Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)
一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...
- 高可用服务设计之二:Rate limiting 限流与降级
<高可用服务设计之二:Rate limiting 限流与降级> <nginx限制请求之一:(ngx_http_limit_conn_module)模块> <nginx限制 ...
随机推荐
- python第三天 变量 作业
作业1,模拟登陆:1. 用户输入帐号密码进行登陆2. 用户信息保存在文件内3. 用户密码输入错误三次后锁定用户 使用文件:user_file.txt 用户列表文件. 格式:{'张三':'12 ...
- 50个常用sql语句 网上流行的学生选课表的例子
50个常用sql语句 建表: --学生表tblStudent(编号StuId.姓名StuName.年龄StuAge.性别StuSex) --课程表tblCourse(课程编号CourseId.课程名称 ...
- Python基础知识:字符串
1.Python中大写字母命名的变量,默认为常量,不可修改:列如:MYSQL_CONNECTION = '192.168.1.1' 2.字符串换行输入格式:换行用\隔开,两行分别用引号,制表符\t,换 ...
- 19LaTeX学习系列之---LaTeX的总结
目录 目录 前言 (一)本系列的章节目录 (二)快速温习LaTeX 1.介绍 2.源文件结构 3.文档的结构 4.字体的设置 5.图片的插入 6.表格的插入 7.数学公式的插入 8.交叉引用与浮动体 ...
- vue学习笔记1-基本知识
1.npm 安装node.js的时候会一起安装npm包管理器,能够解决nodejs代码部署问题,常见使用如下: 允许用户从npm服务器下载别人编写的第三方包到本地应用允许用户从npm服务器下载并安装别 ...
- NSTimer+倒计时功能实现
NSTimer 一.前言,查看官方文档,可以发现NSTimer是Foundation框架下的一个类,它直接继承与NSObject. 二.常用属性 1. @property (copy) NSDate ...
- Djando 的 cmd命令
1.黑窗口命令 安装Django pip install django==1.11.16 -i https://pypi.doubanio.com/simple/ 创建项目 django-ad ...
- 洛谷P1621-集合
Problem 洛谷P1621-集合 Accept:496 Submit: 1.4k Time Limit: 1000 mSec Memory Limit : 128MB Problem De ...
- dd测试
time dd if=/dev/zero of=/root/test.db2 bs=200K count=10000 oflag=dsync
- 容器中JVM获取真实的CPU核数
容器中JVM获取真实的CPU核数 基于 libsysconfcpus的方案,可以为各个版本的JDK提供一个通用的解决方案. libsysconfcpus.so的原理是截获JVM获取CPU核数所用的系统 ...