https://dbus.freedesktop.org/releases/dbus/
zlib:http://www.zlib.net/
libffi:https://www.sourceware.org/libffi/
gettext:http://www.gnu.org/software/gettext/
glib:http://ftp.gnome.org/pub/gnome/sources/glib/
libical:https://github.com/libical/libical
readline:http://ftp.gnu.org/gnu/readline/
ncurses:http://ftp.gnu.org/gnu/ncurses/
bluez:https://mirrors.edge.kernel.org/pub/linux/bluetooth/
alsa-lib:http://www.linuxfromscratch.org/blfs/view/svn/multimedia/alsa-lib.html
alsa-utils:http://www.linuxfromscratch.org/blfs/view/stable/multimedia/alsa-utils.html
sndfile:http://www.mega-nerd.com/libsndfile/#Download
sbc:https://mirrors.edge.kernel.org/pub/linux/bluetooth/
bluez-alsa:https://github.com/Arkq/bluez-alsa
bt_lib.tar.bz2的附件为本次用到的源码打包。
下面流程以 arm-linux-gnueabihf- 8.2
为例,下面的INSTALL_PATH为lib install的位置,请自行更改。
设置环境变量INSTALL_PATH作为bluez的编译输出路径
export INSTALL_PATH=/customer/bluetooth/bluez_build
zlib:
export CC=arm-linux-gnueabihf-gcc export AR=arm-linux-gnueabihf-ar export RANLIB=arm-linux-gnueabihf-ranlib ./configure --prefix=$INSTALL_PATH/zlib make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/zlib/lib/pkgconfig/:$PKG_CONFIG_PATH
libffi:
./configure --prefix=$INSTALL_PATH/libffi --host=arm-linux --target=arm-linux CC=arm-linux-gnueabihf-gcc make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/libffi/lib/pkgconfig/:$PKG_CONFIG_PATH
gettext:
glib只需要gettext的头文件来协助编译,如果server环境已安装,可以不进行移植
编译命令如下:
./configure --prefix=$INSTALL_PATH/gettext --disable-libasprintf --host=arm-linux --target=arm-linux CC=arm-linux-gnueabihf-gcc make && make install
PS:上述基于gettext-0.20.1,不知是否该版本的configure有bug,一开始配置--disable-libasprintf会导致configure不过,需要先进行一个configure,make报错后,重新添加--disable-libasprintf再configure一次才行。
Q1:
A:在configure 命令加入--disable-libasprintf
glib:
echo ac_cv_type_long_long=yes>>arm-linux-gnueabihf.cache echo glib_cv_stack_grows=no>>arm-linux-gnueabihf.cache echo glib_cv_uscore=no>>arm-linux-gnueabihf.cache echo ac_cv_func_posix_getpwuid_r=yes>>arm-linux-gnueabihf.cache echo ac_cv_func_posix_getgrgid_r=yes>>arm-linux-gnueabihf.cache ./configure --prefix=$INSTALL_PATH/glib --host=arm-linux --target=arm-linux CC="arm-linux-gnueabihf-gcc" CFLAGS="-I$INSTALL_PATH/zlib/include -I$INSTALL_PATH/libffi/include" LDFLAGS="-L$INSTALL_PATH/zlib/lib -L$INSTALL_PATH/libffi/lib" LIBS="-lz -lffi" --cache-file=arm-linux-gnueabihf.cache make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/glib/lib/pkgconfig/:$PKG_CONFIG_PATH
Q1:
A:若想自己进行移植可以参考上面gettext的移植参考。不想折腾的话,可以直接在server上安装gettext,apt-get install gettext
Q2:
A:同样不想折腾的话,直接在server上解决环境问题,apt-get install libglib2.0-dev
Q3:
A:请参考https://blog.csdn.net/zmlovelx/article/details/81664043
Q4:编译过程出现c:28:17: fatal error: ffi.h: No such file or directory
A:没有正确指定libffi的安装的头文件目录
Q5:编译过程中出现如下log
./.libs/libgobject-2.0.so: undefined reference to `ffi_type_void' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_double' ./.libs/libgobject-2.0.so: undefined reference to `ffi_prep_cif' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_sint32' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_float' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_uint64' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_sint64' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_pointer' ./.libs/libgobject-2.0.so: undefined reference to `ffi_type_uint32' ./.libs/libgobject-2.0.so: undefined reference to `ffi_call'
A:没有正确指定libffi的lib路径或没有链接该库
Q6:编译过程中出现如下log
./.libs/libgio-2.0.so: undefined reference to `inflateReset' ./.libs/libgio-2.0.so: undefined reference to `inflateEnd' ./.libs/libgio-2.0.so: undefined reference to `inflateGetHeader' ./.libs/libgio-2.0.so: undefined reference to `deflate' ./.libs/libgio-2.0.so: undefined reference to `deflateInit_' ./.libs/libgio-2.0.so: undefined reference to `inflateInit2_' ./.libs/libgio-2.0.so: undefined reference to `inflate' ./.libs/libgio-2.0.so: undefined reference to `deflateSetHeader' ./.libs/libgio-2.0.so: undefined reference to `deflateEnd' ./.libs/libgio-2.0.so: undefined reference to `deflateReset' ./.libs/libgio-2.0.so: undefined reference to `inflateInit_' ./.libs/libgio-2.0.so: undefined reference to `deflateInit2_'
A:没有正确指定zlib的lib路径或没有链接该库
expat:
./configure --prefix=$INSTALL_PATH/expat --host=arm-linux --target=arm-linux CC=arm-linux-gnueabihf-gcc make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/expat/lib/pkgconfig/:$PKG_CONFIG_PATH
dbus:
echo ac_cv_have_abstract_sockets=yes>arm-linux-gnueabihf.cache ./configure --prefix=$INSTALL_PATH/dbus --host=arm-linux --target=arm-linux --disable-tests CC="arm-linux-gnueabihf-gcc -I$INSTALL_PATH/zlib/include -I$INSTALL_PATH/libffi/include -I$INSTALL_PATH/gettext/include -I$INSTALL_PATH/glib/include -I$INSTALL_PATH/expat/include -L$INSTALL_PATH/zlib/lib -L$INSTALL_PATH/libffi/lib -L$INSTALL_PATH/gettext/lib -L$INSTALL_PATH/glib/lib -L$INSTALL_PATH/expat/lib" --cache-file=arm-linux-gnueabihf.cache --with-x=no make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/dbus/lib/pkgconfig/:$PKG_CONFIG_PATH
Q1:
A:没有连接zlib和libffi的库,在configure命令链接这两个库
Q2:
A:这里仅仅dbus的test需要用到glib,我们可以直接不编译test,来解决这个报错,在configure命令添加--disable-tests。同样也可以链接上glib的所有库来修复,
./configure --prefix=$INSTALL_PATH --host=arm-linux --target=arm-linux CC="arm-linux-gnueabihf-gcc" CFLAGS="-I$INSTALL_PATH/include" LDFLAGS="-L$INSTALL_PATH/lib" LIBS="-lz -lffi -lgmodule-2.0 -lglib-2.0 -lgio-2.0 -lgobject-2.0 -lgthread-2.0" --cache-file=arm-linux-gnueabihf.cache --with-x=no
Q3:configure 过程中出现以下log
checking for EXPAT... configure: error: Package requirements (expat) were not met: No package 'expat' found
A:指定expat库的路径
export EXPAT_LIBS="-lexpat -L$INSTALL_PATH/lib/" export EXPAT_CFLAGS="-I$INSTALL_PATH/include/"
libical:
export CC=arm-linux-gnueabihf-gcc export CXX=arm-linux-gnueabihf-g++ cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH/libical make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/libical/lib/pkgconfig/:$PKG_CONFIG_PATH
ncurses:
export CPPFLAGS="-P" ./configure --prefix=$INSTALL_PATH/ncurses --host=arm-linux --target=arm-linux --without-cxx-binding CC="arm-linux-gnueabihf-gcc" --enable-widec --with-shared make && make install
Q1:
A:这里我们可以使用--without-cxx-binding来跳过C++编译的部分来规避。https://stackoverflow.com/questions/46793314/error-when-compiling-ncurses看起来除了换版本没有其他的办法。
readline:
./configure --prefix=$INSTALL_PATH/readline --host=arm-linux --target=arm-linux bash_cv_wcwidth_broken=yes CC=arm-linux-gnueabihf-gcc make && make install
bluez:
./configure --prefix=$INSTALL_PATH/bluez --mandir=$INSTALL_PATH/bluez/man --sysconfdir=$INSTALL_PATH/bluez/etc --localstatedir=$INSTALL_PATH/bluez/var --host=arm-linux CC="arm-linux-gnueabihf-gcc -I$INSTALL_PATH/zlib/include -I$INSTALL_PATH/libffi/include -I$INSTALL_PATH/gettext/include -I$INSTALL_PATH/glib/include -I$INSTALL_PATH/expat/include -I$INSTALL_PATH/dbus/include -I$INSTALL_PATH/libical/include -I$INSTALL_PATH/ncurses/include -I$INSTALL_PATH/readline/include -L$INSTALL_PATH/zlib/lib -L$INSTALL_PATH/libffi/lib -L$INSTALL_PATH/gettext/lib -L$INSTALL_PATH/glib/lib -L$INSTALL_PATH/expat/lib -L$INSTALL_PATH/dbus/lib -L$INSTALL_PATH/libical/lib -L$INSTALL_PATH/ncurses/lib -L$INSTALL_PATH/readline/lib -lreadline -lncursesw" --enable-debug --enable-test --enable-shared --enable-testing --disable-udev --disable-systemd --disable-cups --disable-obex --enable-library --enable-tools --enable-deprecated make && make install export PKG_CONFIG_PATH=$INSTALL_PATH/bluez/lib/pkgconfig/:$PKG_CONFIG_PATH
Q1:configure过程出现xxx are required
A:pkgconfig没在环境变量PKG_CONFIG_PATH中
为了规范编译出来的文件,这里重新定义一个环境变量BLUEALSA_INSTALL_PATH做为编译bluealsa的输出路径
export BLUEALSA_INSTALL_PATH=/customer/bluetooth/bluealsa_build export CC=arm-linux-gnueabihf-gcc export CXX=arm-linux-gnueabihf-g++
alsa-lib:
./configure --prefix=$BLUEALSA_INSTALL_PATH/alsa/ --host=arm-linux --disable-aload --disable-rawmidi --disable-seq --disable-ucm --disable-alisp --disable-old-symbols --disable-python --enable-debug CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ --with-plugindir=$BLUEALSA_INSTALL_PATH/alsa/lib --with-configdir=$BLUEALSA_INSTALL_PATH/alsa/etc make && make install export PKG_CONFIG_PATH=$BLUEALSA_INSTALL_PATH/alsa/lib/pkgconfig/:$PKG_CONFIG_PATH
alsa-utils:
./configure --prefix=$BLUEALSA_INSTALL_PATH/alsa-utils --host=arm-linux --with-curses=ncurses CC="arm-linux-gnueabihf-gcc -lasound -I$BLUEALSA_INSTALL_PATH/alsa/include -L$BLUEALSA_INSTALL_PATH/alsa/lib" --disable-xmlto --disable-alsamixer make && make install
sndfile:
./configure --prefix=$BLUEALSA_INSTALL_PATH/sndfile/ --host=arm-linux-gnueabihf --enable-shared CC=arm-linux-gnueabihf-gcc make && make install export PKG_CONFIG_PATH=$BLUEALSA_INSTALL_PATH/sndfile/lib/pkgconfig/:$PKG_CONFIG_PATH
sbc:
./configure --prefix=$BLUEALSA_INSTALL_PATH/sbc/ --host=arm-linux --enable-shared --enable-debug CC=arm-linux-gnueabihf-gcc make && make install export PKG_CONFIG_PATH=$BLUEALSA_INSTALL_PATH/sbc/lib/pkgconfig/:$PKG_CONFIG_PATH
bluez-alsa:
autoreconf --install ./configure --prefix=$BLUEALSA_INSTALL_PATH/bluez-alsa --host=arm-linux --enable-debug --enable-shared --enable-pcm-test CFLAGS="-I$INSTALL_PATH/zlib/include -I$INSTALL_PATH/libffi/include -I$INSTALL_PATH/gettext/include -I$INSTALL_PATH/glib/include -I$INSTALL_PATH/expat/include -I$INSTALL_PATH/dbus/include -I$INSTALL_PATH/libical/include -I$INSTALL_PATH/ncurses/include -I$INSTALL_PATH/readline/include -I$INSTALL_PATH/bluez/include -I$BLUEALSA_INSTALL_PATH/alsa/include -I$BLUEALSA_INSTALL_PATH/sndfile/include -I$BLUEALSA_INSTALL_PATH/sbc/include" LDFLAGS="-L$INSTALL_PATH/zlib/lib -L$INSTALL_PATH/libffi/lib -L$INSTALL_PATH/gettext/lib -L$INSTALL_PATH/glib/lib -L$INSTALL_PATH/expat/lib -L$INSTALL_PATH/dbus/lib -L$INSTALL_PATH/libical/lib -L$INSTALL_PATH/ncurses/lib -L$INSTALL_PATH/readline/lib -L$INSTALL_PATH/bluez/lib -L$BLUEALSA_INSTALL_PATH/alsa/lib -L$BLUEALSA_INSTALL_PATH/sndfile/lib -L$BLUEALSA_INSTALL_PATH/sbc/lib" LIBS="-lz -lffi -lglib-2.0 -lgmodule-2.0" make && make install export PKG_CONFIG_PATH=$BLUEALSA_INSTALL_PATH/bluez-alsa/lib/pkgconfig/:$PKG_CONFIG_PATH
Q1:
A:sudo apt-get install libtool
到此已经将蓝牙A2DP依赖的库全部编译出来。附件bt_build.tar.bz2为arm-linux-gnueabihf- 8.2工具链按照上述流程编译出来文件的打包。
内核中需要打开以下配置:
打开内核中蓝牙子系统的支持。
Networking support --->
Bluetooth subsystem support(此项设置y或m)
选择所需要的蓝牙功能
这里比较关注的是标红的两项,这两项和蓝牙芯片控制器息息相关,其中BR/EDR即传统蓝牙,而LE则是低功耗蓝牙,两种协议不一样,需要根据蓝牙芯片的支持的模式来选择。
这里的蓝牙是传统蓝牙,故对BR/EDR设置为y。第三项顾名思义是蓝牙的自测,第四项为debugfs设置为y。
按如下图配置,当然也可以设置为m。而没有选上的BNEP和HIDP我们这里没有用到。BNEP:网络封装协议,一般用于作为网卡使用。HIDP则用于蓝牙键鼠等设备。
后面选择蓝牙是通过什么方式连接到系统,选择下图红框选项选择蓝牙设备的连接方式,这里是uart。
打开ALSA选项
Device Drivers --->
Sound card support -→
支持在用户空间加载firmware
Device Drivers --->
Generic Driver Options -→
替换内核
下面需要将相关的lib和bin档放到板子上。比较方便的办法就是删掉不必要的东西(include、man等目录)后将整个install目录完全拷贝到板端,这样可以避免因路径的问题导致的一些错误。
下图是bluez及其所依赖的库编译生成的目录
从上图的各个目录下的lib目录下拷贝出相应的库及其符号链接文件,并做strip,拷贝到板端的/lib目录或其他地方并加入到板端的环境变量中。
在bluez和dbus的目录下拷贝出相应的tools并strip,以下只是一些常用的tools,请按实际情况进行拷贝,拷贝到板端的/bin目录或其他地方并加入到板端的环境变量中。
将bluetoothd(bluez的守护进程)拷贝到板端的/bin目录或其他地方并加入到板端的环境变量中。
在板端的INSTALL_PATH目录下新建一个etc/bluetooth目录,并拷贝bluez源码中的src/main.conf到板端的INSTALL_PATH/etc/bluetooth下,此文件为蓝牙的配置文件,存放一些基本信息,如蓝牙的名字等
下图为bluez-alsa及其所依赖的库编译生成的目录
从上图的各个目录下的lib目录下拷贝出相应的库及其符号链接文件,并做strip,拷贝到板端的/lib目录或其他地方并加入到板端的环境变量中。
注意,这个alsa-lib里面的库需要拷贝到板端的$BLUEALSA_INSTALL_PATH/alsa/lib下
从各个目录中找出相关的tool,做strip,拷贝到板端的/bin目录或其他地方并加入到板端的环境变量中。
拷贝alsa/share,alsa/etc,拷贝到板端对应的绝对路径下,即在server中该目录的绝对路径要和板端的绝对路径一致。
将bluez-alsa生成的20-bluealsa.conf(bluez-alsa/share/alsa/alsa.conf.d/20-bluealsa.conf)拷贝板端的$BLUEALSA_INSTALL_PATH/alsa/etc/alsa.conf.d/下,没有此文件,bluez-alsa没法去虚拟一个alsa设备
bluetooth.tar.bz2为按照上述流程移植到板端的文件。
insmod hci_xxx.ko(build-in请忽略)
蓝牙模块上电
加载对应的firmware(由蓝牙厂商提供)
/var/run准备
mkdir /var/run mount tmpfs /var/run -t tmpfs
将/var/run挂载到tmpfs,因为bluealsa启动初始化时需要到这个目录去创建一个目录并创建一个socket,故需要该目录可写。
由于bluealsa运行时需要访问/var/run/dbus,实际上需要访问的是bluez编译生成的var/run/dbus,故在此做了一个软链接来解决此问题。
ln -s /customer/bluetooth/bluez_build/dbus/var/run/dbus /var/run/dbus
启动dbus的守护进程,dbus-daemon --system &
启动bluez的守护进程,bluetoothd -n -C &
启动bluealsa,bluealsa -p a2dp-source &
使用bluetoothctl或其他tools来查看蓝牙控制器的状态、打开/关闭、修改信息、配置状态、扫描、配对。
查看蓝牙的状态,可使用bluetoothctl中的show命令或直接运行hciconfig –a。
这里的Powered表示蓝牙是否开启,Discoverable表示是否可被发现。
使用hciconfig hci0 up(这里的hci0请根据实际情况做更改)或bluetoothctl中的power on命令来打开蓝牙。
开启蓝牙
修改蓝牙名字可以通过hciconfig hci0 name xxx或bluetoothctl中的system-alias xxx以及修改conf来进行修改。
设置蓝牙的代理能力,请按实际情况进行设置。
蓝牙的可发现和可连接可以通过hciconfig hci0 piscan或bluetoothctl中的discoverable on来进行设置,但通过bluetoothctl来设置的话默认只有180秒的时间可以发现和连接蓝牙,若要修改时间,可将main.conf的此处#号去掉,即可一直可发现可连接。
扫描蓝牙开关,使用bluetoothctl中的scan on/off命令。
配对蓝牙,使用bluetoothctl中的pair + mac地址,来进行匹配。
将蓝牙音箱添加为信任设备,使用bluetoothctl中的trust + mac地址来进行设置
连接蓝牙,使用bluetoothctl中的connect + mac地址来进行连接。
往蓝牙音箱丢数据
aplay -D bluealsa:HCI=hci0,DEV=49:f5:31:5e:93:c8,PROFILE=a2dp /mnt/music/Wav_File/8K_16bit_STERO_30s.wav
(hci0为板端蓝牙对应的hci控制器,49:f5:31:5e:93:c8为所使用的蓝牙音箱的蓝牙地址, /mnt/music/Wav_File/8K_16bit_STERO_30s.wav为所播完的wav档,以上参数请以实际情况为准。如果需要播放其他的格式如MP3,则bluealsa需要别的依赖,请自行移植)
Q: dbus-daemon启动后kill掉无法重新启动,出现如下log:
A:删除板端$INSTALL_PATH/dbus/var/run/dbus/pid,也可以修改rcS文件,添加rm $INSTALL_PATH(对应自己板端的install绝对路径)/dbus/var/run/dbus/pid –f,dbus启动后会去创建这个文件,
若上一次开机启动dbus了关机没有删除该文件,会导致dbus没法启动,为省去麻烦修改rcS文件,每次开机都去删除一遍该dbus生成的文件。
Q: dbus-daemon启动后出错打印如下log:
A:编辑板端$INSTALL_PATH/dbus/etc/dbus-1/system.d/bluetooth.conf文件,删除下列”lp”group
Q:dbus-daemon启动后出错打印如下log:
A:往passwd文件中添加messagebus用户。将messagebus:x:500:500::/home/messagebus:/bin/sh添加到passwd中。如果还不行那就可能是/lib下缺少了libnss_files这个so,从toolchain中找到libnss_files.so.2和libnss_files-2.28.so,放到板端/lib下
Q:启动bluetoothd出错,报如下log:
D-Bus setup failed: Connection ":1.0" is not allowed to own the service "org.bluez" due to security policies in the configuration file
bluetoothd[124]: Unable to get on D-Bus
A:缺少bluetoothd所要的配置文件(bluetooth.conf)
Q:bluealsa启动出错,报如下log:
bluealsa: Couldn't initialize controller thread: Bad file descriptor
A:这是bluealsa初始化线程的时候出错,但通过阅读源码,初始化线程失败后打印的都是这个log,建议到bluealsa中加log去定位出错。
Q:aplay执行出现以下log
A:bluez-alsa生成的20-bluealsa.conf配置文件的位置不对,该文件需要放到板端$BLUEALSA_INSTALL_PATH/alsa/etc/alsa.conf.d/目录下
Q:aplay执行出现以下log
A:libasound_module_pcm_bluealsa.so没有放对路径。
以上为在Takoyaki平台上搭建A2DP的流程(蓝牙模组使用的是rtl8723d),至于应用需要如何写还请参考,bluez-alsa的demo