前言

BlueZ协议栈是Linux平台默认使用的蓝牙Host协议栈,上一篇文章介绍了BlueZ协议栈与Linux kernel之间的数据交互是通过socket的方式进行的,Linux内核提供了AF_BLUETOOTH协议簇的socket通道,BlueZ可以通过创建不同protocal的socket来跟内核进行数据通信,例如BTPROTO_HCI/BTPROTO_L2CAP/BTPROTO_ISO等,下面是Linux 蓝牙框图:

Linux Bluetooth Diagram

BlueZ协议栈处于用户空间,本身提供了bluetoothctl/btmon等工具,还提供了基于DBus方式的API接口,所以应用程序可以通过DBus API进行编程。

本文基于BlueZ 5.70版本进行介绍,需要注意的是在新版本中有一些组件和工具已经被社区弃用(例如hcidump/hciconfig/gatttool/hciattach等)。

bluetoothd守护进程

bluetoothd是BlueZ协议栈的守护进程,运行在蓝牙主机设备上,从Makefile文件可以看出,编译bluetoothd目标的source文件包含了目录plugins,profiles,src下的.c/.h文件,其主要功能如下:

  • 各种DBus消息的处理,并将消息转化为socket数据,发送到对应的proto socket上,例如mgmt命令,L2CAP命令,iso命令等;
  • 注册DBus Interface,例如 Adapter,AgentManager, LEAdvertisingManager等;
  • 注册并运行sdp server;
  • 加载plugins插件

下面是bluetoothd的帮助信息,通常该守护程序会在Linux系统启动脚本/etc/init.d/bluetooth中启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# bluetoothd -h
Usage:
bluetoothd [OPTION?]

Help Options:
-h, --help Show help options

Application Options:
-d, --debug=DEBUG Specify debug options to enable
-p, --plugin=NAME,.., Specify plugins to load
-P, --noplugin=NAME,... Specify plugins not to load
-f, --configfile=FILE Specify an explicit path to the config file
-C, --compat Provide deprecated command line interfaces
-E, --experimental Enable experimental D-Bus interfaces
-K, --kernel Enable kernel experimental features
-n, --nodetach Run with logging in foreground
-v, --version Show version information and exit

BlueZ常用工具

BlueZ协议栈提供的工具都是C语言基于DBus interface实现的,下面介绍两个比较实用的工具。

bluetoothctl

在shell窗口下输入bluetoothctl,会在shell中显示hci和controller信息,并进入交互行界面[bluetooth]#,如下信息所示,可以输入help查看支持的命令,还可以输入show命令查看当前controller和host的详细信息;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# bluetoothctl
Agent registered
hci0 new_settings: powered bondable le secure-conn static-addr cis-central cis-peripheral
[CHG] Controller C3:52:D0:70:ED:01 Pairable: yes
AdvertisementMonitor path registered
[bluetooth]# show
Controller C3:52:D0:70:ED:01 (random)
Name: testSrv
Alias: testSrv
Class: 0x00000000 (0)
Powered: yes
PowerState: on
......
Roles: peripheral
ExperimentalFeatures: BlueZ Experimental ISO... (6fbaf188-05e0-496a-9885-d6ddfdb4e03e)
Advertising Features:
ActiveInstances: 0x00 (0)
SupportedInstances: 0x04 (4)
SupportedIncludes: tx-power
SupportedIncludes: appearance
SupportedIncludes: local-name
......
Advertisement Monitor Features:
SupportedMonitorTypes: or_patterns

需要特别注意的是[bluetooth]交互界面可以通过menu [name]进入name子菜单,支持的子菜单可以在help结果里查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[bluetooth]# help
Menu main:
Available commands:
-------------------
advertise Advertise Options Submenu
monitor Advertisement Monitor Options Submenu
scan Scan Options Submenu
gatt Generic Attribute Submenu
admin Admin Policy Submenu
player Media Player Submenu
endpoint Media Endpoint Submenu
transport Media Transport Submenu
mgmt Management Submenu
monitor Advertisement Monitor Submenu
.....

所以从上面的命令和子菜单可以看出,被弃用的几个工具hcitool,gattool等都可以使用bluetoothctl工具替换。

btmon

btmon命令是bt monitor,用于记录和在线观察HCI log的工具,若将HCI log保存为文件,则需要使用wireshark工具打开,该工具替换了被弃用的工具hcidump。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# btmon --help
btmon - Bluetooth monitor
Usage:
btmon [options]
options:
-r, --read <file> Read traces in btsnoop format
-w, --write <file> Save traces in btsnoop format
-a, --analyze <file> Analyze traces in btsnoop format
If gnuplot is installed on the
system it will also attempt to plot
packet latency graph.
-s, --server <socket> Start monitor server socket
-p, --priority <level> Show only priority or lower
-i, --index <num> Show only specified controller
-d, --tty <tty> Read data from TTY
-B, --tty-speed <rate> Set TTY speed (default 115200)
-V, --vendor <compid> Set default company identifier
-M, --mgmt Open channel for mgmt events
-t, --time Show time instead of time offset
-T, --date Show time and date information
-S, --sco Dump SCO traffic
-A, --a2dp Dump A2DP stream traffic
-I, --iso Dump ISO traffic
-E, --ellisys [ip] Send Ellisys HCI Injection
-P, --no-pager Disable pager usage
-J --jlink <device>,[<serialno>],[<interface>],[<speed>]
Read data from RTT
-R --rtt [<address>],[<area>],[<name>]
RTT control block parameters
-C, --columns [width] Output width if not a terminal
-c, --color [mode] Output color: auto/always/never
-h, --help Show help options

应用程序开发

Linux平台用户空间的代码开发需求是各种各样,可以使用的框架和语言也是非常丰富的,针对蓝牙的应用也可以分为两种情况:

  1. 针对profile或GATT service有定制修改的需求;
  2. 完全基于profile或GATT service做应用开发;

从最上面的系统框图可以看到BlueZ协议栈跟内核的命令和数据交互完全依赖socket通路,所以针对情况1可以推荐使用基于socket的方式,而BlueZ协议栈对外提供了丰富的DBus接口,可以通过查看API文档就可以进行编程,同时不需要对蓝牙协议作具体了解。

基于socket方式编程可以参考BlueZ协议栈中提供的各个测试实例或者工具,例如想了解LE Audio的socket操作流程,可以参考tools/isotest.c。
基于DBus的编程也可以参考协议栈提供的测试用例,例如如何实现BLE Client可以参考test/example-gatt-client脚本,该脚本是基于Python开发,实现了GATT service中hr_service的发现和解析等功能。借助DBus API文档就可以快速实现功能开发。