bluez5.50+pulseaudio实现蓝牙音响音频播放

简介: bluez5.50+pulseaudio实现蓝牙音响音频播放

bluez5.50+pulseaudio实现蓝牙音响音频播放

环境介绍

执行流程

蓝牙服务配置和启动流程

蓝牙连接

音频播放

问题记录


环境介绍

硬件环境:


  • 开发板使用全志 T507 作为主控芯片
  • WiFi蓝牙模块采用移远FC21、AP6236,操作方式一样,实现结果相同。(区别是不同的蓝牙模块在初始化和上电的操作略有不同)

软件环境:


  • bluez-5.50
  • pulseaudio-12.2
  • dbus-1.12.10

执行流程

参考以下文章完成对 bluez 蓝牙协议栈的编译和部署:

手把手教你移植bluez 5.47蓝牙协议栈


参考文章里使用的是 bluez5.47的版本,和我这边使用的 5.50 操作是一样的。目前对于 bluez版本主要区别在于小于5的版本(3.xx-4.xx)和bluez5(大于5.0)版本。


bluez 旧版本(3.xx-4.xx)下结合了应用层的部分协议,所以在增加库依赖后可以仅通过 bluez 完成蓝牙设备的连接;

而 bluez-5 新版本之后,将蓝牙应用层协议剥离开,仅有 bluez 是无法正常完成蓝牙多媒体设备的连接的(会报无应用协议支持而断开),所以在 bluez-5 之后,对于蓝牙音响的使用,就需要借助 pulseaudio 或者 bluealse 等音频服务完成对蓝牙音频设备的连接。


蓝牙服务配置和启动流程

修改 pulseaudio 的部分默认配置,

【/etc/pulse/default.pa】

【/etc/pulse/system.pa】

注释掉其中的以下模块:


load-module module-suspend-on-idle
load-module module-bluetooth-policy


查看蓝牙设备是否已经存在

# hciconfig -a
hci0:   Type: Primary  Bus: UART
        BD Address: BE:5A:D6:6A:9D:5F  ACL MTU: 1021:7  SCO MTU: 64:1
        UP RUNNING PSCAN
        RX bytes:244301 acl:651 sco:0 events:27591 errors:0
        TX bytes:34440936 acl:54726 sco:0 commands:132 errors:0
        Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
        Link policy: RSWITCH SNIFF
        Link mode: SLAVE ACCEPT
        Name: 'BlueZ 5.50'
        Class: 0x0c0000
        Service Classes: Rendering, Capturing
        Device Class: Miscellaneous,
        HCI Version: 4.2 (0x8)  Revision: 0x70
        LMP Version: 4.2 (0x8)  Subversion: 0x410c
        Manufacturer: Broadcom Corporation (15)


如果不存在,则检查蓝牙模块初始化部分是否正常。


蓝牙设备已经存在后,执行以下启动脚本:


#!/bin/sh
btmgmt -i hci0 name "wwtest"
btmgmt -i hci0 connectable on
btmgmt -i hci0 le on
btmgmt -i hci0 advertising on
btmgmt -i hci0 power on
sdptool add --channel=1 GATT SP A2SNK A2DP
btgatt-server &
/usr/libexec/bluetooth/bluetoothd -d -C -n &
pulseaudio -D  --exit-idle-time=-1 --start --log-target=file:/tmp/pulse.log


这里 /usr/libexec/bluetooth/bluetoothd 使用 -d 参数打开了 debug 选项,如果后续一切正常,可以去掉这个参数,就不会显示很多信息了。


蓝牙连接

蓝牙设备连接这里可以使用 bluetoothctl 和 hcitool 这两种工具,bluetoothctl 是 bluez 自带的蓝牙调试工具,具体连接方式和过程如下:


