hdev->open = btusb_open;
hdev->close = btusb_close;
hdev->flush = btusb_flush;
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
……
err = hci_register_dev(hdev);
然后在hdev->open 的时候,在btusb_open中进行fw下载和参数配置的工作,这时蓝牙就可以正常工作了。下载的fw和配置文件通过内核的int request_firmware(const struct firmware **fw, const char *name, struct device *device)函数获取,对于需要获取的文件,只需要提供文件名,该函数会自动搜索系统部分路径,其中就包含“/lib/firmware/”,所以只要把fw及配置文件放到“/lib/firmware/”目录下即可。同时usb保证了传输的可靠性,所以也不需要什么h4、h5协议了。
从上面可以看出,对于usb接口蓝牙的移植,只需要保证两步工作就可以了:
1、 蓝牙usb功能驱动的移植;
如rtl8723bu的蓝牙,bluez与bluedroid下使用的驱动是一样的,但有一个定义是区分用于bluez还是bluedroid的。在rtk_btusb_8723bu.h文件如下代码中:
#ifndef CONFIG_PLATFORM_UBUNTU
#define CONFIG_BLUEDROID 1 /* bleuz 0, bluedroid 1 */
#else
#define CONFIG_BLUEDROID 0
#endif
只要定义了CONFIG_PLATFORM_UBUNTU即可。
该定义在kernel\arch\arm\configs\下config文件中配置,
CONFIG_PLATFORM_UBUNTU=y
2、 把fw及配置文件打包到“/lib/firmware/”目录下;
如gb5_wxga板子的rtl8723bu模组,只需要把rtl8723b_fw、rtl8723bu_config文件放到“\ rootfs\lib\firmware\”目录下即可。
2.2.2 UART接口蓝牙
不像usb接口蓝牙,可以直接向usb驱动注册蓝牙的功能驱动,后面就等着probe被调用就可以了。Uart接口蓝牙,使用那个uart口依赖硬件,同时也没办法像usb一样向串口驱动注册一个功能驱动等待probe,uart是没有枚举的过程的。所以uart接口蓝牙就需要应用层把使用的串口通知hci_core层,同时uart接口蓝牙的fw download及config配置工作也放到了应用层,这些工作都是由hciattach来实现。Hciattach的流程下一节介绍,这里介绍uart接口蓝牙驱动移植需要做的工作。相比图1,图2描述的uart驱动更接近代码结构。
图2 uart接口蓝牙驱动框图
从图2可以看到,串口的使用有一个切换的过程,在初始化的时候,由hciattach使用串口,初始化完成后,把串口切换给hci使用,hci负责与串口交互蓝牙数据,中间还经过了h4/h5协议层,驱动层跟移植相关只有h4/h5协议,若h4/h5使用的是内核自带的协议,那驱动层就不需要做任何的工作。
以rtl8723bs为例,需要使用rtk修改过的h5协议,就需要在kernel\drivers\bluetooth\目录下增加hci_rtk_h5.c文件,hci_ldisc.c增加对hci_rtk_h5.c的init及deinit,由于内核中注册hci协议会使用一个id号,相同id的协议不能再注册,内核中已经有的hci_h5.c与 hci_rtk_h5.c使用的是相同的id号,所以内核中需要屏蔽hci_h5.c的注册。
kernel\drivers\bluetooth\hci_ldisc.c
static int __init hci_uart_init(void)
……
#ifdef CONFIG_BT_HCIUART_H4
h4_init();
#endif
#ifdef CONFIG_BT_HCIUART_BCSP
bcsp_init();
#endif
#ifdef CONFIG_BT_HCIUART_LL
ll_init();
#endif
#ifdef CONFIG_BT_HCIUART_ATH3K
ath_init();
#endif
#ifdef CONFIG_BT_HCIUART_3WIRE
h5_init();
#endif
//Realtek_add_start
//add realtek h5 support
#ifdef CONFIG_BT_HCIUART_RTKH5
rtk_h5_init();
#endif
//Realtek_add_end
……
static void __exit hci_uart_exit(void)
……
#ifdef CONFIG_BT_HCIUART_RTKH5
rtk_h5_deinit();
#endif
kernel\drivers\bluetooth\ hci_uart.h
//Realtek_add_start
#ifdef CONFIG_BT_HCIUART_RTKH5
int rtk_h5_init(void);
int rtk_h5_deinit(void);
#endif
kernel\drivers\bluetooth\ hci_rtk_h5.c
static struct hci_uart_proto h5 = {
.id = HCI_UART_3WIRE, // 与h5_init注册是相同的id
.open = h5_open,
.close = h5_close,
.enqueue = h5_enqueue,
.dequeue = h5_dequeue,
.recv = h5_recv,
.flush = h5_flush
};
int rtk_h5_init(void)
{
int err = hci_uart_register_proto(&h5);