Handle a libusb timeout as a non fatal error.

Dives are downloaded using bulk transfers with an 8K buffer. Normally
the 2 second timeout is more than sufficient, and the timeout should
never expire, unless there is some serious communcation problem. But
nevertheless, users are reporting timeouts for dives having a length
that is an exact multiple of the USB packet size (64 bytes). In that
case, libusb reports a timeout with an non-zero amount of bytes
received. Despite the timeout, the received data contains a complete
dive.

I suspect libusb is somehow unable to determine whether the transfer is
complete and therefore waits until the timeout expires. For transfers
that are not a multiple of the USB packet size, the end of the transfer
is indicated by the last incomplete packet. This is not the case if the
length is an exact multiple of the USB packet size. This problem is
usually solved by sending a zero-length packet. Maybe the USB stack of
the Cobalt is not sending such a zero-length packet?

Atomics will address the problem with a Coblat 2 firmware upgrade, that
will simply append two zero bytes if the length is a multiple of 64
bytes. As a workaround for older firmware versions, we ignore the
timeout and process all received data. This shouldn't have any
disadvantages. An incomplete dive, for example due to a real timeout,
will now be detected by means of the minimum length and/or the checksum.
This commit is contained in:
Jef Driesen 2015-10-13 20:35:35 +02:00
parent 00e0cfa0ab
commit a21f60e0bc

View File

@ -284,7 +284,7 @@ atomics_cobalt_read_dive (dc_device_t *abstract, dc_buffer_t *buffer, int init,
unsigned char packet[8 * 1024] = {0};
rc = libusb_bulk_transfer (device->handle, 0x82,
packet, sizeof (packet), &length, TIMEOUT);
if (rc != LIBUSB_SUCCESS) {
if (rc != LIBUSB_SUCCESS && rc != LIBUSB_ERROR_TIMEOUT) {
ERROR (abstract->context, "Failed to receive the answer.");
return EXITCODE(rc);
}