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.
This commit is contained in:
Jef Driesen 2022-11-06 20:08:11 +01:00
parent 8a6abab1da
commit bf93040ab1

View File

@ -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).",