背景:
BT chip:RTL8761AUV
平台:RK3399
KERNEL版本:kernel4.4
Android版本:android7.1
蓝牙框架结构
Android4.2 之后采用 bluedroid 作为协议;整体由 bluetooth.apk,bluedroid ,libbt-vendor 三个 部 分 组 成 ; bluetooth.apk 作 为 蓝 牙 服 务 进 程 , 通 过 libblueooth_jni 层 获 取bluetooth*.default.so 提 供 的bt_interface_t 控 制 接 口 并 状 态 与 数 据 回 调 注 册 到bluetooth*.default.so;完成对蓝牙模块的控制与数据接收;libbt-vendor 完成对蓝牙模块硬件初始化与控制(物理通讯接口初始化,固件下载,供电控制)RK平台通过判断wifi+Bt模块的type,在libbuetooth_jni层选择加载不同适配厂商协议栈;并在libbt-hci中根据模块类型加载不同厂家模块的libbt-vendor*.so,完成动态适配模块。
其中 RK 平台通过判断模块的 type,在 libbuetooth_jni 层选择加载不同适配厂商协议栈;并
在 libbt-hci 中根据模块类型加载不同厂家模块的 libbt-vendor*.so,完成动态适配模块。
USB蓝牙调试浅析:
kernel部分:
1、将Realtek提供的蓝牙驱动文件rtk_btusb.h和rtk_btusb.c拷贝到kernel的drivers/bluetooth/目录下,
drivers/bluetooth/rtk_btusb.c
drivers/bluetooth/rtk_btusb.h
修改kernel的drivers/bluetooth/目录下的文件“Kconfig” and “Makefile”,
在 Kconfig 文件中增加 BT_RTKBTUSB 的选项:
config BT_RTKBTUSB
tristate "RTK HCI USB driver"
depends on USB
help
RTK Bluetooth HCI USB driver
在 Makefile 文件中添加目标文件 rtk_btusb.o,
obj-$(CONFIG_BT_RTKBTUSB) += rtk_btusb.o
2、平台对应的defconfig文件添加Realtek BT Chip支持的宏定义,或者在 kernel 中make menuconfig选中rtk_btusb driver相关的宏。
CONFIG_BT_RTKBTUSB=y
驱动加载成功会有对应设备节点:
rk3399_all:/ # ls dev/rtk_btusb
dev/rtk_btusb
device/rockchip/common目录:
添加一些节点的权限和一些宏控开关
在device/rockchip/common/init.connectivity.rc文件(一般rk平台代码已经添加):
4 # for bluetooth
5 # change back to bluetooth from system
6 chown bluetooth net_bt_stack /data/misc/bluetooth
7 mkdir /data/misc/bluedroid 0770 bluetooth net_bt_stack
8 # bluetooth LPM
9 chown bluetooth net_bt_stack /proc/bluetooth/sleep/lpm
10 chown bluetooth net_bt_stack /proc/bluetooth/sleep/btwrite
11
12 # USB device
13 insmod /system/lib/modules/rtk_btusb.ko
14 chmod 0660 /dev/rtk_btusb
15 chown bluetooth net_bt_stack /dev/rtk_btusb
16
17 # for 8897 bt
18 # insmod /system/lib/modules/mbt8xxx.ko
19
20 # bluetooth MAC address programming
21 chown bluetooth net_bt_stack ro.bt.bdaddr_path
22 chown bluetooth net_bt_stack /system/etc/bluetooth
23 chown bluetooth net_bt_stack /data/misc/bluetooth
24 setprop ro.bt.bdaddr_path "/data/misc/bluetooth/bdaddr"
在device/rockchip/common/wifi_bt_common.mk文件(一般rk平台代码已经添加):
BOARD_HAVE_BLUETOOTH_RTK := true
BOARD_HAVE_BLUETOOTH_RTK_COEX := true
hardware/realtek目录:
HAL层添加蓝牙协议栈的代码和对应的libbt-vendor.so的源代码,libbt-vendor完成对蓝牙模块硬
件初始化与控制(物理通讯接口初始化,固件下载,供电控制)
固件所在目录:
hardware/realtek/rtkbt/system/etc/firmware/rtl8761au_fw
最终会通过mk文件hardware/realtek/rtkbt/rtkbt.mk拷贝到机器的以下目录,打开蓝牙的时候会去加载fw:
system/etc/firmware/
system/bt目录:
蓝牙协议栈代码和加载libbt-vendor.so库的代码,通常情况下建议使用原生的蓝牙协议栈【在system/bt目录】,如果有厂商的协议栈对原生协议栈做过较大的修正而必须使用厂商自己的协议栈的情况下在 jni 层完成对不同厂商协议栈【一般在hardware目录下】的加载
packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
classInitNative
char type[64];
check_wifi_chip_type_string(type);
if (!strncmp(type, "RTL", 3)) { //加载rtl厂商对应的蓝牙协议栈的库:bluetooth_rtk.default.so
ALOGD("%s, load %s.default.so", __func__, BT_STACK_RTK_MODULE_ID);
err = hw_get_module(BT_STACK_RTK_MODULE_ID, (hw_module_t const**)&module);
} else { //加载原生的蓝牙协议栈的库:bluetooth.default.so
ALOGD("%s, load %s.default.so", __func__, id);
err = hw_get_module(id, (hw_module_t const**)&module);
}
//BT_STACK_RTK_MODULE_ID在./hardware/libhardware/include/hardware/bluetooth.h定义
部分HAL层对应的libbt-vendor.so的源代码浅析:
首先是bluedroid 蓝牙协议栈libbt-hci【原生蓝牙协议栈】通过system/bt/hci/src/vendor.c的vendor_open接口调用->dlopen加载libbt-vendor.so库文件,
加载libbt-vendor.so库之后调用以下接口
// Entry point of DLib
const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
sizeof(bt_vendor_interface_t),
init,
op,
cleanup
};
调用init
-> userial_vendor_init
->snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", BLUETOOTH_UART_DEVICE_PORT);
/*BLUETOOTH_UART_DEVICE_PORT在
hardware/realtek/rtkbt/code/libbt- vendor/usb/include/vnd_buildcfg.h中宏定义,
即蓝牙设备节点:/dev/rtk_btusb初始化蓝牙设备节点等*/
然后调用op,
在static int op(bt_vendor_opcode_t opcode, void *param)中:
case BT_VND_OP_USERIAL_OPEN: //打开蓝牙设备
->fd = userial_vendor_open();
case BT_VND_OP_FW_CFG: //加载蓝牙固件(fw文件)
->retval = ioctl(vnd_userial.fd, DOWN_FW_CFG, NULL);
case BT_VND_OP_USERIAL_CLOSE:
->userial_vendor_close(); //关闭蓝牙设备
调用cleanup
/** Closes the interface */
static void cleanup( void )
{
BTVNDDBG("cleanup");
bt_vendor_cbacks = NULL;
}