Bluetooth scan failure on service discovery start
-
I'm learning about Bluetooth (on Linux), and I tried the BtChat app. It fails to work, reporting "qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3" when I scan for peers. Looks like Service discovery agent isn't working.
I tried the BtScanner app and while it can find devices (Device discovery agent), it does not find any services for any selected device (Service discovery agent isn't working).
So I tried to create a simple Bt scanner based on the above examples. I paired BTChat down to the basics to just print out what it finds (no UUID filtering). I'm running Qt 5.15.2 on Kubuntu 23 64-bit.
Although it runs, the discovery seems stalled for a minute or more when it first starts, as the first 3 errors print out (below). It might repeat this error and give up, or after a minute start printing out discovered services.
What is causing the "SDP scan failure" error? and long delay. I have tried this on 2 differnt Linux PC's with the same result. I found reference to this bug (https://bugreports.qt.io/browse/QTBUG-53041) but I'm not sure if that's the cause since it shows resolved as of Qt 5.7.1. And there is this almost identical question (https://forum.qt.io/topic/80849/qt-bluetooth-bluez-sdp-scan-failure-qprocess-exitstatus-normalexit-3 ) but there is no answer...
Starting discovery qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3 qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3 qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3 Discovered service on "58-B0-2D-4F-71-2E" "58:B0:2D:4F:71:2E" Service name: "" Description: "" Provider: "" L2CAP protocol service multiplexer: 31 RFCOMM server channel: -1 Discovered service on "58-B0-2D-4F-71-2E" "58:B0:2D:4F:71:2E" Service name: "" Description: "" Provider: "" L2CAP protocol service multiplexer: 31
In case it matters, here's the class:
#include "bt.h" #include <QtBluetooth/qbluetoothdeviceinfo.h> #include <QtBluetooth/qbluetoothlocaldevice.h> #include <QtBluetooth/qbluetoothuuid.h> static const QUuid serviceUuid = QUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8"); BlueToothController::BlueToothController() { } BlueToothController::~BlueToothController() { // Ensure no discovery is running stopDiscovery(); } void BlueToothController::setupLocalDevice() { // Get a list of all bluetooth devices (adapter) on this host localAdapters = QBluetoothLocalDevice::allDevices(); qDebug() << "Num adap found" << localAdapters.count(); // If no adapters found, clear name if (localAdapters.count() < 1) { qDebug() << "Few Num adap found" << localAdapters.count(); localName.clear(); localAddress = QBluetoothAddress(); } // Else power on and make the first adapter discoverable else { //we ignore more than two adapters QBluetoothLocalDevice adapter(localAdapters.at(0).address()); adapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable); QBluetoothLocalDevice().setHostMode(QBluetoothLocalDevice::HostDiscoverable); //add this localName = QBluetoothLocalDevice().name(); localAddress = localAdapters.at(0).address(); } } void BlueToothController::startDiscovery(const QBluetoothUuid &uuid) { qDebug() << "Starting discovery"; m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(localAddress); connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, this, &BlueToothController::serviceDiscovered); connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, this, &BlueToothController::discoveryFinished); connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::canceled, this, &BlueToothController::discoveryFinished); // If already running then abort current discovery if (m_discoveryAgent->isActive()) m_discoveryAgent->stop(); // m_discoveryAgent->setUuidFilter(uuid); // Force full discovery (don't use SDP cache only) m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); // m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery); } void BlueToothController::stopDiscovery() { if (m_discoveryAgent == nullptr) return; m_discoveryAgent->stop(); delete m_discoveryAgent; m_discoveryAgent = nullptr; } void BlueToothController::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) { qDebug() << "Discovered service on device.name " << serviceInfo.device().name() << " address " << serviceInfo.device().address().toString(); qDebug() << "\tService name:" << serviceInfo.serviceName(); qDebug() << "\tService UUID:" << serviceInfo.serviceUuid(); qDebug() << "\tService Class UUIDs:" << serviceInfo.serviceClassUuids(); qDebug() << "\tDescription:" << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); qDebug() << "\tProvider:" << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); qDebug() << "\tL2CAP protocol service multiplexer:" << serviceInfo.protocolServiceMultiplexer(); qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); const QBluetoothAddress address = serviceInfo.device().address(); for (const QBluetoothServiceInfo &info : std::as_const(m_discoveredServices)) { if (info.device().address() == address) return; } QString remoteName; if (serviceInfo.device().name().isEmpty()) remoteName = address.toString(); else remoteName = serviceInfo.device().name(); m_discoveredServices.append(serviceInfo); } void BlueToothController::discoveryFinished() { qDebug() << ("Discovery finished"); }
-
I'm learning about Bluetooth (on Linux), and I tried the BtChat app. It fails to work, reporting "qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3" when I scan for peers. Looks like Service discovery agent isn't working.
I tried the BtScanner app and while it can find devices (Device discovery agent), it does not find any services for any selected device (Service discovery agent isn't working).
So I tried to create a simple Bt scanner based on the above examples. I paired BTChat down to the basics to just print out what it finds (no UUID filtering). I'm running Qt 5.15.2 on Kubuntu 23 64-bit.
Although it runs, the discovery seems stalled for a minute or more when it first starts, as the first 3 errors print out (below). It might repeat this error and give up, or after a minute start printing out discovered services.
What is causing the "SDP scan failure" error? and long delay. I have tried this on 2 differnt Linux PC's with the same result. I found reference to this bug (https://bugreports.qt.io/browse/QTBUG-53041) but I'm not sure if that's the cause since it shows resolved as of Qt 5.7.1. And there is this almost identical question (https://forum.qt.io/topic/80849/qt-bluetooth-bluez-sdp-scan-failure-qprocess-exitstatus-normalexit-3 ) but there is no answer...
Starting discovery qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3 qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3 qt.bluetooth.bluez: SDP scan failure QProcess::NormalExit 3 Discovered service on "58-B0-2D-4F-71-2E" "58:B0:2D:4F:71:2E" Service name: "" Description: "" Provider: "" L2CAP protocol service multiplexer: 31 RFCOMM server channel: -1 Discovered service on "58-B0-2D-4F-71-2E" "58:B0:2D:4F:71:2E" Service name: "" Description: "" Provider: "" L2CAP protocol service multiplexer: 31
In case it matters, here's the class:
#include "bt.h" #include <QtBluetooth/qbluetoothdeviceinfo.h> #include <QtBluetooth/qbluetoothlocaldevice.h> #include <QtBluetooth/qbluetoothuuid.h> static const QUuid serviceUuid = QUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8"); BlueToothController::BlueToothController() { } BlueToothController::~BlueToothController() { // Ensure no discovery is running stopDiscovery(); } void BlueToothController::setupLocalDevice() { // Get a list of all bluetooth devices (adapter) on this host localAdapters = QBluetoothLocalDevice::allDevices(); qDebug() << "Num adap found" << localAdapters.count(); // If no adapters found, clear name if (localAdapters.count() < 1) { qDebug() << "Few Num adap found" << localAdapters.count(); localName.clear(); localAddress = QBluetoothAddress(); } // Else power on and make the first adapter discoverable else { //we ignore more than two adapters QBluetoothLocalDevice adapter(localAdapters.at(0).address()); adapter.setHostMode(QBluetoothLocalDevice::HostDiscoverable); QBluetoothLocalDevice().setHostMode(QBluetoothLocalDevice::HostDiscoverable); //add this localName = QBluetoothLocalDevice().name(); localAddress = localAdapters.at(0).address(); } } void BlueToothController::startDiscovery(const QBluetoothUuid &uuid) { qDebug() << "Starting discovery"; m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(localAddress); connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, this, &BlueToothController::serviceDiscovered); connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, this, &BlueToothController::discoveryFinished); connect(m_discoveryAgent, &QBluetoothServiceDiscoveryAgent::canceled, this, &BlueToothController::discoveryFinished); // If already running then abort current discovery if (m_discoveryAgent->isActive()) m_discoveryAgent->stop(); // m_discoveryAgent->setUuidFilter(uuid); // Force full discovery (don't use SDP cache only) m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); // m_discoveryAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery); } void BlueToothController::stopDiscovery() { if (m_discoveryAgent == nullptr) return; m_discoveryAgent->stop(); delete m_discoveryAgent; m_discoveryAgent = nullptr; } void BlueToothController::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) { qDebug() << "Discovered service on device.name " << serviceInfo.device().name() << " address " << serviceInfo.device().address().toString(); qDebug() << "\tService name:" << serviceInfo.serviceName(); qDebug() << "\tService UUID:" << serviceInfo.serviceUuid(); qDebug() << "\tService Class UUIDs:" << serviceInfo.serviceClassUuids(); qDebug() << "\tDescription:" << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); qDebug() << "\tProvider:" << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); qDebug() << "\tL2CAP protocol service multiplexer:" << serviceInfo.protocolServiceMultiplexer(); qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); const QBluetoothAddress address = serviceInfo.device().address(); for (const QBluetoothServiceInfo &info : std::as_const(m_discoveredServices)) { if (info.device().address() == address) return; } QString remoteName; if (serviceInfo.device().name().isEmpty()) remoteName = address.toString(); else remoteName = serviceInfo.device().name(); m_discoveredServices.append(serviceInfo); } void BlueToothController::discoveryFinished() { qDebug() << ("Discovery finished"); }
To help out others facing similar problems, here's what i have (tentatively) concluded:
The device/service discovery process uses an external program called sdpcanner, which is launched using QProcess. If the sdpscanner encounters a device/service which does not respond as expected it times out/crashes. That results in the error shown.
Qt discovery launces many sdpscanner procresses. If one succeeds it will respond with what it found. If none succeed, you get now discovered devices/services. (Not very reliable)
If someone knowledgeable can add to / correct the above please jump in.