# bluetoothctl
bluetoothd[8116]: src/agent.c:agent_ref() 0x298260a0: ref=1
bluetoothd[8116]: src/agent.c:register_agent() agent :1.9
Agent registered
[bluetooth]# show
Controller BE:5A:D6:6A:9D:5F (public)
        Name: BlueZ 5.50
        Alias: BlueZ 5.50
        Class: 0x000c0000
        Powered: yes
        Discoverable: no
        Pairable: yes
        UUID: Audio Source              (0000110a-0000-1000-8000-00805f9b34fb)
        UUID: Audio Sink                (0000110b-0000-1000-8000-00805f9b34fb)
        UUID: A/V Remote Control        (0000110e-0000-1000-8000-00805f9b34fb)
        UUID: PnP Information           (00001200-0000-1000-8000-00805f9b34fb)
        UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
        UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)
        UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
        Modalias: usb:v1D6Bp0246d0532
        Discovering: no
[bluetooth]# devices
Device 60:AA:EF:B4:89:8A HUAWEI P40
Device 28:37:13:B0:F1:D7 HUAWEI CM510
[bluetooth]# connect 28:37:13:B0:F1:D7
Attempting to connect to 28:37:13:B0:F1:D7
bluetoothd[8116]: src/device.c:connect_profiles() /org/bluez/hci0/dev_28_37_13_B0_F1_D7 (all), client :1.10
bluetoothd[8116]: profiles/audio/a2dp.c:a2dp_sink_connect() path /org/bluez/hci0/dev_28_37_13_B0_F1_D7
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_ref() 0x298480f0: ref=1
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_ref() 0x298480f0: ref=2
bluetoothd[8116]: profiles/audio/a2dp.c:setup_ref() 0x29825ed0: ref=1
bluetoothd[8116]: profiles/audio/source.c:source_set_state() State changed /org/bluez/hci0/dev_28_37_13_B0_F1_D7: SOURCE_STATE_DISCONNECTED -> SOURCE_STATE_CONNECTING
bluetoothd[8116]: profiles/audio/sink.c:sink_set_state() State changed /org/bluez/hci0/dev_28_37_13_B0_F1_D7: SINK_STATE_DISCONNECTED -> SINK_STATE_CONNECTING
bluetoothd[8116]: profiles/audio/sink.c:sink_connect() stream creation in progress
bluetoothd[8116]: src/service.c:change_state() 0x29829e80: device 28:37:13:B0:F1:D7 profile a2dp-sink state changed: disconnected -> connecting (0)
[bluetooth]# bluetoothd[8116]: src/adapter.c:connected_callback() hci0 device 28:37:13:B0:F1:D7 connected eir_len 14
[CHG] Device 28:37:13:B0:F1:D7 Connected: yes
[HUAWEI CM510]# bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_connect_cb() AVDTP: connected signaling channel to 28:37:13:B0:F1:D7
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_connect_cb() AVDTP imtu=672, omtu=672
bluetoothd[8116]: profiles/audio/avdtp.c:session_cb()
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_parse_resp() DISCOVER request succeeded
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_discover_resp() seid 1 type 1 media 0 in use 0
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_discover_resp() seid 2 type 0 media 0 in use 0
bluetoothd[8116]: profiles/audio/avdtp.c:session_cb()
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_parse_resp() GET_ALL_CAPABILITIES request succeeded
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_get_capabilities_resp() seid 1 type 1 media 0
bluetoothd[8116]: profiles/audio/avdtp.c:session_cb()
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_parse_resp() GET_ALL_CAPABILITIES request succeeded
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_get_capabilities_resp() seid 2 type 0 media 0
bluetoothd[8116]: profiles/audio/a2dp.c:discover_cb() err (nil)
bluetoothd[8116]: profiles/audio/sink.c:discovery_complete() Discovery complete
bluetoothd[8116]: profiles/audio/a2dp.c:setup_ref() 0x29825ed0: ref=2
bluetoothd[8116]: profiles/audio/a2dp.c:setup_ref() 0x29825ed0: ref=3
bluetoothd[8116]: profiles/audio/media.c:media_endpoint_async_call() Calling SelectConfiguration: name = :1.3 path = /MediaEndpoint/A2DPSource
bluetoothd[8116]: profiles/audio/a2dp.c:setup_unref() 0x29825ed0: ref=2
bluetoothd[8116]: profiles/audio/a2dp.c:a2dp_config() a2dp_config: selected SEP 0x2982ca00
bluetoothd[8116]: profiles/audio/a2dp.c:setup_ref() 0x29825ed0: ref=3
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_set_configuration() 0x298480f0: int_seid=1, acp_seid=1
bluetoothd[8116]: profiles/audio/a2dp.c:setup_unref() 0x29825ed0: ref=2
bluetoothd[8116]: profiles/audio/a2dp.c:setup_unref() 0x29825ed0: ref=1
bluetoothd[8116]: profiles/audio/avdtp.c:session_cb()
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_parse_resp() SET_CONFIGURATION request succeeded
bluetoothd[8116]: profiles/audio/a2dp.c:setconf_cfm() Source 0x2982ca00: Set_Configuration_Cfm
bluetoothd[8116]: profiles/audio/a2dp.c:setup_ref() 0x29825ed0: ref=2
bluetoothd[8116]: profiles/audio/media.c:media_endpoint_async_call() Calling SetConfiguration: name = :1.3 path = /MediaEndpoint/A2DPSource
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_sep_set_state() stream state changed: IDLE -> CONFIGURED
bluetoothd[8116]: profiles/audio/a2dp.c:setup_unref() 0x29825ed0: ref=1
bluetoothd[8116]: profiles/audio/avdtp.c:session_cb()
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_parse_resp() OPEN request succeeded
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_connect_cb() AVDTP: connected transport channel to 28:37:13:B0:F1:D7
bluetoothd[8116]: profiles/audio/avdtp.c:handle_transport_connect() Flushable packets enabled
bluetoothd[8116]: profiles/audio/avdtp.c:handle_transport_connect() sk 20, omtu 672, send buffer size 114688
bluetoothd[8116]: profiles/audio/a2dp.c:open_cfm() Source 0x2982ca00: Open_Cfm
bluetoothd[8116]: profiles/audio/a2dp.c:setup_unref() 0x29825ed0: ref=0
bluetoothd[8116]: profiles/audio/a2dp.c:setup_free() 0x29825ed0
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_unref() 0x298480f0: ref=1
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_sep_set_state() stream state changed: CONFIGURED -> OPEN
bluetoothd[8116]: src/service.c:change_state() 0x29829e80: device 28:37:13:B0[ 4785.589898] input: 28:37:13:B0:F1:D7 as /devices/virtual/input/input8
:F1:D7 profile a2dp-sink state changed: connecting -> connected (0)
bluetoothd[8116]: src/device.c:device_profile_connected() a2dp-sink Success (0)
bluetoothd[8116]: profiles/audio/a2dp.c:a2dp_source_connect() path /org/bluez/hci0/dev_28_37_13_B0_F1_D7
bluetoothd[8116]: profiles/audio/avdtp.c:avdtp_ref() 0x298480f0: ref=2
bluetoothd[8116]: a2dp-source profile connect failed for 28:37:13:B0:F1:D7: Device or resource busy
bluetoothd[8116]: src/device.c:device_profile_connected() returning response to :1.10
bluetoothd[8116]: plugins/policy.c:policy_connect() /org/bluez/hci0/dev_28_37_13_B0_F1_D7 profile avrcp-controller
bluetoothd[8116]: profiles/audio/avrcp.c:avrcp_connect() path /org/bluez/hci0/dev_28_37_13_B0_F1_D7
bluetoothd[8116]: profiles/audio/avctp.c:avctp_set_state() AVCTP Connecting
bluetoothd[8116]: src/service.c:change_state() 0x298286c0: device 28:37:13:B0:F1:D7 profile avrcp-controller state changed: disconnected -> connecting (0)
Connection successful
[HUAWEI CM510]# bluetoothd[8116]: plugins/policy.c:service_cb() Added a2dp-sink reconnect 0
bluetoothd[8116]: profiles/audio/sink.c:sink_set_state() State changed /org/bluez/hci0/dev_28_37_13_B0_F1_D7: SINK_STATE_CONNECTING -> SINK_STATE_CONNECTED
bluetoothd[8116]: profiles/audio/transport.c:transport_update_playing() /org/bluez/hci0/dev_28_37_13_B0_F1_D7/fd4 State=TRANSPORT_STATE_IDLE Playing=0
bluetoothd[8116]: profiles/audio/avctp.c:avctp_connect_cb() AVCTP: connected to 28:37:13:B0:F1:D7
bluetoothd[8116]: profiles/audio/avctp.c:init_uinput() AVRCP: uinput initialized for 28:37:13:B0:F1:D7
bluetoothd[8116]: profiles/audio/avrcp.c:controller_init() 0x2982f220 version 0x0000
bluetoothd[8116]: src/service.c:change_state() 0x298457c0: device 28:37:13:B0:F1:D7 profile audio-avrcp-target state changed: disconnected -> connected (0)
bluetoothd[8116]: profiles/audio/avrcp.c:target_init() 0x2985d0e0 version 0x0106
bluetoothd[8116]: src/service.c:change_state() 0x298286c0: device 28:37:13:B0:F1:D7 profile avrcp-controller state changed: connecting -> connected (0)
bluetoothd[8116]: src/device.c:device_profile_connected() avrcp-controller Success (0)
bluetoothd[8116]: profiles/audio/avctp.c:avctp_set_state() AVCTP Browsing Connecting
bluetoothd[8116]: profiles/audio/avctp.c:avctp_set_state() AVCTP Connected
bluetoothd[8116]: profiles/audio/avrcp.c:handle_vendordep_pdu() AVRCP PDU 0x10, company 0x001958 len 0x0001
bluetoothd[8116]: profiles/audio/avrcp.c:avrcp_handle_get_capabilities() id=3
bluetoothd[8116]: profiles/audio/avctp.c:avctp_connect_browsing_cb() AVCTP Browsing: connected to 28:37:13:B0:F1:D7
bluetoothd[8116]: profiles/audio/avctp.c:avctp_set_state() AVCTP Browsing Connected
bluetoothd[8116]: profiles/audio/avrcp.c:handle_vendordep_pdu() AVRCP PDU 0x31, company 0x001958 len 0x0005
bluetoothd[8116]: src/device.c:search_cb() 28:37:13:B0:F1:D7: No service update
bluetoothd[8116]: src/device.c:device_svc_resolved() /org/bluez/hci0/dev_28_37_13_B0_F1_D7 err 0
[CHG] Device 28:37:13:B0:F1:D7 ServicesResolved: yes


