环境:
HI3559/3519
内核:4.9.37
蓝牙芯片:USB 8723bu
1.驱动添加
8723bu驱动。
内核自带,不过在热插拔时提示找不到bin文件,需要在/lib/firmware/rtl_bt路径放了两个rtl8723b_config.bin
rtl8723b_fw.bin文件,插入USB在驱动probe时需要这两个文件。
内核:蓝牙相关功能打开、蓝牙USB支持。
2.bluez编译
Bluez编译资源列表:
drwxr-xr-x 23 hi3559av100 hi3559av100 4096 7月 21 15:43 bluez-5.54
drwxrwxr-x 4 hi3559av100 hi3559av100 4096 7月 22 13:25 bluez-libs-3.36
drwxrwxrwx 22 hi3559av100 hi3559av100 4096 7月 22 13:25 bluez-utils-3.36
drwxr-xr-x 10 hi3559av100 hi3559av100 4096 7月 21 14:39 dbus-1.12.16
drwxr-xr-x 10 hi3559av100 hi3559av100 4096 7月 21 14:39 expat-2.2.6
drwxrwxr-x 10 hi3559av100 hi3559av100 4096 7月 21 14:39 gettext-0.20.2
drwxrwxr-x 12 hi3559av100 hi3559av100 4096 7月 21 14:39 glib-2.40.0
drwxrwxr-x 11 hi3559av100 hi3559av100 4096 7月 21 14:39 libffi-3.3
drwxrwxr-x 10 hi3559av100 hi3559av100 4096 7月 21 14:39 libical
drwxr-xr-x 18 hi3559av100 hi3559av100 4096 7月 21 14:39 ncurses-5.9
drwxrwxr-x 6 hi3559av100 hi3559av100 4096 7月 21 14:39 readline-8.0
drwxr-xr-x 14 hi3559av100 hi3559av100 4096 7月 21 14:39 zlib-1.2.11
资源连接:
https://download.youkuaiyun.com/download/Yangquot/20530116
主要用到bluez dbus bluez-utils,其他都是依赖库。
每个库都使用configure命令先进行参数配置生成makefile,之后make & make install。
至于库生成路径也是通过参数指定,这里有个坑,路径要尽量简短、和使用绝对路径,因为生成的一些bin文件后期使用时会用到这个路径,也就是说开发板上后期也要有和编译环境相同的文件路径树。
每个库的编译配置已整理打包,3559用了--host=aarch64-linux 但是有的库并不支持,改成了--host=arm-linux,这里看似乎没有大碍。
>>>>编译这些东西花了一周,而且很痛苦,主要是中间换过好多版本,有的根本就无法编译,不知道是不是和我的Ubuntu虚拟机或者编译链有关系,虚拟机版本:Ubuntu14.04。
3.运行
编译完将lib和bin搬到板子上,并且在板子上创建编译路径。
本次编译目标路径:/home/3519_bt/arm_build/libs
我的目标是板子做从机,手机app扫描连接板子,并且通过SPP传输数据。
Hciconfig 可以看到蓝牙芯片的MAC地址。
我的脚本配置:
hciconfig hci0 down
hciconfig hci0 reset
hciconfig hci0 up
hciconfig hci0 piscan
※://这里是我的dbus编译路径dbus上一次运行时会生成一个文件,重启运行前先删掉:
rm /home/3519_bt/arm_build/libs/var/run/dbus/pid
dbus-daemon --system
※://hcid.conf 一个配置文件,已打包。另外bluez-utils编译时会生成plugins文件,都是.so形式,serial.so就是SPP服务,hcid在启动时会去固定的路径下读取所有的.so,通过dlopen函数加载。路径的话和编译路径有关。
hcid -f /etc/bluetooth/hcid.conf -d -n &
※://不明白为什么要单独执行这个才能真正添加SPP服务。
sdptool add SP
到这里SPP已经添加完毕,蓝牙也开始广播了。
不过还需要应用层建立socket监听SPP通道,手机app才能正确连接。这里使用的SPP蓝牙串口APP来协助测试。
4.测试
测试的话可以使用rfcomm命令替代应用层编程,rfcomm会建立socket:
mknod -m 666 /dev/rfcomm0 c 216 1
rfcomm listen /dev/rfcomm0 1 &
※:1是当前的SPP通道,sdptool brower local 可以查看
监听之后APP开始连接,
执行cat /dev/rfcomm 就可以看到app发送来的数据
命令验证完毕,还要做的就是应用层socket,也就是把rfcomm那一套搬到自己工程里罢了。
>>>>>>>>>>>>>>end
配置中的异常:
dbus-daemon[309]: Failed to start message bus: Could not get UID and GID for username "messagebus"
在/home/3519_bt/arm_build/libs/share/dbus-1 # vi system.conf,修改里面的username为root
hcid[319]: Unable to get on D-Bus:
/home/3519_bt/arm_build/libs/etc 下文件没有拷贝完全,用到了/home/3519_bt/arm_build/libs/etc/dbus-1/ system.conf
测试效果图:
Mi8使用串口SPP软件测试
后续 附一段移植RFCOMM的应用层socket:
>>>>>>>>>>>>>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <signal.h>
#include <termios.h>
#include <sys/poll.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include "Bt/bluetooth/bluetooth.h"
#include "Bt/bluetooth/hci.h"
#include "Bt/bluetooth/hci_lib.h"
#include "Bt/bluetooth/rfcomm.h"
static uint8_t bt_recv_buf[300];
static void* BtServer(void *para)
{
int ctl, lm, nsk, alen;
struct sockaddr_rc laddr, raddr;
//ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
ctl = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (ctl < 0) {
printf("Can't open RFCOMM control socket");
return -1;
}
lm = RFCOMM_LM_MASTER;
if (setsockopt(ctl, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
printf("Can't set RFCOMM link mode");
close(ctl);
return;
}
laddr.rc_family = AF_BLUETOOTH;
bacpy(&laddr.rc_bdaddr, BDADDR_ANY);
laddr.rc_channel = 1;
if (bind(ctl, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
printf("Can't bind RFCOMM socket");
close(ctl);
return;
}
printf("[BT] Waiting for connection on channel %d\n", laddr.rc_channel);
listen(ctl, 1);
_wait:
alen = sizeof(raddr);
nsk = accept(ctl, (struct sockaddr *) &raddr, &alen);
printf("[BT] connection on channel %d\n", laddr.rc_channel);
for(;;){
int ret;
int read_len;
fd_set fds;
FD_ZERO(&fds);
FD_SET(nsk, &fds);
ret = select(nsk+1, &fds, NULL, NULL, NULL);
if(ret < 0){
printf("BT select error :%d\n",ret);
continue;
} else if(ret == 0)
continue;
read_len = read(nsk, bt_recv_buf, sizeof(bt_recv_buf));
printf("BT read %d\n", read_len);
if(read_len <= 0){
printf("BT client lost \n");
break;
}
}
goto _wait;
}
void startBTServerThread()
{
pthread_t thread = 0;
pthread_create(&thread, NULL, (void *)BtServer, NULL);
}
<<<<<<<<<<<<<