文档内容拷贝自:
codebase_host/yunhal/opendoc/zh/yunhal_doc/bt.md
联系人:@梁操
本文档主要描述了YunOS下bluetooth的整体软件架构,对YunOS bluetooth Hardware Abstract Layer进行介绍,以帮助芯片厂商可以更加方便地适配YunOS.
YunOS 目前采用的bluetooth stack为bluez,所以建议芯片厂商在此基础上适配BlueTooth driver。
YunOS bluetooth stack 整体软件架构如下:
以上除了保证适配好driver以及相关download firmware外,还需要适配标准bluetooth yunhal API,保证通过dbus能与bluez正常通信。
目前YunOS上支持的profile如下:
Profile | 说明 |
---|---|
BTAL_PROFILE_A2DP | Advanced Audio Distribution Profile |
BTAL_PROFILE_AVRCP | Audio Video Remote Control Profile |
BTAL_PROFILE_GATT | Generic Attribute Profile |
BTAL_PROFILE_HID | Human Interface Device Profile |
BTAL_PROFILE_SOCKET | Socket透传 |
为了实现实现 Bluetooth HAL 分成两步走:
* 实现VendorModule接口和“继承”、实现VendorDevice接口。
* 实现bt_core.h中定义的yun_bluetooth_module接口。
域 | 类型 | 说明 |
---|---|---|
__version__ | uint32_t | 模块版本 |
__id__ | const char* | 模块标识 |
__name__ | const char * | 模块名 |
__author__ | const char * | 作者 |
__CreateDevice()__ | int32_t (*CreateDevice) (const struct __vendor_module_t* module, const char* deviceID, struct __vendor_device_t** device); | 工厂方法: “生产”VendorDevice |
一个 CreateDevice() 的实现示例如下:
static int32_t create_device(const VendorModule* module, const char* id,VendorDevice**dev) { device.common.module = module; *dev = (VendorDevice*)&device; return 0; }
声明模块入口:
BluetoothYunhalModule module = { .common = { .version = 1, .id = "Bluetooth", .name = "Bluetooth for C Yunhal", .author = "yunos", .CreateDevice = &create_device, }, } VENDOR_MODULE_ENTRY(module);
VendorDevice声明:
域 | 类型 | 说明 |
---|---|---|
version | uint32_t | 设备版本 |
id | const char* | 设备标识 |
module | const VendorModule* | 指向模块的指针 |
Destroy() | int32_t (*Destroy) (VendorDevice* device) | 析构函数 |
get_bluetooth_interface() | struct yun_bluetooth_module* get_bluetooth_interface () | 获取蓝牙接口 |
实现:
BluetoothYunhalDevice device = { .common = { .version = 1, .id = "device_bluetooth", .module = NULL, .Destroy = NULL, }, .get_bluetooth_interface = bluetooth_get_yunhal_interface } struct yun_bluetooth_module* bluetooth_get_yunhal_interface (){ return &yun_bluetooth_module; }
对于厂商为了接入到平台标准接口,目前定义出基本操作结构体yun_bluetooth_module(路径:codebase_host/yunhal/modules/include/yunhal)供厂商实现,厂商需要按照其定义进行实现,并且能够接收callback结构体yun_bt_callbacks_t,在不同场景下callback到上层。
struct yun_bluetooth_module:
域 | 定义 | 说明 |
---|---|---|
module_name | char *module_name | 模块名字 |
init | int (*init)(const yun_bt_callbacks_t *callback) | 初始化 |
deinit | int (*deinit)(void) | 清除接口 |
adapter_enable | int (*adapter_enable)(void); | 打开蓝牙 |
adapter_disable | int (*adapter_disable)(void); | 关闭蓝牙 |
adapter_get_property | int(*adapter_get_property)(btal_adapter_property_t type, btal_property_value *property); | 获取本地蓝牙属性 |
adapter_set_property | int(*adapter_set_property)(btal_adapter_property_t type, const btal_property_value *property); | 设置本地蓝牙属性 |
adapter_start_discovery | int(*adapter_start_discovery)(btal_discovery_mode_t mode); | 开始搜索 |
adapter_stop_discovery | int (*adapter_stop_discovery)(void); | 停止搜索 |
adapter_pair_device | int (*adapter_pair_device)(const btal_address_t *address); | 开始配对 |
adapter_unpair_device | int (*adapter_unpair_device)(const btal_address_t *address); | 解除配对 |
adapter_cancel_pairing | int (*adapter_cancel_pairing)(const btal_address_t *address); | 取消配对 |
adapter_pairing_request_reply | int (*adapter_pairing_request_reply)(const btal_address_t *address, btal_pairing_auth_t type, uint8_t accept, uint8_t code[16]); | 配对请求 |
device_get_property | int (*device_get_property)(const btal_address_t *address, btal_device_property_t type, btal_property_value *property); | 获取设备属性 |
device_set_property | int (*device_set_property)(const btal_address_t *address, btal_device_property_t type, const btal_property_value *property); | 设置设备属性 |
get_profile_interface | const void* (*get_profile_interface) (const char *profile_name); | 获取profile接口 |
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_PATH := usr/lib/yunhal LOCAL_SRC_FILES := \ src/bluez-core.c \ src/bluez-hid.c \ src/bluez-a2dp.c \ src/bluez-avrcp.c \ src/bluez-sock.c \ src/utils.c LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/src \ $(LOCAL_PATH)/bluez-lib/include \ $(LOCAL_PATH)/../../include \ $(yunhal-includes) \ $(base-includes) \ $(glib-includes) LOCAL_ADDITIONAL_DEPENDENCIES := libbluez-lib LOCAL_CFLAGS := -fPIC -Wall -Werror -D__YUNOS_SUPPORT__ LOCAL_LDFLAGS := -lglib-2.0 -lgobject-2.0 -lgio-2.0 -lbluez-lib –llog LOCAL_COMPILE_SHELL_CMD := \ mkdir -p $(XMAKE_ROOTFS)/usr/lib/yunhal/ && \ ln -s libbluez_plugin.so $(XMAKE_ROOTFS)/usr/lib/yunhal/libyunhal_Bluetooth.so LOCAL_MODULE := libyunhal_Bluetooth include $(BUILD_SHARED_LIBRARY)
为了保证第三方代码库功能完整性,基于gtest开发一套测试case,主要包括Bluetooth的初始化,Enable/disable、Set/Get Property、discovery,Repeate Enable/disable等进行自动化测试。对异步,同步调用等进行功能测试,验证BT stack到driver是否OK,对每一个测试用例进行单独测试,判断每一个case的状态以及执行命令是否正常 。
测试说明:
模块 | 测试用例 | 说明 |
---|---|---|
Adapter | AdapterEnableDisable | 测试初始化蓝牙stack,并测试异步调用打开关闭蓝牙。 |
Adapter | AdapterRepeatedEnableDisable | 连续多次打开关闭蓝牙,查看状态是否恢复正常。 |
Adapter | AdapterSetGetName | 设置蓝牙name,并获取设置之后的name。 |
Adapter | AdapterSetGetPairable | 为了让周围设备可以配对到本端蓝牙设备,开放其状态。 |
Adapter | AdapterSetGetDiscoveryTimeout | 设置被搜索的时间。 |
Adapter | AdapterCancelDiscovery | 扫描并立即停止扫描,判断BT芯片是否及时停止。 |
Adapter | AdapterStartDiscovery | 开始扫描,查看10s是否有搜索到设备。 |
使用adapter即可进行自动化测试Adapter所有的case,测试结果: