#冲刺创作新星# #跟着小白一起学鸿蒙# [十三]简析蓝牙协议栈

时间:2022-11-11 15:56:00

作者:王石

在《#跟着小白一起学鸿蒙# [八] 蓝牙应用》我们熟悉了如何在开源鸿蒙开发蓝牙应用。在《#跟着小白一起学鸿蒙# [十一] WiFi&蓝牙子系统》,我们了解了各种系统内的蓝牙和WiFi框架,接下来我们就深入分析下开源鸿蒙的蓝牙结构和各层作用及工作内容。

概述

在开源鸿蒙的源码里和系统功能相关的部分大多都放在foundation这个文件夹里,而通讯相关的部分则是在communication这个文件夹内。我们本篇要分析的蓝牙功能就是在foundation/communication/bluetooth路径下,具体目录结构如下:

.
├── bundle.json
├── frameworks				//框架层
│   ├── inner
│   └── js
├── hisysevent.yaml
├── interfaces				//接口层
│   ├── inner_api
│   └── kits
├── LICENSE
├── README.md
├── README_zh.md
├── sa_profile				//系统能力配置
│   ├── 1130.xml
│   └── BUILD.gn
├── services				//服务层
│   ├── bluetooth
│   └── bluetooth_lite
└── test					测试代码
    ├── example
    ├── fuzztest
    ├── moduletest
    └── unittest

架构简析

  • 根据目录结构和内部文件及编译框架总结架构如下:

#冲刺创作新星# #跟着小白一起学鸿蒙# [十三]简析蓝牙协议栈

  • 接口层:对外提供js接口,采用d.ts定义,蓝牙文件夹内位置interfaces/kits/js具体存放路径在interface/sdk-js/api/@ohos.bluetooth.d.ts;对内提供c接口,可以供softbus,netmanager,audioframework三个子系统调用,蓝牙文件夹内位置interfaces/inner_api/include;
  • 框架层:分两个子层,NAPI框架实现层,蓝牙文件夹内位置foundation/communication/bluetooth/frameworks/js/napi,实现所有js层代码接口适配并调用innerapi的实现;蓝牙接口实现层,使用IPC架构同蓝牙服务层通信,将从NAPI收到的命令,或者别的子系统收到的命令经由IPC架构发送给服务层,并注册服务层observer,收听由服务层上报的事件;
  • 服务层:分三个子层,系统能力层,蓝牙文件夹内位置foundation/communication/bluetooth/services/bluetooth/server,实现蓝牙系统能力服务,接收从框架层经由IPC发送下来的命令,并收听蓝牙service传上来的消息并回传给蓝牙框架层;蓝牙服务层,蓝牙文件夹内位置foundation/communication/bluetooth/services/bluetooth/service,实现不同蓝牙能力的adapter(包括classic_adapter和ble_adapter),通过调用蓝牙协议栈实现蓝牙业务的逻辑能力;蓝牙协议栈,蓝牙文件夹内位置foundation/communication/bluetooth/services/bluetooth/stack,实现蓝牙协议包解析,打包以及蓝牙协议流程的处理,实现蓝牙host,蓝牙profile以及蓝牙链路和hci接口,最后通过使用蓝牙硬件驱动收发蓝牙原始数据;
  • 硬件驱动:预编译包,通过dlopen提供hci的底层接口,注册回调以及发送数据;

功能简析

