基于Android8.1的博通bcm89342蓝牙驱动的驱动移植记录

基于Android8.1的博通蓝牙BCM89342的驱动移植记录

  • 说明
    • 一 、软硬件平台
    • 二、蓝牙移植流程
      • 2.1 kernel 对蓝牙的驱动支持配置
      • 2.2 kernel层编写蓝牙电源管理(bt rfkill)驱动
      • 2.3 android源码中把蓝牙这个宏定义给选上
      • 2.4 hal层修改和移植
      • 2.5 system/bt目录下相关源代码修改
    • 三 系统集成
      • 3.1 对主机端和蓝牙通信串口、固件存放路径等进行配置
      • 3.2 添加蓝牙启动脚本文件 init_bt_xxx.rc
      • 3.3 添加 bt_vendor.conf 到终端设备 jacinto6evm:/etc/bluetooth目录下
    • 结尾

说明

本文档是基于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 —>
基于Android8.1的博通bcm89342蓝牙驱动的驱动移植记录_第1张图片
RF switch subsystem support —>

基于Android8.1的博通bcm89342蓝牙驱动的驱动移植记录_第2张图片

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 I         : [0625/132358:INFO:gatt_api.cc(1004)] GATT_Register
06-25 13:23:58.605   411  1182 I         : [0625/132358:INFO:gatt_api.cc(1027)] allocated gatt_if=1
06-25 13:23:58.606   411  1182 I         : [0625/132358:INFO:gatt_api.cc(207)] GATTS_AddService
06-25 13:23:58.606   411  1182 I         : [0625/132358:INFO:gatt_api.cc(317)] GATTS_AddService: service parsed correctly, now starting
06-25 13:23:58.606   411  1182 E         : [0625/132358:ERROR:gatt_attr.cc(301)] yangql gatt_profile_db_init:  gatt_if=1
06-25 13:23:58.608   411  1182 I         : [0625/132358:INFO:gatt_api.cc(1004)] GATT_Register
06-25 13:23:58.608   411  1182 I         : [0625/132358:INFO:gatt_api.cc(1027)] allocated gatt_if=2
06-25 13:23:58.608   411  1182 I         : [0625/132358:INFO:gatt_api.cc(207)] GATTS_AddService
06-25 13:23:58.608   411  1182 I         : [0625/132358:INFO:gatt_api.cc(317)] GATTS_AddService: service parsed correctly, now starting
06-25 13:23:58.608   411  1183 I bt_osi_thread: run_thread: thread id 1183, thread name btu message loop started
06-25 13:23:58.609   411  1184 I bt_osi_thread: run_thread: thread id 1184, thread name module_wrapper started
06-25 13:24:02.595   411   629 V BluetoothAdapterState: PendingCommand - transient state(s): isBleTurningOn
06-25 13:24:02.595   411   629 D BluetoothAdapterState: Current state: PENDING_COMMAND, message: 101
06-25 13:24:02.595   411   629 E BluetoothAdapterState: Error enabling Bluetooth (enable timeout)
06-25 13:24:02.595   411   629 D BluetoothAdapterService: stopProfileServices() - No profiles services to stop or already stopped.
06-25 13:24:02.595   411   629 D BluetoothAdapterService: stopGattProfileService()
06-25 13:24:02.595   411   629 D BluetoothAdapterService: setProfileServiceState() - Stopping service com.android.bluetooth.gatt.GattService
06-25 13:24:02.596   411   629 D BluetoothAdapterProperties: Setting state to 10
06-25 13:24:02.596   411   411 D BtGatt.DebugUtils: handleDebugAction() action=null
06-25 13:24:02.596   411   629 I BluetoothAdapterState: Bluetooth adapter state changed: 14-> 10
06-25 13:24:02.596   411   411 D BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@31ef051
06-25 13:24:02.596   411   629 D BluetoothAdapterService: updateAdapterState() - Broadcasting state to 1 receivers.
06-25 13:24:02.597   411   629 I BluetoothAdapterState: Entering OffState
06-25 13:24:02.597   316   339 D BluetoothManagerService: MESSAGE_BLUETOOTH_STATE_CHANGE: BLE_TURNING_ON > OFF
06-25 13:24:02.597   316   339 D BluetoothManagerService: Bluetooth is complete send Service Down
06-25 13:24:02.597   316   339 D BluetoothManagerService: Broadcasting onBluetoothServiceDown() to 6 receivers.
06-25 13:24:02.597   411   427 D BluetoothAdapter: onBluetoothServiceDown: com.android.bluetooth.btservice.AdapterService$AdapterServiceBinder@9a25cbc
06-25 13:24:02.597   316   339 D BluetoothAdapter: onBluetoothServiceDown: android.bluetooth.IBluetooth$Stub$Proxy@bb7f3a8
06-25 13:24:02.597   553   767 D BluetoothAdapter: onBluetoothServiceDown: android.bluetooth.IBluetooth$Stub$Proxy@533586b
06-25 13:24:02.597   316   339 D BluetoothManagerService: unbindAndFinish(): android.bluetooth.IBluetooth$Stub$Proxy@bb7f3a8 mBinding = false mUnbinding = false
06-25 13:24:02.598   440   801 D BluetoothAdapter: onBluetoothServiceDown: android.bluetooth.IBluetooth$Stub$Proxy@953c236
06-25 13:24:02.598  1038  1052 D BluetoothAdapter: onBluetoothServiceDown: android.bluetooth.IBluetooth$Stub$Proxy@6cfd178
06-25 13:24:02.598   465   512 D BluetoothAdapter: onBluetoothServiceDown: android.bluetooth.IBluetooth$Stub$Proxy@9a25cbc
06-25 13:24:02.598   411   411 D BtGatt.GattService: Received stop request...Stopping profile...
06-25 13:24:02.600   316   339 D BluetoothManagerService: Sending BLE State Change: BLE_TURNING_ON > OFF
06-25 13:24:02.600   411   411 D BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@31ef051
06-25 13:24:02.601   411   411 D BluetoothAdapterService: onUnbind() - calling cleanup
06-25 13:24:02.601   411   411 D BluetoothAdapterService: cleanup()
06-25 13:24:02.602   411   411 W BluetoothSdpJni: Cleaning up Bluetooth SDP Interface...
06-25 13:24:02.603   411   411 W BluetoothSdpJni: Cleaning up Bluetooth SDP object
06-25 13:24:02.603   411   411 D BluetoothAdapterService: cleanup() - Cleaning up adapter native
06-25 13:24:02.609   411   637 E bt_hci  : yangql command_timed_out: 1 commands pending response
06-25 13:24:02.609   411   637 E bt_hci  : command_timed_out:yangql  Waited 3999 ms for a response to opcode: 0xc03 *matches timer*
06-25 13:24:02.609   411   637 E bt_hci  : command_timed_out:yangql  Size 3 Hex 03 0c 00
06-25 13:24:02.609   411   637 E bt_hci  : command_timed_out: yangql requesting a firmware dump.
06-25 13:24:02.610   411   637 E bt_hci  : command_timed_out yangql restarting the Bluetooth process.
06-25 13:24:02.612   411   727 W bt_hci  : filter_incoming_event command complete event with no matching command (opcode: 0xfd5b).
06-25 13:24:07.610   411   637 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 637 (alarm_default_c), pid 411 (droid.bluetooth)

