安卓蓝牙SDP协议数据包

news2024/11/19 3:17:17

1. SDP概念

我们想一想,两个陌生的设备(之前未有过交互)如何去发现对方支持什么服务呢?比如Host端的Controller怎么知道远程蓝牙设备是蓝牙耳机还是HID遥控器呢?我们需要一种协议,这种协议在蓝牙设备配对成功后,能让两个蓝牙设备通信,知道对方的能力(即支持什么Profile)。
SDP(Service Discovery Protocol)协议,它是一种服务发现的协议,在Core_v4.2 Vol 3, Part B,它规定了在服务器上面是如何存储的数据以及对方如何能够通过这个协议来获取到数据。它使用client-server架构,如下图:
在这里插入图片描述
比如:手机作为SDP Client,蓝牙耳机作为SDP Server,手机通过SDP协议向蓝牙耳机“咨询”它的能力。
SDP协议的重点与难点,在于理解服务、服务记录和属性的概念。为了辅助理解,可以用数据库做类比,服务为某个数据库(如MySQL),服务记录则是某类的数据,属性这是这类数据中具体的数据表格。SDP协议的作用则是发现对端所有的服务,以及该服务提供了哪些功能。

2. 相关概念

服务记录(ServiceRecord)

一个服务可能是任何能为另一个实体提供信息,采取行动或控制资源的实体。
SDP服务器维护的每一个服务信息都使用Service Record来表示。这个Service Record由若干ServiceAttribute组成,如下图所示:
在这里插入图片描述

服务属性(Service Attribute)

服务属性由两部分组成,attribute ID和attribute value组成。其结构如下图所示:
在这里插入图片描述
Attribute ID是一个16bits的无符号整形,用于区分各个Attribute,协议里面Core_v4.2 Vol 3, Part B 5 SERVICE ATTRIBUTE DEFINITIONS已经定义了很多Attribute和它们的Attribute ID。
attribute value是根据attribute ID的数据单元(Data Element),它的格式会因Attribute ID的不同而不同。
正因为SDP Service Record由许多Attribute组成,所以,可以把Record看成AtributeList,这在后面的SDP resposne中会常用到。

服务类(Service class)

Service Record只是一个service在软件或硬件上的表现形式(或称存储形式),而一个蓝牙设备支持的SDP service可能有多个,使用Service class来描述一个service(类似于面向对象,Service class是一个抽象类,而一个特定的service就是一个具体实例,而Service Record说明这个对象的数据是以Attribute列表的形式存储起来的)。
SDP协议规定了Service class有以下几个“类成员变量”(下面代码只是大概,并不准确):

struct Attribute{
	usigned16 AttributeID;
	DataElement Value;		// DataElement的定义因AttributeID不同而不同
};
Class Service{		//下面列举一些服务的属性,一个服务可能只实现其中的某些属性。
	Attribute ServiceClassIDList;
	Attribute ServiceID;
	Attribute ProtocolDescriptorList;
	Attribute BluetoothProfileDescriptorList;
	Attribute ServiceName;
	Attribute ServiceDescription;
	......
};

Class AttributeList{		// AttributeList就是一个Service Record
	Attribute ServiceRecordHandle;	//具有唯一的32bit的Handle
    class Service service;
}

SDP规定使用service class identifier来区分不同的Service class。SDP协议规定这个值是一个UUID——唯一标识符,它是128bit的数字,但为了减少存储和传输负担,协议里面规定只有高16bit(以后可能有32bit的)用来区分Service Class,其它bit的值固定。另外,有些常用的服务类已经预定了UUID,参考文档《16-bit UUID Numbers Document.pdf》。ServiceClassIDList成员可保存一个或多个service class identifier,它表示所属的Service适用于一个或多个service class。
此外,有个特殊的Service class,叫BrowseGroupDescriptor。它的作用是方便Client通过Brower。通常,Client根据服务的某些期望UUID搜索服务。然而,有时需要知道SDP服务器的服务记录描述了哪些类型的服务,这个查询过程称为浏览。这个过程依赖一个特殊的Service class,叫BrowseGroupDescriptor。本文不展开说明了。
例子:
在这里插入图片描述

