aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/qt-ble.cpp102
-rw-r--r--core/qt-ble.h6
2 files changed, 80 insertions, 28 deletions
diff --git a/core/qt-ble.cpp b/core/qt-ble.cpp
index d84c223c2..f467e6083 100644
--- a/core/qt-ble.cpp
+++ b/core/qt-ble.cpp
@@ -100,20 +100,6 @@ void BLEObject::writeCompleted(const QLowEnergyDescriptor&, const QByteArray&)
void BLEObject::addService(const QBluetoothUuid &newService)
{
qDebug() << "Found service" << newService;
- bool isStandardUuid = false;
- newService.toUInt16(&isStandardUuid);
- if (IS_HW(device)) {
- /* The HW BT/BLE piece or hardware uses, what we
- * call here, "a Standard UUID. It is standard because the Telit/Stollmann
- * manufacturer applied for an own UUID for its product, and this was granted
- * by the Bluetooth SIG.
- */
- if (newService != QUuid("{0000fefb-0000-1000-8000-00805f9b34fb}"))
- return; // skip all services except the right one
- } else if (isStandardUuid) {
- qDebug () << " .. ignoring standard service";
- return;
- }
auto service = controller->createServiceObject(newService, this);
qDebug() << " .. created service object" << service;
@@ -201,6 +187,80 @@ dc_status_t BLEObject::read(void *data, size_t size, size_t *actual)
return DC_STATUS_SUCCESS;
}
+//
+// select_preferred_service() gets called after all services
+// have been discovered, and the discovery process has been
+// started (by addService(), which calls service->discoverDetails())
+//
+// The role of this function is to wait for all service
+// discovery to finish, and pick the preferred service.
+//
+// NOTE! Picking the preferred service is divecomputer-specific.
+// Right now we special-case the HW known service number, but for
+// others we just pick the first one that isn't a standard service.
+//
+// That's wrong, but works for the simple case.
+//
+dc_status_t BLEObject::select_preferred_service(void)
+{
+ QLowEnergyService *s;
+
+ // Wait for each service to finish discovering
+ foreach (s, services) {
+ WAITFOR(s->state() != QLowEnergyService::DiscoveringServices, BLE_TIMEOUT);
+ }
+
+ // Print out the services for debugging
+ foreach (s, services) {
+ qDebug() << "Found service" << s->serviceUuid() << s->serviceName();
+
+ QLowEnergyCharacteristic c;
+ foreach (c, s->characteristics()) {
+ qDebug() << " c:" << c.uuid();
+
+ QLowEnergyDescriptor d;
+ foreach (d, c.descriptors())
+ qDebug() << " d:" << d.uuid();
+ }
+ }
+
+ // Pick the preferred one
+ foreach (s, services) {
+ if (s->state() != QLowEnergyService::ServiceDiscovered)
+ continue;
+
+ bool isStandardUuid = false;
+ QBluetoothUuid uuid = s->serviceUuid();
+
+ uuid.toUInt16(&isStandardUuid);
+
+ if (IS_HW(device)) {
+ /* The HW BT/BLE piece or hardware uses, what we
+ * call here, "a Standard UUID. It is standard because the Telit/Stollmann
+ * manufacturer applied for an own UUID for its product, and this was granted
+ * by the Bluetooth SIG.
+ */
+ if (uuid != QUuid("{0000fefb-0000-1000-8000-00805f9b34fb}"))
+ continue; // skip all services except the right one
+ } else if (isStandardUuid) {
+ qDebug () << " .. ignoring standard service" << uuid;
+ continue;
+ }
+
+ preferred = s;
+ qDebug() << "Using service" << s->serviceUuid() << "as preferred service";
+ break;
+ }
+
+ if (!preferred) {
+ qDebug() << "failed to find suitable service";
+ report_error("Failed to find suitable BLE GATT service");
+ return DC_STATUS_IO;
+ }
+
+ return DC_STATUS_SUCCESS;
+}
+
dc_status_t BLEObject::setHwCredit(unsigned int c)
{
/* The Terminal I/O client transmits initial UART credits to the server (see 6.5).
@@ -341,24 +401,16 @@ dc_status_t qt_ble_open(void **io, dc_context_t *, const char *devaddr, dc_user_
WAITFOR(controller->state() != QLowEnergyController::DiscoveringState, BLE_TIMEOUT);
qDebug() << " .. done discovering services";
- if (ble->preferredService() == nullptr) {
- qDebug() << "failed to find suitable service on" << devaddr;
- report_error("Failed to find suitable service on '%s'", devaddr);
- delete ble;
- return DC_STATUS_IO;
- }
- qDebug() << " .. discovering details";
- WAITFOR(ble->preferredService()->state() != QLowEnergyService::DiscoveringServices, BLE_TIMEOUT);
+ dc_status_t error = ble->select_preferred_service();
- if (ble->preferredService()->state() != QLowEnergyService::ServiceDiscovered) {
+ if (error != DC_STATUS_SUCCESS) {
qDebug() << "failed to find suitable service on" << devaddr;
report_error("Failed to find suitable service on '%s'", devaddr);
delete ble;
- return DC_STATUS_IO;
+ return error;
}
-
qDebug() << " .. enabling notifications";
/* Enable notifications */
diff --git a/core/qt-ble.h b/core/qt-ble.h
index 5b3991bef..ddf628e60 100644
--- a/core/qt-ble.h
+++ b/core/qt-ble.h
@@ -23,9 +23,8 @@ public:
dc_status_t write(const void* data, size_t size, size_t *actual);
dc_status_t read(void* data, size_t size, size_t *actual);
- //TODO: need better mode of selecting the desired service than below
- inline QLowEnergyService *preferredService()
- { return services.isEmpty() ? nullptr : services[0]; }
+ inline QLowEnergyService *preferredService() { return preferred; }
+ dc_status_t select_preferred_service(void);
public slots:
void addService(const QBluetoothUuid &newService);
@@ -39,6 +38,7 @@ private:
QVector<QLowEnergyService *> services;
QLowEnergyController *controller = nullptr;
+ QLowEnergyService *preferred = nullptr;
QList<QByteArray> receivedPackets;
bool isCharacteristicWritten;
dc_user_device_t *device;