From bf93040ab1f7b0170e8bc2fc0f21851eb4e8795e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 6 Nov 2022 20:08:11 +0100 Subject: [PATCH] Receive only a single USB packet at a time The hidapi based implementation returns as soon as the first packet is received, while the libusb based implementation tries to read the requested number of bytes. That fails with a timeout if the requested number of bytes is larger than the size of a single packet and no further packets are received. Avoid this problem by limiting the size to the maximum packet size. --- src/usbhid.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/usbhid.c b/src/usbhid.c index b3805ca..acd20ef 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -86,6 +86,7 @@ struct dc_usbhid_device_t { int interface; unsigned char endpoint_in; unsigned char endpoint_out; + unsigned short packetsize; #elif defined(USE_HIDAPI) char *path; #endif @@ -125,6 +126,7 @@ typedef struct dc_usbhid_t { int interface; unsigned char endpoint_in; unsigned char endpoint_out; + unsigned short packetsize; unsigned int timeout; #elif defined(USE_HIDAPI) hid_device *handle; @@ -507,6 +509,7 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) device->interface = interface->bInterfaceNumber; device->endpoint_in = ep_in->bEndpointAddress; device->endpoint_out = ep_out->bEndpointAddress; + device->packetsize = ep_in->wMaxPacketSize; *(dc_usbhid_device_t **) out = device; @@ -614,6 +617,7 @@ dc_usbhid_open (dc_iostream_t **out, dc_context_t *context, dc_usbhid_device_t * usbhid->interface = device->interface; usbhid->endpoint_in = device->endpoint_in; usbhid->endpoint_out = device->endpoint_out; + usbhid->packetsize = device->packetsize; usbhid->timeout = 0; #elif defined(USE_HIDAPI) @@ -704,6 +708,10 @@ dc_usbhid_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual int nbytes = 0; #if defined(USE_LIBUSB) + if (size > usbhid->packetsize) { + size = usbhid->packetsize; + } + int rc = libusb_interrupt_transfer (usbhid->handle, usbhid->endpoint_in, data, size, &nbytes, usbhid->timeout); if (rc != LIBUSB_SUCCESS || nbytes < 0) { ERROR (abstract->context, "Usb read interrupt transfer failed (%s).",