这里因为在启动 bluetoothd 时添加了 -d 选项,所以导致这里 debug 信息比较多,但是也能帮助我们在出现问题的时候快速定位。看自己需要是否进行输出显示咯。


从 终端最后的消息可以看到蓝牙音响设备成功连接了,这里也可以使用 hcitool -i hci0 con 来查看:


# hcitool -i hci0 con
Connections:
        < ACL 28:37:13:B0:F1:D7 handle 11 state 1 lm MASTER AUTH ENCRYPT


音频播放

由于我的 aplay 编译的时候可能存在问题,所以即使蓝牙音响已经成功连接,但是 aplay 依然查找不到有新的声卡设备,如下:

13b8a60709ed4132bf42a11808df7f56.png

但是通过 pulseaudio 的工具 pactl 可以查找到有蓝牙声卡设备,这时候除了 aplay 播放工具之外,paplayer 和 mpg123 等音频播放工具都可以正常播放音频文件

8d6301c21f1d44de96c15ceaa49e6fa7.png

# paplay dx.wav


我是使用的 paplay 工具进行播放的。


此外,还可以通过 pacmd 工具进行音量的设置和缓冲音频文件、播放音频等操作,具体可以通过 pacmd help 查看帮助信息完成


#pacmd set-sink-volume 0 10000  #左声道
#pacmd set-sink-volume 1 10000  #右声道
# pacmd dump-volumes
Sink 0: reference = front-left: 15000 /  23% / -38.42 dB,   front-right: 15000 /  23% / -38.42 dB, real = front-left: 15000 /  23% / -38.42 dB,   front-right: 15000 /  23% / -38.42 dB, soft = front-left: 15000 /  23% / -38.42 dB,   front-right: 15000 /  23% / -38.42 dB, current_hw = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, save = yes
Sink 3: reference = front-left: 12000 /  18% / -44.24 dB,   front-right: 12000 /  18% / -44.24 dB, real = front-left: 12000 /  18% / -44.24 dB,   front-right: 12000 /  18% / -44.24 dB, soft = front-left: 12000 /  18% / -44.24 dB,   front-right: 12000 /  18% / -44.24 dB, current_hw = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, save = yes
Source 0: reference = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, real = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, soft = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, current_hw = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, save = no
Source 1: reference = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, real = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, soft = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, current_hw = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, save = no
Source 6: reference = front-left: 10000 /  15% / -48.99 dB,   front-right: 10000 /  15% / -48.99 dB, real = front-left: 10000 /  15% / -48.99 dB,   front-right: 10000 /  15% / -48.99 dB, soft = front-left: 10000 /  15% / -48.99 dB,   front-right: 10000 /  15% / -48.99 dB, current_hw = front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB, save = yes
# pacmd set-sink-volume 3 15000


