十、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! 是死锁问题.尽管报错不多,对性能目前看来 ...
随机推荐
- Vulnhub靶场渗透练习(四) Acid
利用namp 先进行扫描获取ip nmap 192.168.18.* 获取ip 没发现80端口 主机存活 猜测可以是个2000以后的端口 nmap -p1-65533 192.168.18.14 ...
- 测试中常用sql
1.增删改查 2.同一服务器下,要从一个数据库复制某张表到另一个数据库 create table test.sf_audit_plan as select * from v3_0_sf_full.sf ...
- 04jmeter-Concurrency Thread Group
1.下载插件Custom Thread Groups:参照:00jmeter安装相关 2.添加并发线程组 场景举例: 10个线程2分钟的加速时间5个加速步骤持有目标速率2分钟: 即: 2分钟除以5步, ...
- 让button的文字换行和左对齐
btn.titleLabel.numberOfLines = 0; btn.contentHorizontalAlignment = UIControlContentHorizontalAlign ...
- 百万年薪python之路 -- 运算符及while的练习
1.判断下列逻辑语句的结果,一定要自己先分析 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 1 &g ...
- MongoDB系列---入门安装操作
MongoDB 学习大纲: 1.MongoDB简介与其它数据库对比以及数据类型 2.MongoDB安装 3.MongoDB简单操作 环境要求: Linux 一.MongoDB简介 1 什么是Mongo ...
- Swagger--解决日期格式显示为Unix时间戳格式 UTC格式
在swagger UI模型架构上,字段日期显示为“日期”:“2018-10-15T09:10:47.507Z”但我需要将其作为“日期”:“2018-9-26 12:18:48”. tips:以下这两种 ...
- 如何在python文件中测试sql语句
在manage.py的同级目录下新建一个run.py import os if __name__ == '__main__': #加载Django项目的配置信息 os.environ.setdefau ...
- join的使用
我们还是以这四张表为例:1.left joinselect * from student a left join score b on a.sid=b.sid; 也就是说A中的元素都会显示,没有值的用 ...
- 按钮组件.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...