针对性修改关闭低功耗模式hardware/broadcom/libbt/include/bt_vendor_brcm.h如下:
$ cd hardware/broadcom/libbt
$ git diff include/bt_vendor_brcm.h

diff --git a/include/bt_vendor_brcm.h b/include/bt_vendor_brcm.h
index 545e76e..50f5e34 100644
--- a/include/bt_vendor_brcm.h
+++ b/include/bt_vendor_brcm.h
@@ -106,7 +106,8 @@
     1: UART with Host wake/BT wake out of band signals
 */
 #ifndef LPM_SLEEP_MODE
-#define LPM_SLEEP_MODE                  1
+//#define LPM_SLEEP_MODE                  1
+#define LPM_SLEEP_MODE                  0 //qinglong.yang modify 

2.5 system/bt目录下相关源代码修改

由于Ti jacinto6没有rtc,所以会报如下错误:
所以对/system/bt/osi/src/alarm.cc进行如下修改,强制将CLOCK_ID_ALARM属性改为CLOCK_ID_ALARM:
static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
//#if (KERNEL_MISSING_CLOCK_BOOTTIME_ALARM == TRUE) //remove by qinglong.yang
static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME;
//#else //remove by qinglong.yang
// static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME_ALARM; //remove by qinglong.yang
//#endif //remove by qinglong.yang

三 系统集成

3.1 对主机端和蓝牙通信串口、固件存放路径等进行配置

通过修改 hardware/broadcom/libbt/includ/下vnd_jacinto6evm.txt进行配置,并把BCM4349B1.hcd格式的蓝牙固件放到添加到源代码相应位置,系统编译后会放在system/vendor/firmware/下。

1 #Set baudrate to 3000000
 2 UART_TARGET_BAUD_RATE=3000000
 3 BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyS2"
 4 FW_PATCHFILE_LOCATION = "/system/vendor/firmware"
 5 #LPM_IDLE_TIMEOUT_MULTIPLE = 5
 6 SCO_USE_I2S_INTERFACE = TRUE
 7 BTVND_DBG = TRUE
 8 BTHW_DBG = TRUE
 9 VNDUSERIAL_DBG = TRUE
10 UPIO_DBG = TRUE

3.2 添加蓝牙启动脚本文件 init_bt_xxx.rc

    chown bluetooth bluetooth /system/etc/bluetooth   #设备该目录有蓝牙权限
    setprop ro.bt.bdaddr_path "/system/etc/bluetooth/bdaddr"  #设置蓝牙地址路径
    chmod 0666 /sys/class/rfkill/rfkill0/state                      #rfkill文件具有可读可写权限
    chmod 0666 /sys/class/rfkill/rfkill0/type
    chmod 0666 /dev/ttyS2
    chown bluetooth bluetooth /sys/class/rfkill/rfkill0/state #rfkill文件具有蓝牙权限
    chown bluetooth bluetooth /sys/class/rfkill/rfkill0/type

3.3 添加 bt_vendor.conf 到终端设备 jacinto6evm:/etc/bluetooth目录下

# UART device port where Bluetooth controller is attached
  2 UartPort = /dev/ttyS2
  3 
  4 # Firmware patch file location
  5 FwPatchFilePath = /system/vendor/firmware
  6 
  7 #Firmware name
  8 FwPatchFileName = BCM4349B1.hcd

结尾

按照如上步骤操作后,bcm89342蓝牙如下图(名字为Jacinto6)能够正常使用。
蓝牙名字:Jacinto6
设备地址:22:22:67:c6:69

你可能感兴趣的:(驱动)