数据单元(Data Element)

sdp协议数据包(即attribute value)是数据单元的集合,一个数据包中可能包含一个或多个数据单元。每个数据包的头部都是一个“type descriptor(类型描述符)+Size descriptor”组成。
type descriptor占一个字节,由两部分组成:type descriptor(high 5-bits) 和size descriptor(low 3-bits):
在这里插入图片描述
上图中,第一列说明了Type descriptor可以取的值,目前之定义了0~8,第二列说明了不同的 Type descriptor会有不同的size descriptor值,比如Type descriptor为3,则size descriptor值只能取“1,2,4”中的一个值,第三列是这个Type的描述。
size descriptor描述如下:
在这里插入图片描述
因Type descriptor限制了size descriptor的取值,那size descriptor各个值得意思如上图。
实际运用可以参考如下的例子:
在这里插入图片描述
对上图三个Data Element的解释:
A. 这是个“空”的Data Element,Tpye为0,要求Size域的值只能为“0”,表示后面没有数据。
B. 这是一个函数16-bit的整型数,Type为2,表示一个有符号的二进制数,Size域的值为1,表示后面数据长度是2 byte。
C. 这是一个字符串“Hat”,Type为4,表示一个文本字符串,Size域的值为5,意思是后面是一个8bit的无符号数字,它说明了后面的字符串长度,比如8bit的值为3,即后面的字符串长度为3 Byte。

PDU报文格式

SDP协议的数据使用网络字节序,即大端字节序,与底层HCI、L2cap协议有所区别,需要特别注意!
其协议头部由三部分组成:PDU ID、Transaction ID和Parameter Length组成,Parameter则是上文所述的一个个数据单元。其具体的描述如下:
在这里插入图片描述
其中PDU ID表示协议包的类型,类型种类如下图所示:
在这里插入图片描述
TransactionID:用以区别其他的Transaction。大概的意思是Controller发送一个SDP请求后,在没有得到远程蓝牙设备回复之前,Controller又需要发送一个SDP请求,这时,PDU ID可能和上一次是一样的,所以需要用TransactionID来区分这是另一个请求。远程蓝牙设备在回复时,也需要加上TransactionID,标识它回复的是哪个请求。
另外还有一个概念Continuation State:当SDP 服务器返回client 结果的时候,如果数据太大,那么就会分包,下面额度变量就是分包的标志,如果部分包,其值为0
在这里插入图片描述

交互流程

根据PUD id 的不同,交互的流程也不同,但是思路都是一样,都是CS的架构
这里我们对ServiceSearchAttributeRequest PDU的request和response做简要说明,其他有兴趣的可以自行参考核心规范。Core_v4.2 Vol 3, Part B 4.7 ServiceSearchAttributeRequest 一次服务发现交互事务逻辑如下图所示,Client端可认为是手机,Server端可任务是蓝牙耳机:
在这里插入图片描述
1. SDP_ ServiceSearchAttributeRequest PDU
首先由client发起请求Service Search Attribute Request,描述如下
在这里插入图片描述
这个命令有4个参数,也就是说PDU里面除了报文头部,后面跟随四个参数,每个参数的长度可能不一样。
从btsnoop中摘取一次Service Search Request进行数据分析,这里只针对sdp进行解析:
PDU ID=0x06
TransactionID=0x0000
ParameterLength=0x0013,即19Byte。
接下来描述的是第一个参数ServiceSearchPattern——35 03 19 11 0B
DATA Element header =0x35,二进制表示为00110101b,type=00110b=0x06,标识后面的数据是一个Data element(说明DATA Element可以嵌套);size index=101b=0x05,表示后面1Byte是一个额外的字节描述后续字节长度。
Additional size(额外字节)=0x03,意思是后面跟着大小为3个字节的DATA Element——19 11 0B,这个DATA Element同样有header=0x19,二进制表示0x00011001,type=00011b=0x03,标识后面数据是一个UUID,UUID值=0x110B(注意SDP是大端格式),查16-bit UUID Numbers Document.pdf,UUID的别名是AudioSink。
接下来描述的是第二个参数MaximumAttributeByteCount(Attribute能返回的最大字节数),两个字节,0x0290=656。
第三个参数AttributeIDList——35 09 09 00 01 09 00 04 09 00 09。属性列表的数据是包含一个或多个Data element的列表,每个Data element里面标识了Service Search Request的attribute ID。这样在命令结束后,远程蓝牙设备会返回attribute ID相关的服务信息。
Data element header:=0x35,二进制表示为00110101b,type=00110b=0x06,标识后面的数据是一个Data element;size index=101b=0x05,表示后面1Byte是一个额外的字节描述后续字节长度。
Additional size(额外字节)=0x09,意思是后面跟着大小为9个字节的Data element(有三个)。
Data element header:=0x09,二进制表示为00001001b,type=00001b=0x01,标识后面的数据是一个整型数;size index=001b=0x01,表示后面2Byte都是整型数的值,分别是0x00,0x01。即属性ID=0x0001,是ServiceClassIDList Attribute。
Data element header:=0x09,二进制表示为00001001b,type=00001b=0x01,标识后面的数据是一个整型数;size index=001b=0x01,表示后面2Byte都是整型数的值,分别是0x00,0x04。即属性ID=0x0004,是ProtocolDescriptorList Attribute。
Data element header:=0x09,二进制表示为00001001b,type=00001b=0x01,标识后面的数据是一个整型数;size index=001b=0x01,表示后面2Byte都是整型数的值,分别是0x00,0x09。即属性ID=0x0009,是BluetoothProfileDescriptorList Attribute。
第四个参数——ContinuationState
是一个8-bit的数字,本例子中为0x00。

