OSTC over BLE: initialize Terminal I/O client

This initalizes the Terminal I/O client as described in paragraph 3 of
http://www.telit.com/fileadmin/user_upload/products/Downloads/sr-rf/BlueMod/TIO_Implementation_Guide_r04.pdf

This is for all Heinrichs Weikamp computers, that use referenced BT/BLE hardware
module from Telit Wireless Solutions (Formerly Stollmann E+V GmbH). The 16 bit
UUID 0xFEFB (or a derived 128 bit UUID starting with 0x0000FEFB is a
clear indication that the OSTC is equipped with this BT/BLE hardware.
Furthermore, most devices equipped with this BT/BLE hardware have BT addresses
starting with 00:80:25:...

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This commit is contained in:
Jan Mulder 2017-07-03 19:24:39 +02:00 committed by Dirk Hohndel
parent 40d85b5d63
commit 6fe0388b96
2 changed files with 89 additions and 10 deletions

View file

@ -3,6 +3,7 @@
#include <QtBluetooth/QBluetoothAddress>
#include <QLowEnergyController>
#include <QLowEnergyService>
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QEventLoop>
@ -23,6 +24,8 @@
extern "C" {
static int device_is_hw(dc_user_device_t *device);
void waitFor(int ms) {
Q_ASSERT(QCoreApplication::instance());
Q_ASSERT(QThread::currentThread());
@ -106,6 +109,11 @@ static int device_is_shearwater(dc_user_device_t *device)
return !strcmp(device->vendor, "Shearwater");
}
static int device_is_hw(dc_user_device_t *device)
{
return !strcmp(device->vendor, "Heinrichs Weikamp");
}
dc_status_t BLEObject::write(const void *data, size_t size, size_t *actual)
{
Q_UNUSED(actual) // that seems like it might cause problems
@ -163,6 +171,60 @@ dc_status_t BLEObject::read(void *data, size_t size, size_t *actual)
return DC_STATUS_SUCCESS;
}
int BLEObject::setupHwTerminalIo(QList<QLowEnergyCharacteristic> allC)
{ /* This initalizes the Terminal I/O client as described in
* http://www.telit.com/fileadmin/user_upload/products/Downloads/sr-rf/BlueMod/TIO_Implementation_Guide_r04.pdf
* Referenced section numbers below are from that document.
*
* This is for all HW computers, that use referenced BT/BLE hardware module from Telit
* (formerly Stollmann). The 16 bit UUID 0xFEFB (or a derived 128 bit UUID starting with
* 0x0000FEFB is a clear indication that the OSTC is equipped with this BT/BLE hardware.
*/
if (allC.length() != 4) {
qDebug() << "This should not happen. HW/OSTC BT/BLE device without 4 Characteristics";
return DC_STATUS_IO;
}
/* The Terminal I/O client subscribes to indications of the UART credits TX
* characteristic (see 6.4).
*
* Notice that indications are subscribed to by writing 0x0200 to its descriptor. This
* can be understood by looking for Client Characteristic Configuration, Assigned
* Number: 0x2902. Enabling/Disabeling is setting the proper bit, and they
* differ for indications and notifications.
*/
QLowEnergyDescriptor d = allC[HW_OSTC_BLE_CREDITS_TX].descriptors().first();
preferredService()->writeDescriptor(d, QByteArray::fromHex("0200"));
/* The Terminal I/O client subscribes to notifications of the UART data TX
* characteristic (see 6.2).
*/
d = allC[HW_OSTC_BLE_DATA_TX].descriptors().first();
preferredService()->writeDescriptor(d, QByteArray::fromHex("0100"));
/* The Terminal I/O client transmits initial UART credits to the server (see 6.5).
*
* Notice that we have to write to the characteristic here, and not to its
* descriptor as for the enabeling of notifications or indications.
*/
isCharacteristicWritten = false;
preferredService()->writeCharacteristic(allC[HW_OSTC_BLE_CREDITS_RX],
QByteArray(1, 255),
QLowEnergyService::WriteWithResponse);
/* And give to OSTC some time to get initialized */
int msec = 5000;
while (msec > 0 && !isCharacteristicWritten) {
waitFor(100);
msec -= 100;
};
if (!isCharacteristicWritten)
return DC_STATUS_TIMEOUT;
return DC_STATUS_SUCCESS;
}
dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *devaddr)
{
Q_UNUSED(context)
@ -256,6 +318,10 @@ dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *d
if (!list.isEmpty()) {
const QLowEnergyCharacteristic &c = list.constLast();
if (device_is_hw(io->user_device)) {
ble->setupHwTerminalIo(list);
} else {
QList<QLowEnergyDescriptor> l = c.descriptors();
qDebug() << "Descriptor list with" << l.length() << "elements";
@ -264,7 +330,6 @@ dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *d
foreach(d, l)
qDebug() << "Descriptor:" << d.name() << "uuid:" << d.uuid().toString();
if (!l.isEmpty()) {
d = l.first();
qDebug() << "now writing \"0x0100\" to the first descriptor";
@ -272,6 +337,7 @@ dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *d
ble->preferredService()->writeDescriptor(d, QByteArray::fromHex("0100"));
}
}
}
// Fill in info
io->userdata = (void *)ble;

View file

@ -6,6 +6,11 @@
#include <QLowEnergyController>
#include <QEventLoop>
#define HW_OSTC_BLE_DATA_RX 0
#define HW_OSTC_BLE_DATA_TX 1
#define HW_OSTC_BLE_CREDITS_RX 2
#define HW_OSTC_BLE_CREDITS_TX 3
class BLEObject : public QObject
{
Q_OBJECT
@ -25,14 +30,22 @@ public slots:
void serviceStateChanged(QLowEnergyService::ServiceState s);
void characteristcStateChanged(const QLowEnergyCharacteristic &c, const QByteArray &value);
void writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value);
int setupHwTerminalIo(QList<QLowEnergyCharacteristic>);
private:
QVector<QLowEnergyService *> services;
QLowEnergyController *controller = nullptr;
QList<QByteArray> receivedPackets;
QEventLoop waitForPacket;
bool isCharacteristicWritten;
dc_user_device_t *device;
QList<QUuid> hwAllCharacteristics = {
"{00000001-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_RX
"{00000002-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_TX
"{00000003-0000-1000-8000-008025000000}", // HW_OSTC_BLE_CREDITS_RX
"{00000004-0000-1000-8000-008025000000}" // HW_OSTC_BLE_CREDITS_TX
};
};