Scubapro G2: update for BLE downloading

The code actually almost worked as-is, but for a tiny detail: the USBHID
packet reception code always receives a full 64-byte packet, while BLE
GATT will return how much it actually received.

The other difference is that USB HID is so fast that it didn't make any
difference where the progress was updated, it took about a second to
download everything.

BLE GATT is not fast to begin with, and the G2 may be particularly slow.

So with the BLE backend, you really do want progress updates for each
packet received, because the dump is going to take a while...

But with the trivial packet verification change, and with the progress
report updates, everything "JustWorks(tm)" over BLE.

Of course, I haven't committed the actual Subsurface BLE transfer parts
yet, because they are some incredibly ugly stuff with fragile bits and
pieces.  But the fact that I can now download from two different dive
computers does mean that I think it's getting to the point where I will
just submit even my ugly code to Dirk.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2017-06-24 15:01:56 -07:00
parent ca115b97e2
commit accc63df11

View File

@ -58,11 +58,11 @@ static dc_status_t
scubapro_g2_extract_dives (dc_device_t *device, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata);
#define PACKET_SIZE 64
static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int size)
static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int size, dc_event_progress_t *progress)
{
dc_custom_io_t *io = _dc_context_custom_io(g2->base.context);
while (size) {
unsigned char buf[PACKET_SIZE];
unsigned char buf[PACKET_SIZE] = { 0 };
size_t transferred = 0;
dc_status_t rc;
int len;
@ -72,11 +72,15 @@ static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int siz
ERROR(g2->base.context, "read interrupt transfer failed");
return -1;
}
if (transferred != PACKET_SIZE) {
if (io->packet_size == PACKET_SIZE && transferred != PACKET_SIZE) {
ERROR(g2->base.context, "incomplete read interrupt transfer (got %zu, expected %d)", transferred, PACKET_SIZE);
return -1;
}
len = buf[0];
if (transferred < len + 1) {
ERROR(g2->base.context, "small packet read (got %zu, expected at least %d)", transferred, len + 1);
return -1;
}
if (len >= PACKET_SIZE) {
ERROR(g2->base.context, "read interrupt transfer returns impossible packet size (%d)", len);
return -1;
@ -89,6 +93,12 @@ static int receive_data(scubapro_g2_device_t *g2, unsigned char *buffer, int siz
memcpy(buffer, buf+1, len);
size -= len;
buffer += len;
// Update and emit a progress event?
if (progress) {
progress->current += len;
device_event_emit(&g2->base, DC_EVENT_PROGRESS, progress);
}
}
return 0;
}
@ -116,7 +126,7 @@ scubapro_g2_transfer(scubapro_g2_device_t *g2, const unsigned char command[], un
return status;
}
if (receive_data(g2, answer, asize) < 0) {
if (receive_data(g2, answer, asize, NULL) < 0) {
ERROR(g2->base.context, "Failed to receive the answer.");
return DC_STATUS_IO;
}
@ -351,15 +361,11 @@ scubapro_g2_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
return DC_STATUS_PROTOCOL;
}
if (receive_data(device, data, length)) {
if (receive_data(device, data, length, &progress)) {
ERROR (abstract->context, "Received an unexpected size.");
return DC_STATUS_IO;
}
// Update and emit a progress event.
progress.current += length;
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
return DC_STATUS_SUCCESS;
}