mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
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>
This commit is contained in:
commit
b9f691a700
3 changed files with 72 additions and 60 deletions
103
core/qt-ble.cpp
103
core/qt-ble.cpp
|
|
@ -27,8 +27,9 @@ static int debugCounter;
|
||||||
|
|
||||||
#define IS_HW(_d) same_string((_d)->vendor, "Heinrichs Weikamp")
|
#define IS_HW(_d) same_string((_d)->vendor, "Heinrichs Weikamp")
|
||||||
#define IS_SHEARWATER(_d) same_string((_d)->vendor, "Shearwater")
|
#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" {
|
extern "C" {
|
||||||
|
|
||||||
|
|
@ -65,21 +66,24 @@ void BLEObject::characteristcStateChanged(const QLowEnergyCharacteristic &c, con
|
||||||
{
|
{
|
||||||
if (IS_HW(device)) {
|
if (IS_HW(device)) {
|
||||||
if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_DATA_TX]) {
|
if (c.uuid() == hwAllCharacteristics[HW_OSTC_BLE_DATA_TX]) {
|
||||||
|
hw_credit--;
|
||||||
receivedPackets.append(value);
|
receivedPackets.append(value);
|
||||||
|
if (hw_credit == MINIMAL_HW_CREDIT)
|
||||||
|
setHwCredit(MAXIMAL_HW_CREDIT - MINIMAL_HW_CREDIT);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "ignore packet from" << c.uuid() << value.toHex();
|
qDebug() << "ignore packet from" << c.uuid() << value.toHex();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
receivedPackets.append(value);
|
receivedPackets.append(value);
|
||||||
}
|
}
|
||||||
//qDebug() << ".. incoming packet count" << receivedPackets.length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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() == 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;
|
isCharacteristicWritten = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -91,8 +95,8 @@ void BLEObject::characteristicWritten(const QLowEnergyCharacteristic &c, const Q
|
||||||
void BLEObject::writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value)
|
void BLEObject::writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value)
|
||||||
{
|
{
|
||||||
Q_UNUSED(value)
|
Q_UNUSED(value)
|
||||||
|
Q_UNUSED(d)
|
||||||
qDebug() << "BLE write completed on" << d.name() << d.value();
|
qDebug() << "BLE write completed";
|
||||||
}
|
}
|
||||||
|
|
||||||
void BLEObject::addService(const QBluetoothUuid &newService)
|
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())
|
if (receivedPackets.isEmpty())
|
||||||
return DC_STATUS_IO;
|
return DC_STATUS_IO;
|
||||||
|
|
||||||
int offset = 0;
|
QByteArray packet = receivedPackets.takeFirst();
|
||||||
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();
|
|
||||||
|
|
||||||
if (IS_SHEARWATER(device))
|
if (IS_SHEARWATER(device))
|
||||||
packet.remove(0,2);
|
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) {
|
memcpy((char *)data, packet.data(), packet.size());
|
||||||
qDebug() << "BLE read trouble, receive buffer too small";
|
*actual += packet.size();
|
||||||
return DC_STATUS_NOMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy((char *)data + offset, packet.data(), packet.size());
|
return DC_STATUS_SUCCESS;
|
||||||
offset += packet.size();
|
}
|
||||||
*actual += packet.size();
|
|
||||||
// EON Steel wants to read only one packet at a time
|
dc_status_t BLEObject::setHwCredit(unsigned int c)
|
||||||
if (IS_EON_STEEL(device) || IS_G2(device))
|
{
|
||||||
goto we_are_done;
|
/* The Terminal I/O client transmits initial UART credits to the server (see 6.5).
|
||||||
}
|
*
|
||||||
waitFor(50); // and process some Qt events to see if there is more data coming in.
|
* Notice that we have to write to the characteristic here, and not to its
|
||||||
}
|
* descriptor as for the enabeling of notifications or indications.
|
||||||
we_are_done:
|
*
|
||||||
|
* 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;
|
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();
|
d = allC[HW_OSTC_BLE_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). */
|
||||||
*
|
return setHwCredit(MAXIMAL_HW_CREDIT);
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *devaddr)
|
dc_status_t qt_ble_open(dc_custom_io_t *io, dc_context_t *context, const char *devaddr)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ public slots:
|
||||||
void characteristicWritten(const QLowEnergyCharacteristic &c, const QByteArray &value);
|
void characteristicWritten(const QLowEnergyCharacteristic &c, const QByteArray &value);
|
||||||
void writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value);
|
void writeCompleted(const QLowEnergyDescriptor &d, const QByteArray &value);
|
||||||
dc_status_t setupHwTerminalIo(QList<QLowEnergyCharacteristic>);
|
dc_status_t setupHwTerminalIo(QList<QLowEnergyCharacteristic>);
|
||||||
|
dc_status_t setHwCredit(unsigned int c);
|
||||||
private:
|
private:
|
||||||
QVector<QLowEnergyService *> services;
|
QVector<QLowEnergyService *> services;
|
||||||
|
|
||||||
|
|
@ -39,6 +40,7 @@ private:
|
||||||
QList<QByteArray> receivedPackets;
|
QList<QByteArray> receivedPackets;
|
||||||
bool isCharacteristicWritten;
|
bool isCharacteristicWritten;
|
||||||
dc_user_device_t *device;
|
dc_user_device_t *device;
|
||||||
|
unsigned int hw_credit = 0;
|
||||||
|
|
||||||
QList<QUuid> hwAllCharacteristics = {
|
QList<QUuid> hwAllCharacteristics = {
|
||||||
"{00000001-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_RX
|
"{00000001-0000-1000-8000-008025000000}", // HW_OSTC_BLE_DATA_RX
|
||||||
|
|
|
||||||
|
|
@ -126,19 +126,34 @@ static dc_status_t ble_serial_read(dc_custom_io_t *io, void* data, size_t size,
|
||||||
{
|
{
|
||||||
Q_UNUSED(io)
|
Q_UNUSED(io)
|
||||||
size_t len;
|
size_t len;
|
||||||
|
size_t received = 0;
|
||||||
|
|
||||||
if (buffer.in_pos >= buffer.in_bytes) {
|
if (buffer.in_pos >= buffer.in_bytes) {
|
||||||
dc_status_t rc;
|
|
||||||
size_t received;
|
|
||||||
|
|
||||||
ble_serial_flush_write();
|
ble_serial_flush_write();
|
||||||
rc = ble_serial_ops.packet_read(&ble_serial_ops, buffer.in, sizeof(buffer.in), &received);
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
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)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
return rc;
|
return rc;
|
||||||
if (!received)
|
if (!received)
|
||||||
return DC_STATUS_IO;
|
return DC_STATUS_IO;
|
||||||
buffer.in_pos = 0;
|
|
||||||
buffer.in_bytes = received;
|
buffer.in_bytes += received;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = buffer.in_bytes - buffer.in_pos;
|
len = buffer.in_bytes - buffer.in_pos;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue