由于蓝牙,BlueZ 在使用 SDP 进行广告时无法接受传入连接
BlueZ unable to accept incoming connection while advertising with SDP due to bluetoothd
我正在尝试使用 Pi 来模拟使用 BlueZ C 的蓝牙设备 api。我能够分别 1) 配置 SDP 服务器以通告正确的服务和 2) 监听并建立 L2CAP 连接。但是,我无法同时进行这两项操作。
问题是 sdp_record_register() will segfault unless bluetoothd
is both running and in compatibility mode. However, accept() won't return for the Bluetooth socket 如果 bluetoothd
是 运行,因为 bluetoothd
会窃取请求。
所以我可以:
- Register/advertise 我的服务使用 SDP,但无法接受传入连接,运行
bluetoothd
(在兼容模式下)。
- 能够接受传入连接,但不能register/advertise我的服务,不运行
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()
永远不会 return ](在任何模式下)。
我一直无法调和这两个问题。看起来理想的解决方案是以某种方式告诉 bluetoothd
忽略 PSM 0x11 上的连接(因为这意味着它的代理仍然可以处理配对),但我不知道该怎么做。
(不令人满意但正确的)答案是不使用 hci*
API。 API 显然已被弃用,因此不会修复像段错误这样的错误。正确的做法是使用 DBus API。 API 几乎和 hci
API 一样麻烦,但至少有文档记录。
在换掉我用 glib-2.0 提供的 gdbus API 编写的大量基于 hci
的代码来设置 SDP 服务之后,我终于可以做广告了服务并同时连接。我的套接字代码无需修改即可工作。
我正在尝试使用 Pi 来模拟使用 BlueZ C 的蓝牙设备 api。我能够分别 1) 配置 SDP 服务器以通告正确的服务和 2) 监听并建立 L2CAP 连接。但是,我无法同时进行这两项操作。
问题是 sdp_record_register() will segfault unless bluetoothd
is both running and in compatibility mode. However, accept() won't return for the Bluetooth socket 如果 bluetoothd
是 运行,因为 bluetoothd
会窃取请求。
所以我可以:
- Register/advertise 我的服务使用 SDP,但无法接受传入连接,运行
bluetoothd
(在兼容模式下)。 - 能够接受传入连接,但不能register/advertise我的服务,不运行
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()
永远不会 return ](在任何模式下)。
我一直无法调和这两个问题。看起来理想的解决方案是以某种方式告诉 bluetoothd
忽略 PSM 0x11 上的连接(因为这意味着它的代理仍然可以处理配对),但我不知道该怎么做。
(不令人满意但正确的)答案是不使用 hci*
API。 API 显然已被弃用,因此不会修复像段错误这样的错误。正确的做法是使用 DBus API。 API 几乎和 hci
API 一样麻烦,但至少有文档记录。
在换掉我用 glib-2.0 提供的 gdbus API 编写的大量基于 hci
的代码来设置 SDP 服务之后,我终于可以做广告了服务并同时连接。我的套接字代码无需修改即可工作。