diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2017-07-11 20:31:40 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2017-07-11 20:32:48 -0700 |
commit | b9f691a70093f1174d07a28a8d05b436e46478b2 (patch) | |
tree | 160907bd555a9b19d6924892f551d2a61438084f | |
parent | 45f36e251bb780b6276fcbe78e6ea849ec3ecc2b (diff) | |
parent | fbaaa64a4a3cf3266b8afe62af578105ec32a374 (diff) | |
download | subsurface-b9f691a70093f1174d07a28a8d05b436e46478b2.tar.gz |
Merge branch 'hw-o-ble-2' of https://github.com/janmulder/subsurface
Doing a manual merge from the command line in order to retain Jan's SHAs
so that the commit message makes sense...
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r-- | core/qt-ble.cpp | 103 | ||||
-rw-r--r-- | core/qt-ble.h | 2 | ||||
-rw-r--r-- | core/qtserialbluetooth.cpp | 25 |
3 files changed, 71 insertions, 59 deletions
diff --git a/core/qt-ble.cpp b/core/qt-ble.cpp index 0ce52bc02..967827db1 100644 --- a/core/qt-ble.cpp +++ b/core/qt-ble.cpp @@ -27,8 +27,9 @@ static int debugCounter; #define IS_HW(_d) same_string((_d)->vendor, "Heinrichs Weikamp") #define IS_SHEARWATER(_d) same_string((_d)->vendor, "Shearwater") -#define IS_EON_STEEL(_d) same_string((_d)->product, "EON Steel") -#define IS_G2(_d) same_string((_d)->product, "G2") + +#define MAXIMAL_HW_CREDIT 255 +#define MINIMAL_HW_CREDIT 32 extern "C" { @@ -65,21 +66,24 @@ void BLEObject::characteristcStateChanged(const QLowEnergyCharacteristic &c, con { if (IS_HW(device)) { if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_DATA_TX]) { + hw_credit--; receivedPackets.append(value); + if (hw_credit == MINIMAL_HW_CREDIT) + setHwCredit(MAXIMAL_HW_CREDIT - MINIMAL_HW_CREDIT); } else { qDebug() << "ignore packet from" << c.uuid() << value.toHex(); } } else { receivedPackets.append(value); } - //qDebug() << ".. incoming packet count" << receivedPackets.length(); } void BLEObject::characteristicWritten(const QLowEnergyCharacteristic &c, const QByteArray &value) { if (IS_HW(device)) { if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_CREDITS_RX]) { - qDebug() << "HW_OSTC_BLE_CREDITS_RX confirmed" << c.uuid() << value.toHex(); + bool ok; + hw_credit += value.toHex().toInt(&ok, 16); isCharacteristicWritten = true; } } else { @@ -91,8 +95,8 @@ void BLEObject::characteristicWritten(const QLowEnergyCharacteristic &c, const Q void BLEObject::writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value) { Q_UNUSED(value) - - qDebug() << "BLE write completed on" << d.name() << d.value(); + Q_UNUSED(d) + qDebug() << "BLE write completed"; } void BLEObject::addService(const QBluetoothUuid &newService) @@ -185,38 +189,47 @@ dc_status_t BLEObject::read(void *data, size_t size, size_t *actual) if (receivedPackets.isEmpty()) return DC_STATUS_IO; - int offset = 0; - while (!receivedPackets.isEmpty()) { - /* - * Yes, to while loops with same condition seems strange. The inner one - * does the real work, but it prevents the QtEventloop to do its thing. - * As the incoming packets arrive based on signals and slots, that - * stuff is not handeled during the inner loop. So, add a short waitFor - * between the inner and outer while loop. - */ - while (!receivedPackets.isEmpty()) { - QByteArray packet = receivedPackets.takeFirst(); + QByteArray packet = receivedPackets.takeFirst(); - if (IS_SHEARWATER(device)) - packet.remove(0,2); + if (IS_SHEARWATER(device)) + packet.remove(0,2); - //qDebug() << ".. read (packet.length, contents, size)" << packet.size() << packet.toHex() << size; + if (packet.size() > size) + return DC_STATUS_NOMEMORY; - if ((offset + packet.size()) > size) { - qDebug() << "BLE read trouble, receive buffer too small"; - return DC_STATUS_NOMEMORY; - } + memcpy((char *)data, packet.data(), packet.size()); + *actual += packet.size(); - memcpy((char *)data + offset, packet.data(), packet.size()); - offset += packet.size(); - *actual += packet.size(); - // EON Steel wants to read only one packet at a time - if (IS_EON_STEEL(device) || IS_G2(device)) - goto we_are_done; - } - waitFor(50); // and process some Qt events to see if there is more data coming in. - } -we_are_done: + 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). + * + * Notice that we have to write to the characteristic here, and not to its + * descriptor as for the enabeling of notifications or indications. + * + * Futher notice that this function has the implicit effect of processing the + * event loop (due to waiting for the confirmation of the credit request). + * So, as characteristcStateChanged will be triggered, while receiving + * data from the OSTC, these are processed too. + */ + + QList<QLowEnergyCharacteristic> list = preferredService()->characteristics(); + isCharacteristicWritten = false; + preferredService()->writeCharacteristic(list[HW_OSTC_BLE_CREDITS_RX], + QByteArray(1, c), + QLowEnergyService::WriteWithResponse); + + /* And wait for the answer*/ + int msec = BLE_TIMEOUT; + while (msec > 0 && !isCharacteristicWritten) { + waitFor(100); + msec -= 100; + }; + if (!isCharacteristicWritten) + return DC_STATUS_TIMEOUT; return DC_STATUS_SUCCESS; } @@ -252,26 +265,8 @@ dc_status_t BLEObject::setupHwTerminalIo(QList<QLowEnergyCharacteristic> allC) 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 = BLE_TIMEOUT; - while (msec > 0 && !isCharacteristicWritten) { - waitFor(100); - msec -= 100; - }; - if (!isCharacteristicWritten) - return DC_STATUS_TIMEOUT; - - return DC_STATUS_SUCCESS; + /* The Terminal I/O client transmits initial UART credits to the server (see 6.5). */ + return setHwCredit(MAXIMAL_HW_CREDIT); } dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *devaddr) diff --git a/core/qt-ble.h b/core/qt-ble.h index 7368b71cd..ad5dfda2b 100644 --- a/core/qt-ble.h +++ b/core/qt-ble.h @@ -32,6 +32,7 @@ public slots: void characteristicWritten(const QLowEnergyCharacteristic &c, const QByteArray &value); void writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value); dc_status_t setupHwTerminalIo(QList<QLowEnergyCharacteristic>); + dc_status_t setHwCredit(unsigned int c); private: QVector<QLowEnergyService *> services; @@ -39,6 +40,7 @@ private: QList<QByteArray> receivedPackets; bool isCharacteristicWritten; dc_user_device_t *device; + unsigned int hw_credit = 0; QList<QUuid> hwAllCharacteristics = { "{00000001-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_RX diff --git a/core/qtserialbluetooth.cpp b/core/qtserialbluetooth.cpp index 8b5779ce5..3a031e1ae 100644 --- a/core/qtserialbluetooth.cpp +++ b/core/qtserialbluetooth.cpp @@ -126,19 +126,34 @@ static dc_status_t ble_serial_read(dc_custom_io_t *io, void* data, size_t size, { Q_UNUSED(io) size_t len; + size_t received = 0; if (buffer.in_pos >= buffer.in_bytes) { + ble_serial_flush_write(); + } + + /* There is still unused/unread data in the input steam. + * So preseve it at the start of a new read. + */ + if (buffer.in_pos > 0) { + len = buffer.in_bytes - buffer.in_pos; + memcpy(buffer.in, buffer.in + buffer.in_pos, len); + buffer.in_pos = 0; + buffer.in_bytes = len; + } + + /* Read a long as requested in the size parameter */ + while ((buffer.in_bytes - buffer.in_pos) < size) { dc_status_t rc; - size_t received; - ble_serial_flush_write(); - rc = ble_serial_ops.packet_read(&ble_serial_ops, buffer.in, sizeof(buffer.in), &received); + rc = ble_serial_ops.packet_read(&ble_serial_ops, buffer.in + buffer.in_bytes, + sizeof(buffer.in) - buffer.in_bytes, &received); if (rc != DC_STATUS_SUCCESS) return rc; if (!received) return DC_STATUS_IO; - buffer.in_pos = 0; - buffer.in_bytes = received; + + buffer.in_bytes += received; } len = buffer.in_bytes - buffer.in_pos; |