【发布时间】:2020-04-13 06:35:11
【问题描述】:
我正在尝试使用 Pi 来模拟使用 BlueZ C api 的蓝牙设备。我能够单独 1)配置 SDP 服务器以宣传正确的服务,以及 2)侦听并建立 L2CAP 连接。但是,我无法同时进行这两项操作。
问题是sdp_record_register() will segfault 除非bluetoothd 正在运行并处于兼容模式。然而,accept() won't return for the Bluetooth socket 如果bluetoothd 正在运行,因为bluetoothd 会窃取请求。
所以我可以:
- 通过运行
bluetoothd(在兼容模式下)向 SDP 注册/宣传我的服务,但无法接受传入连接。 - 通过不运行
bluetoothd,能够接受传入连接,但无法注册/宣传我的服务。
设置 SDP 服务
int deviceID = hci_get_route(NULL);
if (deviceID < 0) {
printf("Error: Bluetooth device not found\n");
exit(1);
}
int bluetoothHCISocket = hci_open_dev(deviceID);
if (bluetoothHCISocket < 0) {
perror("hci_open_device");
exit(2);
}
/* some HCI config */
sdp_session_t *session = sdp_connect(&myBDAddrAny, &myBDAddrLocal, SDP_RETRY_IF_BUSY);
sdp_record_t record;
bzero(&record, sizeof(sdp_record_t));
record.handle = 0x10000;
/* register all of the attributes for my service */
printf("Might segfault\n");
if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
perror("sdp_record_register");
exit(7);
}
printf("Didn't segfault\n");
这在bluetoothd 以兼容模式运行时有效,但当它未运行或以默认模式运行时会出现段错误。
接受蓝牙连接
int btSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
if (btSocket < 0) {
perror("socket");
exit(3);
}
struct sockaddr_l2 loc_addr = { 0 };
loc_addr.l2_family = AF_BLUETOOTH;
loc_addr.l2_bdaddr = myBDAddrAny;
loc_addr.l2_psm = htobs(0x11);
if (bind(btSocket, (struct sockaddr *)&loc_addr, sizeof(loc_addr))) {
perror("bind");
exit(4);
}
if (listen(btSocket, 1)) {
perror("listen");
exit(6);
}
struct sockaddr_l2 remoteAddress;
socklen_t socketSize = sizeof(remoteAddress);
printf("Waiting for connection\n");
int clientSocket = accept(btSocket, (struct sockaddr *)&remoteAddress, &socketSize);
这将在bluetoothd 未运行时正确接受传入连接,但如果bluetoothd 正在运行(在任何模式下),accept() 将永远不会返回。
我一直无法调和这两个问题。似乎理想的解决方案是以某种方式告诉bluetoothd 忽略 PSM 0x11 上的连接(因为这意味着它的代理仍然可以处理配对),但我不知道该怎么做。
【问题讨论】:
标签: c bluetooth raspberry-pi bluez