Я пытаюсь использовать Pi для эмуляции устройства Bluetooth с использованием API BlueZ C. Я могу отдельно 1) настроить сервер SDP для объявления правильной услуги и 2) прослушать и установить sh соединение L2CAP. Тем не менее, я не могу сделать и то и другое одновременно.
Проблема в том, что sdp_record_register () будет вызывать ошибку , если bluetoothd
не запущен и не находится в режиме совместимости. Однако accept () не вернется для сокета Bluetooth , если bluetoothd
работает, потому что bluetoothd
украдет запрос.
Так что я могу либо:
- Зарегистрировать / прорекламировать мой сервис с помощью SDP, но не иметь возможности принимать входящие соединения, запустив
bluetoothd
(в режиме совместимости). - Возможность принимать входящие соединения, но не может регистрировать / рекламировать мою службу, не запуская
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
работает в режиме совместимости, но будет зависать, если он не работает или не работает в режиме по умолчанию.
Принятие соединения Bluetooth
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
не запущено, но accept()
никогда не вернется, если bluetoothd
работает (в любом режиме).
Мне не удалось решить эти две проблемы. Кажется, что идеальным решением было бы как-то сказать bluetoothd
игнорировать соединения на PSM 0x11 (поскольку это означает, что его агент все еще может обрабатывать сопряжение), но я не могу понять, как это сделать.