summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/qt-ble.cpp103
-rw-r--r--core/qt-ble.h2
-rw-r--r--core/qtserialbluetooth.cpp25
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;