Android 11:[email protected]蓝牙架构分析

介绍结

参考:蓝牙  |  Android 开源项目  |  Android Open Source Projecticon-default.png?t=M85Bhttps://source.android.com/docs/core/connect/bluetooth

蓝牙应用通过 Binder 与蓝牙进程进行通信。蓝牙进程使用 JNI 与蓝牙堆栈通信,并向开发者提供对各种蓝牙配置文件的访问权限。下图显示了蓝牙堆栈的常规结构:

应用框架

处于应用框架级别的是应用代码,它使用 android.bluetooth API 与蓝牙硬件进行交互。此代码在内部通过 Binder IPC 机制调用蓝牙进程。

蓝牙系统服务

蓝牙系统服务(位于 packages/apps/Bluetooth 中)被打包为 Android 应用,并在 Android 框架层实现蓝牙服务和配置文件。此应用通过 JNI 调用原生蓝牙堆栈。

JNI

与 android.bluetooth 相关联的 JNI 代码位于 packages/apps/Bluetooth/jni 中。当发生特定蓝牙操作时(例如发现设备时),JNI 代码会调用蓝牙堆栈。

蓝牙堆栈

AOSP 中提供了默认蓝牙堆栈(位于 system/bt 中)。该堆栈实现常规蓝牙 HAL,并通过扩展程序和更改配置对其进行自定义。

供应商实现

供应商设备使用硬件接口设计语言 (HIDL) 与蓝牙堆栈交互

HIDL

HIDL 定义了蓝牙堆栈和供应商实现之间的接口。如需生成蓝牙 HIDL 文件,请将蓝牙接口文件传入 HIDL 生成工具中。接口文件位于 hardware/interfaces/bluetooth 中。

蓝牙堆栈开发

Android 蓝牙堆栈是一个完全限定的蓝牙堆栈。限定列表位于蓝牙 SIG 网站上的 QDID 169365 下。