NAPI ->> 蓝牙框架: 同进程,函数调用
蓝牙框架-->>蓝牙系统能力: 跨进程,IPC调用
Note right of 蓝牙系统能力: 通过samgr获取服务Proxy对象
蓝牙系统能力-->>蓝牙功能适配: 利用adapter和server调用功能
蓝牙功能适配->>蓝牙协议栈: c接口调用
蓝牙协议栈->>蓝牙驱动: dlopen加载驱动
蓝牙驱动--x 蓝牙协议栈: 注册,回调
蓝牙协议栈--x 蓝牙功能适配: observer回调
蓝牙功能适配--x 蓝牙系统能力: observer回调
蓝牙系统能力--x 蓝牙框架: observer proxy + stub
蓝牙框架--x NAPI: 注册,回调
  1. NAPI功能

    • HAP应用层通过@ohos.bluetooth.d.ts引用调用蓝牙接口,蓝牙接口包括bluetooth接口,BLE接口,profile接口。bluetooth接口包括经典蓝牙接口,BLE接口接口,和profile接口;目前支持的profile有A2dpSourceProfile,HandsFreeAudioGatewayProfile,HidHostProfile和PanProfile;
    • NAPI框架接口均通过DECLARE_NAPI_FUNCTION,js的回调也通过此接口经由传入回调函数指针实现;
    • NAPI层通过调用蓝牙框架层的BluetoothHost实现功能,通过将g_bluetoothHostObserver注册到框架层内部实现来获得消息回调;同时NAPI层提供g_Observer存储js层的回调函数,在收到框架层的回调后在g_Observer里查找对应的回调函数来实现应用通知;此对象因为是map结构体,所以一个应用只能注册一个并在应用内部自己处理;
  2. 蓝牙框架功能

    • 蓝牙框架提供cadapter接口和蓝牙框架具体实现(蓝牙NAPI层调用的BluetoothHost即在具体实现层);
    • cadapter实现c接口,通过BluetoothHost实现功能,其他外部模块均通过cadapter提供的c接口调用蓝牙能力;
    • 蓝牙框架内部实现层提供接口一一对应cadapter和NAPI接口。BluettoothHost内部通过SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager()接口得到samgr,然后通过BLUETOOTH_HOST_SYS_ABILITY_ID标识获取蓝牙服务对象,然后通过蓝牙服务对象通过IPC接口调用蓝牙服务功能;
    • 蓝牙框架内部提供RegisterObserver方式,允许其他层应用(比如软总线层通过调用cadapter接口GapRegisterCallbacks收听蓝牙的回调事件)收听蓝牙回调事件;
    • 蓝牙框架因为是动态库实现,所以如果有多处依赖则会生成多份实例,如NAPI和软总线都依赖蓝牙框架库,所以在系统里会有两份实例同时若产生蓝牙通知也会有两个进程同时收到消息;
  3. 蓝牙系统能力

    • 蓝牙系统能力通过继承SystemAbility,BluetoothHostStub两个类实现蓝牙服务能力并实现IPC进行通信;IPC通信部分的代码在蓝牙文件夹foundation/communication/bluetooth/services/bluetooth/ipc内,提供proxy和stub实现,即btipc_static.a静态库;
    • 蓝牙系统能力可视作蓝牙服务进程,提供包括蓝牙状态机,蓝牙adapter(classic,ble),蓝牙profile服务实例;
    • 蓝牙系统配置在foundation/communication/bluetooth/services/bluetooth/etc/init目录内,此部分内容会在制作镜像包时打包到系统文件内去;在蓝牙服务启动的时候会读取蓝牙配置(AdapterConfig::GetInstance()->Load(),ProfileConfig::GetInstance()->Load())并确定蓝牙的snooplog(协议栈输出文件)
    • 蓝牙系统能力内部使用Dispatcher模型执行任务事务,在Dispatcher对象内部它通过线程加任务队列的方式处理多条任务命令,目前实现方法为但线程依次处理队列内的事务
    • 蓝牙系统能力层通过permission_utils提供应用权限保护能力,服务调用功能时首先调用PermissionUtils::VerifyXXXBluetoothPermission(XXX包括,Use,Discover,Manage,Location),然后调用AuthCenter对应功能,最后调用PermissionHelper对应接口确认权限;在AuthCenter里内部定义了g_permissionAlwaysGrant全局变量,可以方便调试时拥有所有权限;
  4. 蓝牙协议栈

    • 蓝牙协议栈通过c接口对蓝牙服务层提供接口;
    • 蓝牙协议栈内部他提供任务队列方式处理蓝牙命令(GapRunTaskBlockProcess, GapRunTaskUnBlockProcess),分别对于蓝牙协议栈同步接口和异步接口;
    • 蓝牙协议栈内部也有层级,对上的是gap,中间是btm,对下的是hci,中间部分和其他蓝牙协议站定义的内容一致,如:att,avctp,avdtp,l2cap,rfcomm,sdp,smp
    • HCI层它通过g_hdiLib加载蓝牙驱动库libbluetooth_hdi_adapter.so,并通过加载蓝牙驱动接口(HdiInit,HdiSendHciPacket,HdiClose)实现蓝牙数据发送,蓝牙数据接收(g_hdiCallacks)

总结

  1. 蓝牙服务的结构也是所有开源鸿蒙的结构能力,大致流程均为:NAPI框架,系统服务框架,IPC框架,Observer框架,原生driver框架(其实可以采用HDF框架);
  2. 目前开源鸿蒙用的蓝牙协议站不是android,bluez,btstack这三种主流蓝牙协议栈,根据注释可得其参考《BLUETOOTH SPECIFICATION Version 5.0》实现;目前官方最新的协议栈是v5.3,参考链接如下:https://www.bluetooth.com/specifications/specs/core-specification-5-3/

附件链接:https://ost.51cto.com/resource/2381

本文作者:左翼风发

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​