十、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! 是死锁问题.尽管报错不多,对性能目前看来 ...
随机推荐
- V2er - Best client for V2EX
V2er - Best client for V2EX 可能是体验最好的掌上 V2EX 客户端,专为 iOS 打造并在 Github 开源. 关于 V2EX,V2EX 是创意工作者们的社区.这里目前汇 ...
- WebStorm 使用过程中出现的一些问题以及解决方案
标签: WebStorm 配置 描述: 有关 WebStorm 使用过程中出现的一些问题以及其解决方案的汇总 "unresolved function or method" 问题描 ...
- 百万年薪python之路 -- re模块
re模块 re模块是python用来描述正则表达式的一个模块. 正则表达式本身也和python没有什么关系,就是匹配字符串内容的一种规则. 官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先 ...
- kali2019里安装Burp Suite安装破解版加汉化版
Burpsuite是一个强大web漏洞挖掘工具,截断代理,解码和编码,Fuzzy进行各种注入和暴力破解 插件扩展,有多个模块 Burp Suite没有中文版的,我英语又不好,我虽然精通Burp Sui ...
- Flask:Flask-script插件
Flask-Script插件扩展提供向Flask插入外部脚本的功能,包括一个开发用的服务器,一个定制的python shell,设置数据库的脚本,cronjobs,及其它运行在web应用之外的命令行任 ...
- C++智能指针类型转换
#include <iostream> #include <memory> struct Base { int a; virtual void f() const { std: ...
- 条款03:尽肯使用const
定义常量 define 是一个Compile-Time的概念,它的生命周期止于编译器期,它存在与程序的代码段,在实际程序中它只是一个常数.一个命令中的参数.并没有实际的存在 const常量存在于程序的 ...
- SpringCloud 中集成Sentinel+Feign实现服务熔断降级
Sentine 1.背景 Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度来帮助用户保护服务的稳 ...
- mysql多种备份与恢复方式一
基于mysql社区版5.7,严重声明:本文中图方便直接写入了-p数据库密码,在生产环境中如果指定了一定要使用history -C清空历史命令记录哦,所有博客作者原创纯手打,转载一定要注明本博客链接,感 ...
- MYSQL5.7修改密码强度策略
---恢复内容开始--- 在MySQL5.6.6之后,ORACLE更新了mysql密码强度必须要使用大小写数字符号来设置密码,但是有时候这样还是很不方便的.所以记录一篇如何修改mysql密码强度的博文 ...