基于bluez的蓝牙ble开发
linux蓝牙协议栈bluez(https://github.com/bluez/bluez/tree/master),提供了丰富的蓝牙开发工具和示例。
bluez5主要提供基于HCI和基于DBUS的接口,基于HCI的接口主要用于更细致控制蓝牙硬件模块,而基于DBUS的接口提供大量的蓝牙上层协议,能更好的管理蓝牙。
轻量级开发:不使用glib、dbus,开发周边设备可以借鉴btmgmt.c和btgatt-server.c、btgatt-client.c。
重应用开发:使用glib、dbus开发的话,可以参考gatt-service.c。一般音频、文件传输基于此,提供了丰富接口和上层应用。
一、ble开发
蓝牙低功耗协议给设备定义了若干角色,或称工作模式。小程序蓝牙目前支持的有以下几种:
1) 中心设备/主机 (Central)/client
中心设备可以扫描外围设备,并在发现有外围设备存在后与之建立连接,之后就可以使用外围设备提供的服务(Service)。
一般而言,手机会担任中心设备的角色,利用外围设备提供的数据进行处理或展示等等。小程序提供低功耗蓝牙接口是默认设定手机为中心设备的。
2) 外围设备/从机 (Peripheral)/server
外围设备一直处于广播状态,等待被中心设备搜索和连接,不能主动发起搜索。例如智能手环、传感器等设备。
如果外围设备广播时被设置为不可连接的状态,也被称为广播模式 (Broadcaster),常见的例子是蓝牙信标 (Beacon) 设备。
ble client开发
一般 BLE(低功耗蓝牙)设备的连接流程可以分为以下几个步骤:
启动设备发现:通过 StartDiscovery 方法开始扫描周围的 BLE 设备。
监听设备发现信号:监听 InterfacesAdded 信号,以获取发现的设备对象路径。
停止设备发现:扫描到目标设备后,通过 StopDiscovery 方法停止扫描。
配对设备(可选):如果设备需要配对,可以调用 Pair 方法进行配对。
连接到设备:通过 Connect 方法连接到设备。
发现服务和特征:连接成功后,发现设备上的服务和特征。
操作特征:读取或写入特征,订阅通知等。
hciconfig hci0 reset hcitool -i hci0 lescan hcitool -i hci0 leinfo E0:E1:A9:3C:90:2B hcitool -i hci0 lecc E0:E1:A9:3C:90:2B hcitool -i hci0 ledc E0:E1:A9:3C:90:2B hcitool con ./btgatt-client -i hci0 -d E0:E1:A9:3C:90:2B
ble server开发
虽然bluez并没有给c提供直接可用的ble接口,但是通过分析源码和工具可以如下方式实现ble外围设备(server)供手机APP扫描传输数据。
hciconfig hci0 up hciconfig hci0 name "ble" hciconfig hci0 leadv btgatt-server -v -r // 开启health rate服务
# hciconfig
hci0: Type: Primary Bus: UART
BD Address: 63:E8:09:BF:10:A5 ACL MTU: 1021:8 SCO MTU: 240:3
UP RUNNING
RX bytes:744 acl:0 sco:0 events:51 errors:0
TX bytes:5366 acl:0 sco:0 commands:51 errors:0
btmgmt -i hci0 power off btmgmt power off btmgmt le on btmgmt bredr off btmgmt name mini_0002 btmgmt connectable on btmgmt power on btmgmt advertising on # btmgmt info hci0: Primary controller addr E0:E1:A9:3C:90:2B version 7 manufacturer 93 class 0x000000 supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr hs le advertising secure-conn debug-keys privacy static-addr phy-configuration current settings: powered connectable ssp br/edr le advertising secure-conn name ble_0000 short name
在bluez的根目录下有一个peripheral文件夹,里面实现了ble的peripheral角色(server),也就是包含和实现了gap profile和gatt server profile的功能,源码可以参考。
二、hci接口(旧)
HCI提供一套统一的方法来访问Bluetooth底层。
HCI编程就是调用bluez提供的HCI接口来进行编程,只不过编译的时候要注意把蓝牙库链接进去,即-lbluetooth。
HCI有很多命令,可以查看下/usr/include/bluetooth/hci_lib.h文件。
bluez源码中tools目录下的许多文件可以作为HCI编程的参考,例如tools/hcitool.c和tools/hciconfig.c等
HCI是应用程序跟蓝牙驱动进行交互的接口,Linux内核向应用程序提供一个AF_BLUETOOTH的socket来实现蓝牙Host和Controller的交互。
// lib/hci.c /* Open HCI device. * Returns device descriptor (dd). */ int hci_open_dev(int dev_id) { struct sockaddr_hci a; int dd, err; /* Check for valid device id */ if (dev_id < 0) { errno = ENODEV; return -1; } /* Create HCI socket */ dd = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); if (dd < 0) return dd; /* Bind socket to the HCI device */ memset(&a, 0, sizeof(a)); a.hci_family = AF_BLUETOOTH; a.hci_dev = dev_id; if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0) goto failed; return dd; failed: err = errno; close(dd); errno = err; return -1; } int hci_close_dev(int dd) { return close(dd); }
三、mgmt接口(新)
mgmt接口是什么,为什么要引入,参考:http://www.bluez.org/the-management-interface/
mgmt is a new interface for user space Bluetooth components (like bluetoothd) to talk to the kernel and it aims to replace the existing raw HCI sockets.
mgmt支持的api(commands和event),参考:doc/mgmt-api.txt。
所有mgmt命令都会产生event,而invalid lengths或unknown commands会生成command status response event;给invalid controller index发送commands生成command status event。
As a general rule all commands generate the events as specified below, however invalid lengths or unknown commands will always generate a Command Status response (with Unknown Command or Invalid Parameters status). Sending a command with an invalid Controller Index value will also always generate a Command Status event with the Invalid Index status code.
The Bluetooth management sockets can be created by setting the hci_channel member of struct sockaddr_hci to HCI_CHANNEL_CONTROL (3) when creating a raw HCI socket.
struct mgmt *mgmt_new_default(void) { struct mgmt *mgmt; union { struct sockaddr common; struct sockaddr_hci hci; } addr; int fd; fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI); if (fd < 0) return NULL; memset(&addr, 0, sizeof(addr)); addr.hci.hci_family = AF_BLUETOOTH; addr.hci.hci_dev = HCI_DEV_NONE; addr.hci.hci_channel = HCI_CHANNEL_CONTROL; if (bind(fd, &addr.common, sizeof(addr.hci)) < 0) { close(fd); return NULL; } mgmt = mgmt_new(fd); if (!mgmt) { close(fd); return NULL; } mgmt->close_on_unref = true; return mgmt; }
使用mgmt接口实现ble_server,思路如下(来自:[BlueZ5] 如何用MGMT接口实现ble slave)
[1] 如何实现开关蓝牙. [2] 如何实现广播,包含广播包和响应包的设定,以及广播参数设定等等。 [3] 如何实现GATT连接. [4] 如何实现服务注册,即收发数据. [5] 如何实现状态通知,包含连接成功,断开成功,timeout,terminate等等. [6] 如何实现更新连接参数,连接间隔设定等等。 需要指出,以上几点可归纳为如何两个文件以及kernel中node的设定等等。 [1][2] -->bluez-5.5x\tools\btmgmt.c [3][4][5] -->bluez-5.5x\tools\btgatt-server.c [6] -->部分可从btmgmt.c中获取
参考:
1. 低功耗蓝牙ble开发(一)——bluez介绍及源码分析
2. linux下BLE(低功耗蓝牙协议)C语言开发笔记(2)---ble蓝牙扫描-连接-读写