核心蓝牙堆栈位于 [system/bt](https://android.googlesource.com/platform/system/bt/+/master) 中。开发工作在 AOSP 中进行,欢迎贡献内容。

Android Bluetooth Stack代码具体实现

Android蓝牙协议栈的实现在system/bt目录

应用框架 android.bluetooth

以下类和接口 是为APP 提供的API,在API内部通过Binder 机制向下调用

Interfaces

BluetoothAdapter.LeScanCallback Callback interface used to deliver LE scan results.
BluetoothProfile Public APIs for the Bluetooth Profiles.
BluetoothProfile.ServiceListener An interface for notifying BluetoothProfile IPC clients when they have been connected or disconnected to the service.

Class

BluetoothA2dp This class provides the public APIs to control the Bluetooth A2DP profile.
BluetoothAdapter Represents the local device Bluetooth adapter.
BluetoothAssignedNumbers Bluetooth Assigned Numbers.
... ...

蓝牙系统服务

 

代码位置:/aosp/packages/apps/Bluetooth/ ,这个文件夹中的代码实现了蓝牙服务和配置文件,并且最后编译时打包成一个APP,这个APP通过JNI调用蓝牙堆栈

JNI

"Bluetooth" 应用程序调用的JNI 位于/aosp/packages/apps/Bluetooth/jni 中。

 

JNI 负责调用原生的蓝牙协议栈。

蓝牙堆栈

蓝牙堆栈代码位于/aosp/system/bt 中

 

这层的代码通过调用hal 层代码 来调用底层硬件

因此厂商就可以通过HIDL 接口 来对接自己的硬件设备。

HDIL

hidl 接口代码位于/hardware/interfaces/bluetooth

我们就可以按照HIDL 实现自己的接口了

厂商蓝牙协议栈

已经集成到aosp源码中的厂商蓝牙代码定义在/aosp/hardware中

 

 

 

以瑞昱(realtek)为例

对于蓝牙厂商来说必须提供一个名字为 libbt-vendor.so的库文件,这个文件的接口在

/aosp/hareware/interfaces/bluetooth/1.0/default/bt_vendor_lib.h中定义好了,aosp 并没有实现,需要厂商提供这个文件的实现方法。

 

bt_vendor_lib.h源码:

#ifndef BT_VENDOR_LIB_H
#define BT_VENDOR_LIB_H

#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/** Struct types */

/** Typedefs and defines */

/** Vendor specific operations OPCODE */
typedef enum {
  /*  [operation]
   *      Power on or off the BT Controller.
   *  [input param]
   *      A pointer to int type with content of bt_vendor_power_state_t.
   *      Typecasting conversion: (int *) param.
   *  [return]
   *      0 - default, don't care.
   *  [callback]
   *      None.
   */
  BT_VND_OP_POWER_CTRL,
...

} bt_vendor_opcode_t;
...
/** Define HCI channel identifier in the file descriptors array
    used in BT_VND_OP_USERIAL_OPEN operation.
 */
typedef enum {
  CH_CMD,      // HCI Command channel
  CH_EVT,      // HCI Event channel
  CH_ACL_OUT,  // HCI ACL downstream channel
  CH_ACL_IN,   // HCI ACL upstream channel

  CH_MAX  // Total channels
} bt_vendor_hci_channels_t;
...
/*
 * Bluetooth Host/Controller Vendor callback structure.
 */

/* vendor initialization/configuration callback */
typedef void (*cfg_result_cb)(bt_vendor_op_result_t result);

/* datapath buffer allocation callback (callout)
 *
 *  Vendor lib needs to request a buffer through the alloc callout function
 *  from HCI lib if the buffer is for constructing a HCI Command packet which
 *  will be sent through xmit_cb to BT Controller.
 *
 *  For each buffer allocation, the requested size needs to be big enough to
 *  accommodate the below header plus a complete HCI packet --
 *      typedef struct
 *      {
 *          uint16_t          event;
 *          uint16_t          len;
 *          uint16_t          offset;
 *          uint16_t          layer_specific;
 *      } HC_BT_HDR;
 *
 *  HCI lib returns a pointer to the buffer where Vendor lib should use to
 *  construct a HCI command packet as below format:
 *
 *  --------------------------------------------
 *  |  HC_BT_HDR  |  HCI command               |
 *  --------------------------------------------
 *  where
 *      HC_BT_HDR.event = 0x2000;
 *      HC_BT_HDR.len = Length of HCI command;
 *      HC_BT_HDR.offset = 0;
 *      HC_BT_HDR.layer_specific = 0;
 *
 *  For example, a HCI_RESET Command will be formed as
 *  ------------------------
 *  |  HC_BT_HDR  |03|0c|00|
 *  ------------------------
 *  with
 *      HC_BT_HDR.event = 0x2000;
 *      HC_BT_HDR.len = 3;
 *      HC_BT_HDR.offset = 0;
 *      HC_BT_HDR.layer_specific = 0;
 */
typedef void* (*malloc_cb)(int size);
typedef void (*mdealloc_cb)(void* p_buf);
typedef void (*tINT_CMD_CBACK)(void* p_mem);
...
/*
 * Bluetooth Host/Controller VENDOR Interface
 */
typedef struct {
  /** Set to sizeof(bt_vndor_interface_t) */
  size_t size;

  /*
   * Functions need to be implemented in Vendor libray (libbt-vendor.so).
   */

  /**
   * Caller will open the interface and pass in the callback routines
   * to the implemenation of this interface.
   */
  int (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char* local_bdaddr);

  /**  Vendor specific operations */
  int (*op)(bt_vendor_opcode_t opcode, void* param);

  /** Closes the interface */
  void (*cleanup)(void);
} bt_vendor_interface_t;


 

通过代码可以知道,厂商最终只需要实现

/* Entry point of DLib --
 *      Vendor library needs to implement the body of bt_vendor_interface_t
 *      structure and uses the below name as the variable name. HCI library
 *      will use this symbol name to get address of the object through the
 *      dlsym call.
 */
extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;

通过这个结构体,蓝牙协议栈将厂商的实现的方法导入到协议栈内部。

[email protected]通过vendor_interface.cc 中“VendorInterface::Open ”函数加载 这个lib

 

 

 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>