零.声明
本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:
第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。
第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等
第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等
第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。
第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)
第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等
第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展
第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。
另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。
-------------------------------------------------------------------------------------------------------------------------
蓝牙视频教程(跟韦东山老师合作):
https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.20.5aeb41f98e267j&id=693788592796
蓝牙交流扣扣群:765961169
Github代码:GitHub - sj15712795029/bluetooth_stack: 这是一个开源的双模蓝牙协议栈(bluetooth.stack)(btstack),可以运行在STM32,Linux.,包含HCI,L2CAP,SDP,RFCOMM,HFP,SPP,A2DP,AVRCP,AVDTP,AVCTP,OBEX,PBAP等协议,后续会继续维护,以达到商用的目的
入手开发板:https://shop220811498.taobao.com/category-1542116976.htm?spm=a1z10.5-c-s.w4010-22329603913.7.39ca7dbe2EA0K3&search=y&catName=%C0%B6%D1%C0%BF%AA%B7%A2%B0%E5#bd
蓝牙学习目录:一篇文章足够你学习蓝牙技术,提供史上最全的蓝牙技术(传统蓝牙/低功耗蓝牙)文章总结,文档下载总结(2020/12/11更新)_Wireless_Link的博客-CSDN博客_蓝牙eir
--------------------------------------------------------------------------------------------------------------------------
一. AVRCP command跟response
AVRCP特定的command有以下几种:
这么多PDU,我们不会一一介绍,只介绍几个典型的,其他的自己举一反三。
1. Capabilities
这个下面一共有一个实现
这个是AVRCP controller发给target的,来获取对端设备的能力,包括公司名称以及支持的event.整个数据格式如下:
获取公司ID response的格式为:
获取支持event的response格式为:
其中Capability EventID有:
我们介绍到notify的时候会详细介绍以上几个
我们结合前面的讲的vendor dependent格式来举例看下整个封包格式:
实际应用中我们一般只会用到Get Capabiliby for event,来获取对端支持的event,方便注册notify,可以看到上图支持播放状态改变,歌曲改变,播放器设置改变。当然在一般的代码中也会先获取支持的company然后再获取支持的event列表!
2. Notifications
2.1 GetPlayStatus
这个命令是controller像target发送获取播放状态的命令,返回值包括歌曲总长度,歌曲当前进度,以及播放状态,一共占用9byte(4byte歌曲长度,4byte当前进度,1byte播放状态)
我们来看下一个btsnoop
2.2 RegisterNotification
这个就是CT像TG注册消息,然后TG有对应的更新会通知,具体消息就是我们之前get capability with event的消息(需要注意的是:每次注册只能一次生效,收到change后要重新注册)我们在来贴下
我们来看下command、response的举例
我们来看一个流程图
下面我们就EVENT ID一个个来说下
EVENT_PLAYBACK_STATUS_CHANGED:播放状态改变,有以下值
EVENT_TRACK_CHANGED:歌曲名称改变
EVENT_TRACK_REACHED_END:歌曲到结尾
EVENT_TRACK_REACHED_START:歌曲开始
EVENT_ PLAYBACK_POS_CHANGED:歌曲播放进度变化
占4byte数据,是ms级别
EVENT_BATT_STATUS_CHANGED:电量状态改变,有以下值
EVENT_SYSTEM_STATUS_CHANGED:系统状态改变,有以下值
VENT_ PLAYER_APPLICATION_SETTING_CHANGED:播放器设置改变
其中AttributeID跟value对应如下:
3. Metadata Attributes for Current Media Item
这个主要是获取歌曲信息的(包括名称/专辑名/歌手名/歌曲索引/歌曲总个数等等)
AttributeID列表如下:
根据个数填上ID来获取不同的属性子项
注意两点:
- 如果格式填0,那么获取所有的属性
- 部分手机+部分播放器,比如iphone11+QQ音乐,Title会动态更新歌词
4. Volume handling
绝对音量用1个byte来表示,最高位(bit7)保留使用,所以范围是0x0~0x7f,0x0代表0%,0x7f代表100%,所以一个可读达标0.784%,其实这里我觉得设计的有点奇怪,为啥不用一个可读是1%,这样还方便统计!当然也是个人看法啦!好了,我们来看看其中的技术细节吧!
4.1 SetAbsoluteVolume
这个是用来设置绝对音量的命令,通过Pass throught命令来发送,正常搭配A2DP sink角色的AVRCP应该做controller角色,也就是可以通知上一首/下一首/播放/暂停等功能,但是这里比较特殊,需要A2DP sink搭配的AVRCP角色是TG端,所以一般要支持这个feature,需要AVRCP要做双角色,也就是AVRCP CT/TG!另外这个命令是AVRCP CT发送给TG的,所以如果是手机连接耳机,那么是手机作为CT角色发送给耳机的TG角色,这点尤其要注意,如图所示:
4.2 Notify Volume Change
注册notification时间的消息由AVRCP的controller角色发起,AVRCP的TG角色有音量变化,会通知到CT角色,当然这里也是作为双角色来做,我们还是拿手机连接耳机这个例子来说明,也就是手机还是作为AVRCP的CT角色,耳机作为AVRCP的TG角色。如果所示: