屏蔽内核中现有的hci_h5.c修改方式为:
kernel\arch\arm\configs\目录下config文件修改下面两行。
# CONFIG_BT_HCIUART_ATH3K is not set //屏蔽BT_HCIUART_ATH3K
CONFIG_BT_HCIUART_RTKH5=y // 打开BT_HCIUART_RTKH5
Hci_ldisc通过tty_register_ldisc(N_HCI, &hci_uart_ldisc)向串口注册HCI line discipline,当hciattach通过ioctl把串口切换到HCI line discipline时,hci_ldisc就可以与串口通信了。
kernel\drivers\bluetooth\ hci_ldisc.c
static int __init hci_uart_init(void)
{
static struct tty_ldisc_ops hci_uart_ldisc;
int err;
BT_INFO("HCI UART driver ver %s", VERSION);
/* Register the tty discipline */
memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
hci_uart_ldisc.name = "n_hci";
hci_uart_ldisc.open = hci_uart_tty_open;
hci_uart_ldisc.close = hci_uart_tty_close;
hci_uart_ldisc.read = hci_uart_tty_read;
hci_uart_ldisc.write = hci_uart_tty_write;
hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
hci_uart_ldisc.poll = hci_uart_tty_poll;
hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
hci_uart_ldisc.owner = THIS_MODULE;
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
BT_ERR("HCI line discipline registration failed. (%d)", err);
return err;
}
3 Hciattach的处理流程
只有uart接口的蓝牙才需要hciattach工具,hciattach的作用为配置串口,下载fw及config文件,把串口切换给hci_ldisc使用。
Bluez带有hciattach的源码,框架也比较清晰,对很多厂家都有支持,但实际调试realtek及boardcom的模组时,Bluez自带的hciattach都是不能使用的,realtek及boardcom对hciattach有特殊的修改,主要是针对fw和config的下载部分。但hciattach的作用及流程与Bluez自带的hciattach是一样的。Hciattach的流程如图3所示。
图3 hciattach初始化流程
Hciattach的流程比较简单,从现在Ubuntu及debian系统的设计看,hciattach都是开机时就运行,一直到关机时才结束。
Hciattach的移植涉及下面几个地方:
1、 把hciattach可执行文件放到bin目录下;
以lemaker板子为例:
把hciattach_rtk放到\rootfs\usr\sbin\目录下;
2、 把fw及config文件打包进系统,放置的路径由hciattach open fw确定
以使用rtl8723bs模组:
把rtl8723b_fw、rtk8723_bt_config放到
\rootfs\lib\firmware\rtl8723bs\目录下;
3、 加入hciattach的启动与退出控制:
把 bluetooth.conf文件放到\rootfs\etc\init\目录下。
bluetooth.conf文件内容
description "bluetooth daemon"
start on started dbus
stop on stopping dbus
env UART_CONF=/etc/bluetooth/uart
env RFCOMM_CONF=/etc/bluetooth/rfcomm.conf
expect fork
respawn
exec /usr/sbin/bluetoothd
post-start script
#[ "$VERBOSE" = no ] && redirect='>/dev/null 2>&1' || redirect=
# start_uarts()
#if [ -x /usr/sbin/hciattach ] && [ -f $UART_CONF ];
#then
# grep -v '^#' $UART_CONF | while read i; do
# eval "/usr/sbin/hciattach $i $redirect" || :
# done
#fi
exec hciattach_rtk -n -s 115200 /dev/ttyS2 rtk_h5 &
# start_rfcomm()
if [ -x /usr/bin/rfcomm ] && [ -f $RFCOMM_CONF ] ;
then
# rfcomm must always succeed for now: users
# may not yet have an rfcomm-enabled kernel
eval "/usr/bin/rfcomm -f $RFCOMM_CONF bind all $redirect" || :
fi
end script
post-stop script
# stop_uarts()
logger -t bluez "Stopping uarts"
kill
bluetooth.conf中有脚本,在开机、关机时运行,这里:
开机运行:exec hciattach_rtk -n -s 115200 /dev/ttyS2 rtk_h5 &
关机运行:killall hciattach_rtk >/dev/null 2>&1 || :