2. SDP_ServiceSearchAttributeResponse PDU
当服务器收到请求之后,给出对应的Service Search Attribute Response描述如下:
在这里插入图片描述
在这里插入图片描述
如上图,分别返回了三个指定属性ID的信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/670038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git-Desktop【使用说明】

仓库操作 简单的创建仓库、删除仓库 删除点击 Remove 即可 文件操作 1、提交文件到本地仓库 2、修改文件 Git没有修改文件这一说,它只会再次提交一个新的版本到仓库中,提交修改后的文件其实是在仓库创建了一个新的文件,只不过是一个不同的…

Optano.Modeling 简单教程

前言 在工作中遇到两个需求,将两个数学公式用 .NET 的数学库找到数学公式中某个未知数的最优解,我尝试了几个数学库都没有办法完美解决我的需求,直到找到 Optano.Modeling Optano.Modeling 官网:Optano.Modeling 官网 Optano.Mo…

AI操作视频的工具最新最强集合

AI的进化日新月异,很多之前只是在想象中的操作,已经有很多可以使用AI来完成了。最新的Stable Diffusion,ControlNet,EBsynth有哪些神奇的应用,如何一键替换视频中人物和场景,如何根据文字描述即可生成梦幻视频?我们整理…

DFS/回溯/动态规划算法的融会贯通

学算法认准 labuladong 后台回复课程查看精品课 点击卡片可搜索文章👇 在线学习网站: https://labuladong.gitee.io/algo/ 经常有读者后台问我,DFS算法/回溯算法/动态规划算法之间的区别和联系是什么? 对于这个问题,我…

私有化部署的无忧·企业文档2.1.7新版本核心功能介绍

无忧企业文档是一款针对企业用户提供在线文档、协同编辑、知识管理的基础化办公工具,产品采用B/S构架。功能覆盖场景包括:在线文档的私有化部署、团队协同、知识管理、在线文档识别的扩展、文档权限化管理等等场景。本次2.1.7版本更新了以下几个核心功能…

【机器学习】十大算法之一 “线性回归”

作者主页:爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

什么是事件委托

