基于Android8.1的博通蓝牙BCM89342的驱动移植记录
说明
本文档是基于Android 8.1版本的一款博通蓝牙的驱动移植全过程记录。本驱动是通过/dev/ttyS2和蓝牙进行通信。因为较android以前的版本有很大变化尤其是上层关于蓝牙协议栈的部分,以前老版本用Bluez再到后来的BlueDroid,到现在的集到/system/bt下。蓝牙的固件烧录方式也有变化,以前broadcom蓝牙用\system\bluetooth\brcm_patchram_plus目录下编译出的可执行程序brcm_patchram_plus进行.hcd格式的蓝牙固件烧录,现在android 8.1版本是由hardware/broadcom/libbt/src/下的工程进行固件烧录和pskey(蓝牙寄存器初始化配置)设置。
一 、软硬件平台
系统软件:android-8.1、linux-4.4.117
硬件平台:Ti jacinto6
蓝牙芯片:cyw89342(bcm89342)
二、蓝牙移植流程
2.1 kernel 对蓝牙的驱动支持配置
对蓝牙的驱动支持配置((UART)H4 、BCSP、HCILL等)要全部确保勾选:
Bluetooth subsystem support —>
RF switch subsystem support —>
2.2 kernel层编写蓝牙电源管理(bt rfkill)驱动
将蓝牙电源管理添加到linux rfkill(无线设备电源开关)子系统。主要是通过bt_reg_on 这个gpio管脚控制蓝牙的上电、下电。添加rfkill驱动后,就可以在命令行执行echo操作进行蓝牙的开启和关闭。因为蓝牙设备默认是 /sys/class/rfkill/rfkill0所以通过:cat /sys/class/rfkill/rfkill0/name 确认是否是自己驱动创建的rfkill设备,我这里是bcm89342_bt_rfkill。(详细驱动代码见下载文件)确认后可执行开关操作:
蓝牙上电: echo 1 > /sys/class/rfkill/rfkill0/state
蓝牙下电 : echo 0 > /sys/class/rfkill/rfkill0/state
rfkill驱动bcm89342_bt_rfkill.c部分源代码如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/rfkill.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#define BT_REG_ON 169
static int rfkill_set_power(void *data, bool blocked);
static struct platform_device *rfkill_pdev;
static struct rfkill *rfkill; /* for driver only */
static struct rfkill_ops rfkill_ops = {
.set_block = rfkill_set_power,
};
static int bt_gpio_init(void)
{
int ret;
ret = gpio_request_one(BT_REG_ON, GPIOF_OUT_INIT_LOW, "BT_REG_ON");
if (ret == 0) {
printk("Yangql obtain gpio for BT_REG_ON \n");
gpio_export(BT_REG_ON, 0);
} else {
pr_err("could not obtain gpio for BT_REG_ON\n");
}
#if 0
ret = gpio_request_one(BT_HOST_WAKE, GPIOF_IN, "BT_HOST_WAKE");
if (ret == 0) {
gpio_export(BT_HOST_WAKE, 0);
} else {
pr_err("could not obtain gpio for BT_HOST_WAKE\n");
}
#endif
return ret;
}
...
...
...
...
module_init(rfkill_init);
module_exit(rfkill_exit);
MODULE_DESCRIPTION(" bcm89342_bt_rfkill driver");
MODULE_AUTHOR("qinglong.yang");
MODULE_LICENSE("GPL");
2.3 android源码中把蓝牙这个宏定义给选上
BOARD_HAVE_BLUETOOTH := true
BOARD_HAVE_BLUETOOTH_BCM := true
BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := device/ti/jacinto6evm/bluetooth
2.4 hal层修改和移植
2.4.1 修改编译脚本将hardware/broadcom/libbt编译生成libbt-vendor.so到/out/product/…目录下。
具体改动如下:device/ti/jacinto6evm$ git diff device.mk
+# Bluetooth HAL
+PRODUCT_PACKAGES += \
+ libbt-vendor
+
+
2.4.2 关闭低功耗模式
其中最关键一点是LPM_SLEEP_MODE 要关闭,因为驱动里面目前没有添加BT_HOST_WAKE 和BT_DEV_WAKE, 无唤醒控制,暂时不支持低功耗模式,如果不关闭的会出现hci_reset命令 和其他的一些hci 命令发送超时的错误和一些BLE相关的错误。关键错误log如下:
06-25 13:23:58.600 411 1182 I : [0625/132358:INFO:btu_task.cc(107)] Bluetooth chip preload is complete
06-25 13:23:58.605 411 1182