背景:
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/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;
}