From a21f60e0bcdd7dccd198d2b16c7e7fe17774873e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 13 Oct 2015 20:35:35 +0200 Subject: [PATCH] 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. --- src/atomics_cobalt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atomics_cobalt.c b/src/atomics_cobalt.c index 88febec..aec412d 100644 --- a/src/atomics_cobalt.c +++ b/src/atomics_cobalt.c @@ -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); }