蓝牙连接失败,使用 bluetoothctl 命令
Posted
技术标签:
【中文标题】蓝牙连接失败,使用 bluetoothctl 命令【英文标题】:bluetooth connection fail with bluetoothctl command 【发布时间】:2018-11-27 01:38:43 【问题描述】:我在Vmware环境下的Ubuntu下尝试了蓝牙连接测试。 Ubuntu 是 14.04 lts,蓝牙是 USB-dongle,BT 堆栈是 Bluez 5.35。 我不使用pulseaudio。
我使用 bluetoothctl 命令进行扫描、配对和连接。 但是连接失败。下面是bluetoothctl的日志
$ sudo bluetoothctl
[bluetooth]# power on
[bluetooth]# show
Controller 00:1A:7D:DA:xx:xx (public)
Name: ubuntu
Alias: ubuntu-0
Class: 0x00000000
Powered: yes
Discoverable: no
Pairable: yes
UUID: Generic Attribute Profile (00001801-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)
Modalias: usb:v1D6Bp0246d0532
Discovering: no
[bluetooth]# scan on // Wait until found BT headset
[bluetooth]# scan off
[bluetooth]# devices
Device 11:11:22:xx:xx:xx Test
Device 0C:E0:E4:xx:xx:xx PLT_Legend
[bluetooth]# pair 0C:E0:E4:xx:xx:xx // try pairing with 0C:E0:E4:xx:xx:xx
Attempting to pair with 0C:E0:E4:xx:xx:xx
[CHG] Device 0C:E0:E4:xx:xx:xx Connected: yes
[PLT_Legend]# interfaces_added
[CHG] Device 0C:E0:E4:xx:xx:xx Modalias: bluetooth:v0055p0113d0067
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 0C:E0:E4:xx:xx:xx UUIDs: 82972387-294e-4d62-97b5-2668aa35f618
[CHG] Device 0C:E0:E4:xx:xx:xx ServicesResolved: yes
[CHG] Device 0C:E0:E4:xx:xx:xx Paired: yes
Pairing successful
[CHG] Device 0C:E0:E4:xx:xx:xx ServicesResolved: no
[CHG] Device 0C:E0:E4:xx:xx:xx Connected: no
[PLT_Legend]# connect 0C:E0:E4:xx:xx:xx
Attempting to connect to 0C:E0:E4:xx:xx:xx
[CHG] Device 0C:E0:E4:xx:xx:xxConnected: yes
Failed to connect: org.bluez.Error.Failed
我发现上面的 bluez 没有 a2dp 配置文件。 实际上,bluez5.x 和pulseaudio 是紧密结合的。如果不使用 pulseaudio,用户必须添加额外的配置文件(a2dp 或 hspag)。
以下代码是添加 a2dpsink 、 a2dpsource 和 haspag 的示例。
#define A2DP_SOURCE_ENDPOINT "/MediaEndpoint/A2DPSource"
#define A2DP_SINK_ENDPOINT "/MediaEndpoint/A2DPSink"
#define HSP_AG_PROFILE "/Profile/HSPAGProfile"
#define PA_BLUETOOTH_UUID_HSP_AG "00001112-0000-1000-8000-00805f9b34fb"
#define PA_BLUETOOTH_UUID_A2DP_SOURCE "0000110a-0000-1000-8000-00805f9b34fb"
#define PA_BLUETOOTH_UUID_A2DP_SINK "0000110b-0000-1000-8000-00805f9b34fb"
static void register_profile_reply(DBusPendingCall *call, void *user_data)
//struct bluetooth_profile *profile = user_data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
DBusError derr;
dbus_error_init(&derr);
if (!dbus_set_error_from_message(&derr, reply))
printf("Profile %s registered", (char *)user_data);
goto done;
//unregister_profile(profile);
printf("bluetooth: RequestProfile error: %s, %s", derr.name,
derr.message);
dbus_error_free(&derr);
done:
dbus_message_unref(reply);
static DBusConnection *connection;
void btd_profile_add_hspag(const char *profile, const char *uuid)
DBusMessage *msg;
DBusMessageIter iter, opt;
DBusPendingCall *call;
connection = btd_get_dbus_connection();
msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
"org.bluez.ProfileManager1",
"RegisterProfile");
if( msg == NULL )
printf("%s : msg is null \n", __func__);
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &profile);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uuid);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
DBUS_TYPE_STRING_AS_STRING
DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
&opt);
dbus_message_iter_close_container(&iter, &opt);
if (!g_dbus_send_message_with_reply(connection, msg, &call, -1))
printf("%s:%s - fail g_dbus_send_message_with_reply() \n", __FILE__, __func__);
//unregister_profile(profile);
goto failed;
dbus_pending_call_set_notify(call, register_profile_reply, &profile,
NULL);
dbus_pending_call_unref(call);
failed:
dbus_message_unref(msg);
return;
void btd_profile_add(void)
btd_profile_add_hspag(HSP_AG_PROFILE, PA_BLUETOOTH_UUID_HSP_AG);
btd_profile_add_hspag(A2DP_SOURCE_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SOURCE);
btd_profile_add_hspag(A2DP_SINK_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SINK);
在那之后,bluez 有了 a2dp、hspag 配置文件,没有 pulseaudio。 我可以用 bluetoothctl 的“show”命令查看。
[bluetooth]# show
Controller 00:1A:7D:xx:xx:xx
Name: ubuntu
Alias: ubuntu-0
Class: 0x000000
Powered: yes
Discoverable: no
Pairable: yes
UUID: Headset AG (00001112-0000-1000-8000-00805f9b34fb)
UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb)
UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb)
UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb)
UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)
UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb)
UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
Modalias: usb:v1D6Bp0246d0523
Discovering: no
即使添加了 a2dp 配置文件,蓝牙连接仍然失败。 通过btmon trace,断开了rfcomm的连接,接下来,l2cap的连接也断开了。 我不知道我错过了什么。 在没有pulseaudio的情况下运行bluez 5.35我还需要什么?
【问题讨论】:
【参考方案1】:日志显示您的“PLT_Legend”设备支持 A2DP SINK 角色,因此您的 Ubuntu 应充当 A2DP SOURCE 角色。要使其工作,您需要一个工作配置文件实现。
您可能不需要完全实现 A2DP 源配置文件来获取音频数据,但至少您需要注册基本功能才能让 bluetoothd 满意。
下图直接复制自here。
在上面的序列中,您可以看到蓝牙在连接具有 A2DP 功能的新设备时调用“SelectConfiguration”和“SetConfiguration”。
正如您所观察到的,连接状态最初移动到已连接,然后回退到“否”。这是因为,bluetoothd 在获得低级连接后会尝试与配置文件(SDP 服务发现协议)进行连接。低级连接成功后,设备被标记为已连接,SDP 继续进行。
在 SDP 期间,bluetoothd 尝试获取您的设备(在本例中为 ubuntu)的功能,并使用“SelectConfiguration”与终端设备 (PLT_Legend) 就编解码器支持进行协商,并使用“SetConfiguration”选择一个。握手成功后,蓝牙标记 A2DP 配置文件已连接。
因此,使用您的配置文件的虚拟注册,由于它找不到方法并且正确的编解码器返回,它标志着连接失败并终止 Ubuntu 和设备之间的连接。
如果您不想使用 pulseaudio,可以尝试使用 bluez-alsa https://github.com/Arkq/bluez-alsa 并开始收听 A2DP 配置文件。我认为这个包已经在 ubuntu repo 中可用了,你可以试试
sudo apt-get install bluez-alsa
AFAIK,pulseaudio 没有与蓝牙紧密绑定,你仍然可以以蓝牙理解的方式实现自己的 A2DP 实现。
注意,bluez-alsa 使用开源 fdk-aac 进行 AAC 编码和解码。
【讨论】:
以上是关于蓝牙连接失败,使用 bluetoothctl 命令的主要内容,如果未能解决你的问题,请参考以下文章
[BlueZ] 2使用bluetoothctl搜索连接配对读写使能notify蓝牙低功耗设备