1. 简介
随着现代移动通信和物联网的快速发展,万物互联已经越来越成为一个基本需求,而近距离的无线通信更是在移动设备之间有着及其广泛的应用。蓝牙技术是一种无线数据和语音传输的开放式标准,它是基于低成本的近距离无线连接,为固定和移动设备建立通信的一种近距离无线技术连接。蓝牙技术正广泛运用于汽车领域、工业生产、医疗领域。
1.1 OpenHarmony架构图
蓝牙子系统所属的分布式软总线在整个OpenHarmony系统中的位置在如下红框处:
2. 基础知识
2.1 蓝牙概述
蓝牙是一种支持设备短距离通信(一般10m内)的无线电技术,能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多具有蓝牙模块的设备之间进行短距离无线信息交换,使得数据传输变得更加迅速高效。它是爱立信、IBM等5家公司在1998年联合推出的一项无线通信技术,随后成立的蓝牙技术特殊兴趣组织(SIG)来负责该技术的开发和技术协议的制定,如今全世界已有1800多家公司加盟该组织。
蓝牙工作在全球通用的2.4GHz ISM(即工业、科学、医学)频段,使用IEEE802.15协议。作为一种的短距离无线通信技术,在现在的生活中,正扮演着极其重要的角色。当然,在操作系统中,蓝牙模块正扮演着必不可少的基础功能。
2.2 蓝牙架构图
在蓝牙技术中,有Application,Host和Controller三个角色。这三个角色可以位于不同的设备,也可以位于同一个设备上。在一个系统中,Host只有一个,但Controller可以一个也可以有多个。
Application:由不同的Profiles来限定,蓝牙系统中的应用程序互操作性是由profiles完成的。profiles定义了蓝牙系统中从PHY到L2CAP以及核心规范之外的任何其他协议所需的每层功能和特性。配置文件定义了层之间的垂直交互以及设备之间特定层的点对点交互。此外,应用程序的行为和数据格式也由profiles定义。
Host:负责在逻辑链路的基础上,进行更为友好的封装,这样就可以屏蔽掉蓝牙技术的细节,让Bluetooth Application更为方便的使用。
Controller:负责定义RF、Baseband等底层的规范,并在这之上抽象出用于通信的逻辑链路。
2.3 蓝牙子系统代码架构图
下图为OpenHamony蓝牙子系统的代码结构,图中可以看到从上层到底层的整个过程。
APP:蓝牙应用程序,即使用蓝牙API的程序,一般是在设备的settings里实现。通过调用bluetooth的interfaces下的对应接口来实现应用程序的功能。
bluetooth:蓝牙框架层,主要包括interfaces和services,本篇主要针对该部分做详细解读。
HDF:硬件驱动框架,bluetooth的设备驱动的开发是基于该框架的基础上,结合操作系统适配层(OSAL)和平台驱动接口(比如I2C/SPI/UART总线等平台资源)能力,屏蔽不同操作系统和平台总线资源差异,实现bluetooth驱动"一次开发,多系统部署"的目标。
HardWare:各类具有蓝牙模块硬件实体的硬件设备,如移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备。
2.4 蓝牙子系统代码目录
bluetooth 框架层的代码目录结构如下:
/foundation/communication/bluetooth
├── interfaces # 接口代码
│ └── innerkits # 系统服务接口存放目录
│ ├── native\_c # C接口存放目录
│ │ └── include # C接口定义目录
│ └── native\_cpp # C++接口存放目录
│── sa\_profile # 蓝牙服务定义目录
│── services # 蓝牙服务代码目录
└── LICENSE # 版权声明文件
interfaces,负责向上层应用程序提供相应的功能接口,使应用开发者实现具体蓝牙业务功能,目前只提供c/c++接口。
services负责interfaces接口的实现。系统提供C/C++接口定义及服务和协议栈的代码,目前提供的只有BLE相关的接口,包括BLE设备GATT相关的操作,以及BLE广播、扫描等功能,其它A2DP,AVRCP,HFP等相关接口在后续增量发布。
services部分主要是通过bluetooth_standard目录下的相关模块来实现interfaces接口。相关的模块有common、hardware、external、etc、ipc、stack、service、server。模块间利用c++的相关特性,完成了各自的分层功能,最终实现了蓝牙不同协议的场景功能。代码架构如下:
└── services
├── bluetooth
│ └── BUILD.gn
└── bluetooth\_standard
├── common #定义蓝牙相关的数据结构,供其他子模块调用
├── etc #蓝牙服务的配置文件存放处,蓝牙设备、profile的配置文件
├── external #扩展目录
├── hardware #定义HCI的相关接口供其他子模块调用
├── ipc #进程间通信,不同协议的proxy和stub之间的数据传递等
├── server #主从模式的server端代码存放处
├── service #不同协议的服务接口及实现,供server调用
└── stack #常规stack、list、queue,信号量,互斥量的操作,不同协议栈的相关数据结构的创建、初始化等
2.5 蓝牙子系统协议
蓝牙相关协议栈在stack目录下按照目录进行协议分类,如下:
└── stack
└── src
├── att 属性协议
├── avctp 音视频控制传输协议
├── avdtp 音视频分发协议
├── btm (Bluetooth manage蓝牙配对与链路管理)
├── gap (Generic Access Profile通用访问协议)
├── hci 主机控制接口协议
├── l2cap 逻辑链路控制和适配协议
├── rfcomm 串口仿真协议
├── sdp 服务发现协议
└── smp(Security Manage Protoco蓝牙安全管理协议)
3. 源码分析
@ohos.bluetooth.d.ts文件提供了供应用侧调用的接口,我们以最常用的打开蓝牙开关的操作来展示代码的时序流程。
应用侧调用了@ohos.bluetooth.d.ts中示例的enableBluetooth()接口来开启蓝牙,如下:
function enableBluetooth(): boolean;
实际上d.ts中的接口在代码中仅仅只是用来示例,真正起作用的是NAPI的接口EnableBluetooth,该接口对应的文件为napi_bluetooth_host.cpp,如下:
napi\_value EnableBluetooth(napi\_env env, napi\_callback\_info info)
{
HILOGI("EnableBluetooth start");
BluetoothHost \*host = &BluetoothHost::GetDefaultHost();
bool enabled = host-\>EnableBt();
enabled |= host-\>EnableBle();
napi\_value result = nullptr;
napi\_get\_boolean(env, enabled, &result);
HILOGI("EnableBluetooth end");
return result;
}
napi接口调用的是BluetoothHost中的EnableBt()和EnableBle()方法分别打开经典蓝牙和低功耗蓝牙开关。我们以打开低功耗蓝牙为例分析代码流程。
3.1 打开低功耗蓝牙代码流程
BluetoothHost::EnableBle()接口如下:
bool BluetoothHost::EnableBle()
{
HILOGD("BluetoothHost::Enable BLE starts");
if (!pimpl) {
HILOGE("BluetoothHost::Enable BLE fails: no pimpl");
return false;
}
if (pimpl-\>proxy\_ == nullptr) {
HILOGE("BluetoothHost::Enable fails: no proxy");
return false;
}
return pimpl-\>proxy\_-\>EnableBle();
}