十、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! 是死锁问题.尽管报错不多,对性能目前看来 ...
随机推荐
- 造轮子了!NETCore跨平台UI框架,CPF
CPF(暂时命名)(Cross platform framework),模仿WPF的框架,支持NETCore的跨平台UI框架,暂时不够完善,只用于测试,暂时只支持Windows和Mac.支持数据绑定, ...
- python编程系列---Pycharm快捷键(更新中....)
以下是我常用到的Pycharm快捷键(还有很多,只是我暂时用的最多的就这些): 在开发过程中,经常使用一些快捷键会大大提高开发效率,不要因为看这多而不用,常用的就那些,用得多就都记住了,脱离鼠标,逼格 ...
- 学习了解Shiro框架
有关Shiro安全框架 实现权限的几种方式 1)通过表来实现 2)shiro框架 3)Spring Security框架 shiro有哪些主要功能 1.授权 访问控制的过程,即确定谁有权访问 2.身份 ...
- Spring Boot从零入门1_详述
本文属于原创,转载注明出处,欢迎关注微信小程序`小白AI博客` 微信公众号`小白AI`或者网站 [https://xiaobaiai.net](https://xiaobaiai.net) 
window.onbeforeunload = function (e) { var evt = e || window.event; evt.returnValue = '离开会使编写的内容丢失'; ...
- Java基础(十)接口(interface)
1.接口的概念 在Java中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述. 例如:Array类中的sort方法可以对对象数组进行排序,但要求满足下列前提:对象所属的类必须实现了Compa ...
- python基础-元组(tuple)及内置方法
元组-tuple 用途:用于存储多个不同类型的值,但是不能存储可变类型数据 定义方法:用小括号存储数据,数据与数据之间通过逗号分隔,元组中的值不能改变. 注意: 1.定义元组时,如果里面只有一个值,在 ...
- 前端技术之:如何创建一个NodeJs命令行交互项目
方法一:通过原生的NodeJs API,方法如下: #!/usr/bin/env node # test.js var argv = process.argv; console.log(argv) ...
- Scrapy爬虫day1——环境配置
安装 Scrapy pip install scrapy 配置虚拟环境 mkvirtualenv Spider 创建项目 在Spider的虚拟环境中运行 scrapy startproject Boo ...
- [考试反思]0901NOIP模拟测试34:游离
又是放假回来的收心考.幸而熬了夜回来也不至于很困(虽说第二天早上困成狗...) 说分数吧: skyhAK300,后面有220,220,220,190,190,180 我170,排第8.凑合,其实不太满 ...