十、GAP
1.1 背景
GAP(Generic Access Profile)位于主机协议栈的最顶层,用来定义BLE设备在待机或者连接状态中的行为,该Profile保证不同的Bluetooth产品可以互相发现对方并建立连接。GAP定义了:
蓝牙设备如何发现和建立与其他设备的安全/不安全连接;
处理一些一般模式的业务(如询问、命名和搜索)和一些安全性问题(如担保) ;
处理一些有关连接的业务(如链路建立、信道和连接建立);
下图直观地展示了GAP处于蓝牙协议栈的层次关系。
GAP Role |
Description |
BROADCASTER |
A device that only sends advertising events. |
OBSERVER |
A device that only receives advertising events. |
PERIPHERAL |
A device that accepts the establishment of an LE physical link using the connection establishment procedure. |
CENTRAL |
A device that supports the Central role initiates the establishment of a physical connection. |
1.2 广播(advertising)
蓝牙设备通过在广播数据包中发送广播包(PDUS)来允许其他设备(scanners)发现并连接它,这些广播数据最大长度支持31字节的可配置数据,针对到来的scan request,在scan response中,蓝牙设备(Broadcaster)可以发送额外的31字节数据。GAP一共定义了四种不同类型的广播数据包类型:
Advertising PDU |
Description |
Max Adv Data Len |
Max Scan Res Len |
Allow Connect |
ADV_IND |
用于发送可连接,非定向的广播 |
31 bytes |
31 bytes |
Yes |
ADV_DIRECT_IND |
用于发送可连接,定向广播 |
N/A |
N/A |
Yes |
ADV_SCAN_IND |
用于发送扫描,非定向广播 |
31 bytes |
31 bytes |
No |
ADV_NONCONN_IND |
用于发送非可连接,非定向广播 |
31 bytes |
N/A |
No |
在上面的表格中,除了直接广播(ADV_DIRECT_IND),其余广播PDU携带广播数据报文最大长度是31字节。对于直接广播来说,其只携带了6字节的目标设备地址,该目标设备地址的预期被连接的设备地址。另外,所有的广播类型允许对于到来的scan response做出scan response,除了直接广播(ADV_DIRECT_IND)和非连接广播(ADV_NONCONN_IND),更多信息,请参考BT Core Spec V4.2 Vol. 6, Part B, Section 4.4。
下面的表格总结了广播过程中可以配置的参数:
Parameter |
Description |
Range |
Advertising Interval |
Time between the start of two consecutive advertising events |
20ms to 10.24s |
Advertising Types |
Different PDUs are sent for different types of advertising |
Connectable undirected, connectable directed, scannable directed, non-connectable |
Advertising Channels |
Advertising packets are sent on three channels |
Different combinations of channels 37, 38 and 39. |
蓝牙设备有三个特定的广播通道,分别是:通道37 (2402 MHz), 通道 38 (2426 MHz), 和通道39 (2480 MHz)。这三个通道选择能够将与WIFI干扰降低到最小,下图展示了一个广播事件,该事件使用了全部三个广播通道。
需要注意的是:在这三个广播通道上,相同的数据被传递,GAP允许设备只广播在某一个或者两个通道上。在更少的通道上进行广播,意味这激着更小的能量消耗。但是,会降低被对端设备侦听到的概率。
1.3 扫描(Scanning)
当设备处于连接状态时,其或可以发送广播包对外广播其存在,或扫描周边正在广播的设备。扫描周边设备的过程称为设备发现。GAP定义了两种扫描类型——主动(active)和(被动),两者的区别是,前者可以发送scan request从广播者获取更多额外的信息,而后者仅仅能够接收广播者的广播数据。如无特殊语境,“发现”和“扫描”两个术语讲不加区分,交替使用。下图演示了一个设备对广播者发送扫描请求以及广播者做出应答的时序图。
在扫描过程中,你需要熟悉一些扫描参数,每个参数都有特定的范围,下表罗列了这些参数的语义以及可配置范围。
Parameter |
Description |
Range |
Scan Interval |
Interval between the start of two consecutive scan windows |
10ms to 10.24s |
Scan Window |
The duration in which the Link Layer scans on one channel |
10ms to 10.24s |
Scan Duration |
The duration in which the device stays in the scanning state |
10ms to infinity |
GAP并没有规定扫描过程中,对三个广播通道的扫描顺序,扫描者在每个扫描间隔内,在一个扫描窗口期间内,依次扫描37,38,39通道。下图形象的展示了这些扫描参数的内涵:
1.4 模式/状态
一、发现模式(Discoverablity Modes), 对应于inquiry(inquiry request/response)
- Non-discoverable Mode: 不响应inquiry;
- Discoverable Mode: 是下面两种模式的总称, 设备进入INQUIRY_SCAN状态, 响应inquiry;
- Limited discoverable Mode: 响应LIAC inquiry;
- General discoverable Mode: 响应GIAC inquiry;
二、连接模式(Connectability Modes), 对应于paging(paging request/response)
- Non-connectable Mode: 不响应paging;
- Connectable Mode: 设备进入PAGE_SCAN状态, 响应paging;
三、配对模式(Bondable Modes), 对应于bonding/paring, 需要和SSP(Secure Simple Pairing)配合使用
- Non-bondable Mode: 设备不可接受来自远端设备的绑定/配对请求;
- Bondable Mode: 设备可接受来自远端设备的绑定/配对请求;
1.5 ADK信号时序
以ADK4.4为例,简单的罗列了设备在初始化时,如何进行扫描,广播初始化的,具体细节请见ADK源代码。
/*Power on -> start scan -> start(fast)advertising -> start(slow)advertising (if not connected)*/
sink_ble.c
sinkBleInitialiseDevice()-->
ConnectionDmBleAddTdlDevicesToWhiteListReq(BLE_ONLY) /* Setup whitelist*/
sinkGattInitInitialiseDevice(); /* Initialise GATT */
sinkBleGapInitialise();-->
sinkBleGapInitGapConnFlag();
gapSetAdvSpeed(ble_gap_adv_speed_fast);
sinkBlePowerOnEvent()-->
sinkBleGapEvent(ble_gap_event_power_on)-->
gapStateIdleHandleEvent()-->
sinkBleSetGapState(ble_gap_state_scanning_advertising)
sinkBleCheckNoConnectionsEvent()-->BLE_INTERNAL_MESSAGE_EVENT_NO_CONNECTIONS
-->sinkBleGapEvent(ble_gap_event_no_connections)
gapStateScanAdvHandleEvent(ble_gap_event_no_connections)-->
sinkBleGapStartReadLocalName(ble_gap_read_name_advertising)
gapStartScanning(TRUE)-->
bleStartScanning()-->
ConnectionDmBleSetScanParametersReq()-->DM_HCI_ULP_SET_SCAN_PARAMETERS_REQ
ConnectionDmBleSetScanEnable(TRUE)
bluestack_handler.c
DM_HCI_READ_LOCAL_NAME_CFM-->
connectionHandleLocalNameComplete()-->
localNameComplete()-->CL_DM_LOCAL_NAME_COMPLETE
sinkBleHandleCLMessage()-->CL_DM_LOCAL_NAME_COMPLETE-->
sinkBleGapReadLocalNameComplete()-->
bleSetupAdvertisingData(ble_gap_read_name_advertising)-->
ConnectionDmBleSetAdvertisingDataReq()-->
DM_HCI_ULP_SET_ADVERTISING_DATA_REQ
DM_HCI_ULP_SET_ADVERTISING_DATA_CFM-->
connectionHandleDmBleSetAdvertisingDataCfm()-->CL_DM_BLE_SET_ADVERTISING_DATA_CFM-->
bleHandleSetAdvertisingData()-->
sinkBleGapEvent(ble_gap_event_set_advertising_complete)
gapStartAdvertising();-->
gapStartAdvertising()-->
sinkBleGetAdvertisingParameters()
sinkBleSetAdvertisingParamsDefault()
sinkGattManagerStartAdvertising()-->
sinkEnableGattConnectable()-->
enablePageScan(sink_scan_connectable_gatt)
gapStartFastAdvTimer()-->
MessageSendLater(BLE_INTERNAL_MESSAGE_FAST_ADV_TIMER)
BLE_INTERNAL_MESSAGE_FAST_ADV_TIMER-->
sinkBleGapEvent(ble_gap_event_fast_adv_timeout)-->
gapStateScanAdvHandleEvent()-->
gapStopAdvertising(ble_gap_adv_speed_slow)-->
gapSetAdvSpeed(new_speed) /* First stop fast advertising*/
sinkGattManagerStopAdvertising()--> /* Then start slow advertising */
GattManagerCancelWaitForRemoteClient()
GATT_MANAGER_CANCEL_REMOTE_CLIENT_CONNECT_CFM-->
handleGattManagerCancelRemoteClientConnectCfm()-->
sinkBleCancelAdvertisingEvent()-->
sinkBleGapEvent(ble_gap_event_cancelled_advertising)-->
gapStateScanAdvHandleEvent()-->
sinkBleGapStartReadLocalName(ble_gap_read_name_advertising)
十、GAP的更多相关文章
- 十大经典排序算法总结(JavaScript描述)
前言 读者自行尝试可以想看源码戳这,博主在github建了个库,读者可以Clone下来本地尝试.此博文配合源码体验更棒哦~~~ 个人博客:Damonare的个人博客 原文地址:十大经典算法总结 这世界 ...
- 十大经典排序算法总结——JavaScrip版
首先,对于评述算法优劣术语的说明: 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面:即排序后2个相等键值的顺序和排序之前它们的顺序相同 不稳定:如果a原本在b的前面,而a=b,排序之后a ...
- JS的十大经典算法排序
引子 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements JavaScript. 当年,想凭借抱Java大腿火一把而不惜把自己名字给改了的JavaScript(原名LiveScript ...
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- Gap year | 最好金龟换酒
Gap year | 最好金龟换酒 Gap year Posted on February 8, 2009 by 真 后.90后相比,说是虽然形成背景不同,但有很多特征相似,比如离经叛道,比如信仰缺失 ...
- 十大经典排序算法的JS版
前言 个人博客:Damonare的个人博客 如遇到问题或有更好的优化方法,可以: 提issue给我 或是pull requests 我都会看到并处理,欢迎Star. 这世界上总存在着那么一些看似相似但 ...
- 排序算法——(2)Python实现十大常用排序算法
上期为大家讲解了排序算法常见的几个概念: 相关性:排序时是否需要比较元素 稳定性:相同元素排序后是否可能打乱 时间空间复杂度:随着元素增加时间和空间随之变化的函数 如果有遗忘的同学可以看排序算法——( ...
- Android为TV端助力 转载:Android绘图Canvas十八般武器之Shader详解及实战篇(下)
LinearGradient 线性渐变渲染器 LinearGradient中文翻译过来就是线性渐变的意思.线性渐变通俗来讲就是给起点设置一个颜色值如#faf84d,终点设置一个颜色值如#CC423C, ...
- 死锁问题分析(个人认为重点讲到了gap间隙锁,解决了我一些不明报死锁的问题)
线上某服务时不时报出如下异常(大约一天二十多次):“Deadlock found when trying to get lock;”. Oh, My God! 是死锁问题.尽管报错不多,对性能目前看来 ...
随机推荐
- python使用input().split()接收多个用户输入
1.input() 接收多个用户输入需要与split()结合使用 host, port, username, passwd, dbname = input("请输入服务器地址,端口号,用户名 ...
- 在Spring Boot项目中使用Spock测试框架
本文首发于个人网站:在Spring Boot项目中使用Spock测试框架 Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring Boot项目 ...
- 在已有 Windows10 系统的基础上,安装 Ubuntu17.10 系统(新版 BIOS)
1.第一步,下载Ubuntu系统镜像 2.第二步,制作启动U盘,使用UltralSO,步骤:打开文件——选择iso文件——启动——写入硬盘映像——选择U盘——写入 3.第三步,分区,在Windows徽 ...
- Java8系列 (二) Stream流
概述 Stream流是Java8新引入的一个特性, 它允许你以声明性方式处理数据集合, 而不是像以前的指令式编程那样需要编写具体怎么实现. 比如炒菜, 用指令式编程需要编写具体的实现 配菜(); 热锅 ...
- 用Java JMC控制台分析线程阻塞原因
问题 今天在玩dianping-CAT框架时,发现请求某个页面的时候,发生了阻塞.浏览器得不到响应. 环境 本地Tomcat 8 , Windows 系统. 解决 启动jmc 控制台,找到BLOCKE ...
- NetworkManager网络通讯_NetworkLobbyManager(三)
此部分可以先建立游戏大厅,然后进入游戏,此处坑甚多耗费大量时间.国内百度出来的基本没靠谱的,一些专栏作家大V也不过是基本翻译了一下用户手册(坑啊),只能通过看youtube视频以及不停的翻阅用户手册解 ...
- jquery链式原理.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 阿里云和微软共同开源的 OAM 对 Kubernetes 开发人员意味着什么?
上周,微软和阿里巴巴共同推出了开放应用模型(OAM),用于定义部署在任何地方的应用模型的一种规范.Rudr是Microsoft基于Kubernetes环境的OAM标准实现. 我用了一个周末来了解OAM ...
- 使用Java调用exe可执行文件
一.出发点 平日里,我们看到了很多已经成型的可执行文件,而且经过了一定的封装.因为开源的关系,大多时候可以自己使用eclipse进行编译,但也常常遇到不如直接调用更加方便的情况.那么这时候,我个人需要 ...
- Mybaits 源码解析 (九)----- 全网最详细,没有之一:一级缓存和二级缓存源码分析
像Mybatis.Hibernate这样的ORM框架,封装了JDBC的大部分操作,极大的简化了我们对数据库的操作. 在实际项目中,我们发现在一个事务中查询同样的语句两次的时候,第二次没有进行数据库查询 ...