summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2017-06-27 15:14:27 -0700
committerGravatar Linus Torvalds <torvalds@linux-foundation.org>2017-06-27 15:14:27 -0700
commit526595644fbef79aba53bc96f5e1507a13294805 (patch)
tree95180c8ccb8b15b8eb4ca0f1fcca2c969661ad66
parentd01b7bf89167ff8ab40c4b663398816da678084a (diff)
downloadsubsurface-526595644fbef79aba53bc96f5e1507a13294805.tar.gz
Use SSRF_CUSTOM_IO v2 to implement device data quirks for BLE GATT
Right now we have a quirk for Shearwater devices to set the random address flag, but also to handle the differences at read/write time. With this, I can finally download from both the Suunto EON Steel and the Shearwater Perdix AI with the same binary. It's not *pretty*, but it works. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--core/qt-ble.cpp25
-rw-r--r--core/qt-ble.h3
2 files changed, 23 insertions, 5 deletions
diff --git a/core/qt-ble.cpp b/core/qt-ble.cpp
index 85dd0b1d1..246b59ee9 100644
--- a/core/qt-ble.cpp
+++ b/core/qt-ble.cpp
@@ -80,9 +80,10 @@ void BLEObject::addService(const QBluetoothUuid &newService)
}
}
-BLEObject::BLEObject(QLowEnergyController *c)
+BLEObject::BLEObject(QLowEnergyController *c, dc_user_device_t *d)
{
controller = c;
+ device = d;
}
BLEObject::~BLEObject()
@@ -90,7 +91,13 @@ BLEObject::~BLEObject()
qDebug() << "Deleting BLE object";
}
-dc_status_t BLEObject::write(const void* data, size_t size, size_t *actual)
+/* Yeah, I could do the C++ inline member thing */
+static int device_is_shearwater(dc_user_device_t *device)
+{
+ return !strcmp(device->vendor, "Shearwater");
+}
+
+dc_status_t BLEObject::write(const void *data, size_t size, size_t *actual)
{
QList<QLowEnergyCharacteristic> list = preferredService()->characteristics();
QByteArray bytes((const char *)data, (int) size);
@@ -103,6 +110,9 @@ dc_status_t BLEObject::write(const void* data, size_t size, size_t *actual)
QLowEnergyService::WriteWithoutResponse :
QLowEnergyService::WriteWithResponse;
+ if (device_is_shearwater(device))
+ bytes.prepend("\1\0", 2);
+
preferredService()->writeCharacteristic(c, bytes, mode);
return DC_STATUS_SUCCESS;
}
@@ -110,7 +120,7 @@ dc_status_t BLEObject::write(const void* data, size_t size, size_t *actual)
return DC_STATUS_IO;
}
-dc_status_t BLEObject::read(void* data, size_t size, size_t *actual)
+dc_status_t BLEObject::read(void *data, size_t size, size_t *actual)
{
if (receivedPackets.isEmpty()) {
QList<QLowEnergyCharacteristic> list = preferredService()->characteristics();
@@ -133,6 +143,10 @@ dc_status_t BLEObject::read(void* data, size_t size, size_t *actual)
return DC_STATUS_IO;
QByteArray packet = receivedPackets.takeFirst();
+
+ if (device_is_shearwater(device))
+ packet.remove(0,2);
+
if (size > packet.size())
size = packet.size();
memcpy(data, packet.data(), size);
@@ -161,6 +175,9 @@ dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *d
qDebug() << "qt_ble_open(" << devaddr << ")";
+ if (device_is_shearwater(io->user_device))
+ controller->setRemoteAddressType(QLowEnergyController::RandomAddress);
+
// Try to connect to the device
controller->connectToDevice();
@@ -184,7 +201,7 @@ dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *d
}
/* We need to discover services etc here! */
- BLEObject *ble = new BLEObject(controller);
+ BLEObject *ble = new BLEObject(controller, io->user_device);
ble->connect(controller, SIGNAL(serviceDiscovered(QBluetoothUuid)), SLOT(addService(QBluetoothUuid)));
qDebug() << " .. discovering services";
diff --git a/core/qt-ble.h b/core/qt-ble.h
index cd27423a4..247f7d64c 100644
--- a/core/qt-ble.h
+++ b/core/qt-ble.h
@@ -11,7 +11,7 @@ class BLEObject : public QObject
Q_OBJECT
public:
- BLEObject(QLowEnergyController *c);
+ BLEObject(QLowEnergyController *c, dc_user_device_t *);
~BLEObject();
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);
@@ -32,6 +32,7 @@ private:
QLowEnergyController *controller = nullptr;
QList<QByteArray> receivedPackets;
QEventLoop waitForPacket;
+ dc_user_device_t *device;
};