Add support for the new OSTC hardware

In the latest OSTC hardware, the Telit/Stollman bluetooth module has
been replaced with a u-Blox Nina B2 bluetooth module. The BLE
communication protocol remains roughly the same, except for a few minor
differences:

 - New UUIDs for services and characteristics
 - Only one common characteristic for Rx and Tx
 - Credit based flow control is optional
 - Credit value of 255 corresponds to a disconnect

[Dirk Hohndel: small edit to a comment]

Signed-off-by: Jef Driesen <jef@libdivecomputer.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Jef Driesen 2022-01-29 16:47:56 +01:00 committed by Dirk Hohndel
parent f8c794e11c
commit 3a77d15eef
2 changed files with 32 additions and 18 deletions

View file

@ -30,7 +30,7 @@ static int debugCounter;
#define IS_SHEARWATER(_d) same_string((_d)->vendor, "Shearwater") #define IS_SHEARWATER(_d) same_string((_d)->vendor, "Shearwater")
#define IS_GARMIN(_d) same_string((_d)->vendor, "Garmin") #define IS_GARMIN(_d) same_string((_d)->vendor, "Garmin")
#define MAXIMAL_HW_CREDIT 255 #define MAXIMAL_HW_CREDIT 254
#define MINIMAL_HW_CREDIT 32 #define MINIMAL_HW_CREDIT 32
#define WAITFOR(expression, ms) do { \ #define WAITFOR(expression, ms) do { \
@ -67,7 +67,7 @@ void BLEObject::characteristcStateChanged(const QLowEnergyCharacteristic &c, con
if (verbose > 2 || debugCounter < DEBUG_THRESHOLD) if (verbose > 2 || debugCounter < DEBUG_THRESHOLD)
qDebug() << QTime::currentTime() << "packet RECV" << value.toHex(); qDebug() << QTime::currentTime() << "packet RECV" << value.toHex();
if (IS_HW(device)) { if (IS_HW(device)) {
if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_DATA_TX]) { if (c.uuid() == telit[TELIT_DATA_TX] || c.uuid() == ublox[UBLOX_DATA_TX]) {
hw_credit--; hw_credit--;
receivedPackets.append(value); receivedPackets.append(value);
if (hw_credit == MINIMAL_HW_CREDIT) if (hw_credit == MINIMAL_HW_CREDIT)
@ -83,7 +83,7 @@ void BLEObject::characteristcStateChanged(const QLowEnergyCharacteristic &c, con
void BLEObject::characteristicWritten(const QLowEnergyCharacteristic &c, const QByteArray &value) void BLEObject::characteristicWritten(const QLowEnergyCharacteristic &c, const QByteArray &value)
{ {
if (IS_HW(device)) { if (IS_HW(device)) {
if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_CREDITS_RX]) { if (c.uuid() == telit[TELIT_CREDITS_RX] || c.uuid() == ublox[UBLOX_CREDITS_RX]) {
bool ok; bool ok;
hw_credit += value.toHex().toInt(&ok, 16); hw_credit += value.toHex().toInt(&ok, 16);
isCharacteristicWritten = true; isCharacteristicWritten = true;
@ -135,7 +135,8 @@ static const char *match_uuid_list(const QBluetoothUuid &match, const struct uui
// Oh. It did, didn't it? // Oh. It did, didn't it?
// //
static const struct uuid_match serial_service_uuids[] = { static const struct uuid_match serial_service_uuids[] = {
{ "0000fefb-0000-1000-8000-00805f9b34fb", "Heinrichs-Weikamp" }, { "0000fefb-0000-1000-8000-00805f9b34fb", "Heinrichs-Weikamp (Telit/Stollmann)" },
{ "2456e1b9-26e2-8f83-e744-f34f01e9d701", "Heinrichs-Weikamp (U-Blox)" },
{ "544e326b-5b72-c6b0-1c46-41c1bc448118", "Mares BlueLink Pro" }, { "544e326b-5b72-c6b0-1c46-41c1bc448118", "Mares BlueLink Pro" },
{ "6e400001-b5a3-f393-e0a9-e50e24dcca9e", "Nordic Semi UART" }, { "6e400001-b5a3-f393-e0a9-e50e24dcca9e", "Nordic Semi UART" },
{ "98ae7120-e62e-11e3-badd-0002a5d5c51b", "Suunto (EON Steel/Core, G5)" }, { "98ae7120-e62e-11e3-badd-0002a5d5c51b", "Suunto (EON Steel/Core, G5)" },
@ -467,8 +468,9 @@ dc_status_t BLEObject::setHwCredit(unsigned int c)
*/ */
QList<QLowEnergyCharacteristic> list = preferredService()->characteristics(); QList<QLowEnergyCharacteristic> list = preferredService()->characteristics();
int credits_rx = list.length() == 4 ? TELIT_CREDITS_RX : UBLOX_CREDITS_RX;
isCharacteristicWritten = false; isCharacteristicWritten = false;
preferredService()->writeCharacteristic(list[HW_OSTC_BLE_CREDITS_RX], preferredService()->writeCharacteristic(list[credits_rx],
QByteArray(1, c), QByteArray(1, c),
QLowEnergyService::WriteWithResponse); QLowEnergyService::WriteWithResponse);
@ -490,8 +492,8 @@ dc_status_t BLEObject::setupHwTerminalIo(const QList<QLowEnergyCharacteristic> &
* 0x0000FEFB is a clear indication that the OSTC is equipped with this BT/BLE hardware. * 0x0000FEFB is a clear indication that the OSTC is equipped with this BT/BLE hardware.
*/ */
if (allC.length() != 4) { if (allC.length() != 4 && allC.length() != 2) {
qDebug() << "This should not happen. HW/OSTC BT/BLE device without 4 Characteristics"; qDebug() << "This should not happen. HW/OSTC BT/BLE device without 2(UBLOX) or 4(TELIT) Characteristics";
return DC_STATUS_IO; return DC_STATUS_IO;
} }
@ -503,13 +505,15 @@ dc_status_t BLEObject::setupHwTerminalIo(const QList<QLowEnergyCharacteristic> &
* Number: 0x2902. Enabling/Disabeling is setting the proper bit, and they * Number: 0x2902. Enabling/Disabeling is setting the proper bit, and they
* differ for indications and notifications. * differ for indications and notifications.
*/ */
QLowEnergyDescriptor d = allC[HW_OSTC_BLE_CREDITS_TX].descriptors().first(); int credits_tx = allC.length() == 4 ? TELIT_CREDITS_TX : UBLOX_CREDITS_TX;
QLowEnergyDescriptor d = allC[credits_tx].descriptors().first();
preferredService()->writeDescriptor(d, QByteArray::fromHex("0200")); preferredService()->writeDescriptor(d, QByteArray::fromHex("0200"));
/* The Terminal I/O client subscribes to notifications of the UART data TX /* The Terminal I/O client subscribes to notifications of the UART data TX
* characteristic (see 6.2). * characteristic (see 6.2).
*/ */
d = allC[HW_OSTC_BLE_DATA_TX].descriptors().first(); int data_tx = allC.length() == 4 ? TELIT_DATA_TX : UBLOX_DATA_TX;
d = allC[data_tx].descriptors().first();
preferredService()->writeDescriptor(d, QByteArray::fromHex("0100")); preferredService()->writeDescriptor(d, QByteArray::fromHex("0100"));
/* The Terminal I/O client transmits initial UART credits to the server (see 6.5). */ /* The Terminal I/O client transmits initial UART credits to the server (see 6.5). */

View file

@ -8,10 +8,15 @@
#include <QLowEnergyController> #include <QLowEnergyController>
#include <QEventLoop> #include <QEventLoop>
#define HW_OSTC_BLE_DATA_RX 0 #define TELIT_DATA_RX 0
#define HW_OSTC_BLE_DATA_TX 1 #define TELIT_DATA_TX 1
#define HW_OSTC_BLE_CREDITS_RX 2 #define TELIT_CREDITS_RX 2
#define HW_OSTC_BLE_CREDITS_TX 3 #define TELIT_CREDITS_TX 3
#define UBLOX_DATA_RX 0
#define UBLOX_DATA_TX 0
#define UBLOX_CREDITS_RX 1
#define UBLOX_CREDITS_TX 1
class BLEObject : public QObject class BLEObject : public QObject
{ {
@ -55,11 +60,16 @@ private:
unsigned int desc_written = 0; unsigned int desc_written = 0;
int timeout; int timeout;
QList<QUuid> hwAllCharacteristics = { QList<QUuid> telit = {
"{00000001-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_RX "{00000001-0000-1000-8000-008025000000}", // TELIT_DATA_RX
"{00000002-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_TX "{00000002-0000-1000-8000-008025000000}", // TELIT_DATA_TX
"{00000003-0000-1000-8000-008025000000}", // HW_OSTC_BLE_CREDITS_RX "{00000003-0000-1000-8000-008025000000}", // TELIT_CREDITS_RX
"{00000004-0000-1000-8000-008025000000}" // HW_OSTC_BLE_CREDITS_TX "{00000004-0000-1000-8000-008025000000}" // TELIT_CREDITS_TX
};
QList<QUuid> ublox = {
"{2456e1b9-26e2-8f83-e744-f34f01e9d703}", // UBLOX_DATA_RX, UBLOX_DATA_TX
"{2456e1b9-26e2-8f83-e744-f34f01e9d704}" // UBLOX_CREDITS_RX, UBLOX_CREDITS_TX
}; };
}; };