问题记录

  • 如 果 出 现 类 似 的 错 误 :“ main.c: Failed to acquire org.pulseaudio.Server:

org.freedesktop.DBus.Error.AccessDenied: Connection “:1.46” is not allowed to own the service

“org.pulseaudio.Server” due to security policies in the configuration file ”, 需 要 在

/etc/dbus-1/system.d/pulseaudio-system.conf ( 此 文 件 来 之 于 <pulseaudio-x.y>/src/daemon/

pulseaudio-system.conf)中添加如下内容。如果以普通用户运行 pulseaudio,在这个文件中为

普通用户添加一个 policy,内容和 root 用户类似。

<?xml version="1.0"?><!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<!--
This file is part of PulseAudio.
PulseAudio is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
-->
<busconfig>
  <!-- System-wide PulseAudio runs as 'pulse' user. This fragment is
       not necessary for user PulseAudio instances. -->
  <policy user="pulse">
    <allow own="org.pulseaudio.Server"/>
    <allow send_destination="org.bluez"/>
    <allow send_interface="org.bluez.Manager"/>
  </policy>
  <policy user="pulse">
    <allow own="org.pulseaudio.Server"/>
    <allow send_destination="org.bluez"/>
    <allow send_interface="org.bluez.Manager"/>
  </policy>
  <policy context="default">
    <deny own="org.pulseaudio.Server"/>
    <deny send_destination="org.bluez"/>
    <deny send_interface="org.bluez.Manager"/>
  </policy>