文章目录 导文文章重点具体而言,事件委托包含两个主要角色:通过使用事件委托,可以实现以下优势: 代码示例 导文 事件委托是一种在软件开发中常用的设计模式,用于处理事件和回调函数。它允许一个对象(委托对…

数据帧转发过程中IP地址及MAC地址的变化

数据帧在交换机间转发 帧经过交换机时,其源、目标MAC是不会变的。 交换机内部的CPU会在每个端口成功连接时,通过将MAC地址和端口对应,形成一张MAC表。在今后的通讯中,发往该MAC地址的数据包将仅送往其对应的端口,而不…

odoo字段加密以及模糊显示

在信息时代,信息本身是把双刃剑,一方面它服务于我们的生产、生活、使我们受益; 一方面,信息的泄露可能对我们构成巨大的威胁。因此,客观上就需要一种有力的安全措施来保护机密数据不被窃取或篡改 。 数据加密与解密从宏观上讲是非…

[2022]DyOb-SLAM : Dynamic Object Tracking SLAM System

1.作者 Rushmian Annoy Wadud、Wei Sun 2.时间 2022 3.整体架构 DyOb-SLAM是DynaSLAM和VDO-SLAM的结合: 基于先验信息使用Mask RCNN分割出动态目标通过基于光流和场景流的算法对运动目标进行跟踪对静态点进行BA优化 输出: 当前帧显示ORB特征以及Masj信息和对…

探索Zabbix API:企业监控管理工具

新钛云服已累计为您分享754篇技术干货 Zabbix是一种流行的开源监控解决方案,其强大的API功能为用户提供了灵活且可扩展的监控管理能力。本文将介绍Zabbix API的基本概念和用法,以及如何利用API来简化监控配置、数据获取和自动化任务等方面的工作。 在现代…

数据结构 树

树的基本概念 树是一种非线性的数据结构,它由节点(node)和边(edge)组成。树的基本概念包括以下要点: 树由一个根节点(root)开始,根节点没有父节点,它可以有…

华为OD机试之阿里巴巴找黄金(III)(Java源码)

文章目录 阿里巴巴找黄金(III) 阿里巴巴找黄金(III) 题目描述 一贫如洗的椎夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地,藏宝地有编号从0~N的箱子,每个箱子上面贴有一个数字。阿里…

Rancher创建arm架构的下游k8s集群

目录 前言添加自定义集群镜像源配置使用支持ARM架构的docker镜像 前言 费了些时间在成功在华为云arm架构的服务器上搭建了k8s集群,期间问题不断,以下是三个关键点: 确保网络能正常拉取所需镜像拉取的镜像需支持arm架构 否则报错&#xff1a…

SOFAStack 的下一个五年

文|宋顺(GitHub ID:nobodyiam) SOFAStack 社区开源负责人 蚂蚁集团高级技术专家 本文 3861 字 阅读 11 分钟 #01 回顾开源这五年 回想起 2018 年 4 月 19 日 SOFAStack 首次开源,当时的官宣文章中就提到了我们开源的初心&#xf…

C++——map/mutimap再理解

目录 1. map 1.1 map介绍 1.2 map的构造 1.3 map插入和删除 1.4 map的迭代器 1.5 map[ ]运算符重载 1.6 map的查找find 1.7 map的删除erase 1.8 map的其它函数 1.9 map的总结 2. multimap 2.1 multimap的介绍 2.2 mutimap的使用 1. map 1.1 map介绍 1、map是关联…

多窗口通信

1、基本概念 BroadcastChannel接口代理了一个命名频道,可以让指定 origin 下的任意 browsing context 来订阅它。它允许同源的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间相互通信。通过触发一个 message 事件,消…

第3讲:使用ajax技术实现异步登录功能(XMLHttpRequest)

封装XMLHttpRequest对象,实现ajax异步登录功能;用三种不同的方法实现登录功能, 方法一:返回文本内容; 方法二:返回JSON格式数据; 方法三:使用fastJSON生成JSON数据,返…

Tensorboard‘s sample_per_plugin

Tensorboard’s sample_per_plugin Tensorboard’s sample_per_plugin controls the step size of the slider. Draw the train images to tensorboard: step 0 writer SummaryWriter() for imgs, labels in train_loader:grid torchvision.utils.make_grid(imgs)writer.…

Android 设计中心 | 助您为各种设备类型轻松打造精彩界面

作者 / Android 开发者体验部设计负责人 Adhithya Ramakumar 和 Android 高级开发者关系工程师 Rebecca Gutteridge 我们推出了 Android 设计中心,帮助开发者更轻松地针对各种类型的设备构建引人注目的界面。 Android 设计中心https://developer.android.google.cn/…