</busconfig>



相关文章
H8
|
9月前
|
物联网 数据安全/隐私保护 智能硬件
女朋友问: 你知道蓝牙耳机的原理吗?
蓝牙是一种无线通讯技术标准,用来让固定与移动设备,在短距离间交换资料,以形成个人局域网(PAN)。其使用短波特高频(UHF)无线电波,经由2.4至2.485GHz的ISM频段来进行通信。1994年由电信商(Ericsson)发展出这个技术。它最初的设计,是希望创建一个RS-232数据线的无线通信替代版本。
H8
356 0
|
Linux 网络安全
树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)
树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)
树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)
|
C语言
bluez5.50蓝牙文件传输
bluez5.50蓝牙文件传输
610 0
bluez5.50蓝牙文件传输
|
Java Android开发 C++
|
Java 开发工具 Android开发
利用MCU实现制作一台蓝牙控制小车方法
今天主要和大家分享一下,如何使用MCU自己做一台蓝牙小车,并通过自己写的APP进行控制。
156 0
利用MCU实现制作一台蓝牙控制小车方法
|
传感器 移动开发 监控
蓝牙插座解决方案|学习笔记
快速学习蓝牙插座解决方案
146 0
蓝牙插座解决方案|学习笔记
|
Android开发
STM32+HC05串口蓝牙设计简易的蓝牙音箱
STM32+HC05串口蓝牙设计简易的蓝牙音箱
470 0
STM32+HC05串口蓝牙设计简易的蓝牙音箱
|
Android开发
问题:安卓手机插入OTG摄像头时,如何禁用摄像头自带的MIC?
问题:安卓手机插入OTG摄像头时,如何禁用摄像头自带的MIC?
181 0
|
物联网 开发工具 Android开发