From a28d2feb4f3712c13bfc7f1f89ee9f92b9679f7e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 22 Sep 2017 21:36:39 +0200 Subject: [PATCH 1/3] Replace the size macro with the sizeof operator --- src/uwatec_g2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/uwatec_g2.c b/src/uwatec_g2.c index f6b0b02..b04d761 100644 --- a/src/uwatec_g2.c +++ b/src/uwatec_g2.c @@ -71,17 +71,17 @@ receive_data (uwatec_g2_device_t *device, dc_event_progress_t *progress, unsigne dc_status_t rc = DC_STATUS_SUCCESS; unsigned int len = 0; - rc = dc_usbhid_read (device->usbhid, buf, PACKET_SIZE, &transferred); + rc = dc_usbhid_read (device->usbhid, buf, sizeof(buf), &transferred); if (rc != DC_STATUS_SUCCESS) { ERROR (device->base.context, "read interrupt transfer failed"); return rc; } - if (transferred != PACKET_SIZE) { - ERROR (device->base.context, "incomplete read interrupt transfer (got " DC_PRINTF_SIZE ", expected %d)", transferred, PACKET_SIZE); + if (transferred != sizeof(buf)) { + ERROR (device->base.context, "incomplete read interrupt transfer (got " DC_PRINTF_SIZE ", expected " DC_PRINTF_SIZE ")", transferred, sizeof(buf)); return DC_STATUS_PROTOCOL; } len = buf[0]; - if (len >= PACKET_SIZE) { + if (len >= sizeof(buf)) { ERROR (device->base.context, "read interrupt transfer returns impossible packet size (%d)", len); return DC_STATUS_PROTOCOL; } @@ -112,7 +112,7 @@ uwatec_g2_transfer (uwatec_g2_device_t *device, const unsigned char command[], u dc_status_t status = DC_STATUS_SUCCESS; size_t transferred = 0; - if (csize + 2 > PACKET_SIZE) { + if (csize + 2 > sizeof(buf)) { ERROR (device->base.context, "command too big (%d)", csize); return DC_STATUS_INVALIDARGS; } From ddb7276bf017e60e76a8d55cc119bfa485ba4210 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 22 Sep 2017 21:50:28 +0200 Subject: [PATCH 2/3] Use a fixed size packet for sending The Windows HID api always expects to receive a fixed size buffer (corresponding to the largest report supported by the device). But unlike the hidapi library, the libusb library doesn't automatically pad the buffer to the expected size when trying to send less bytes. Thus when trying to submit the transfer, the underlying Windows api call immediately fails with ERROR_INVALID_PARAMETER. To workaround this problem, pad the data packet with zeros manually and always send the entire packet (1 byte report ID and 32 bytes payload). --- src/uwatec_g2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/uwatec_g2.c b/src/uwatec_g2.c index b04d761..4ef949f 100644 --- a/src/uwatec_g2.c +++ b/src/uwatec_g2.c @@ -32,7 +32,8 @@ #define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_g2_device_vtable) -#define PACKET_SIZE 64 +#define RX_PACKET_SIZE 64 +#define TX_PACKET_SIZE 32 typedef struct uwatec_g2_device_t { dc_device_t base; @@ -66,7 +67,7 @@ static dc_status_t receive_data (uwatec_g2_device_t *device, dc_event_progress_t *progress, unsigned char *data, unsigned int size) { while (size) { - unsigned char buf[PACKET_SIZE]; + unsigned char buf[RX_PACKET_SIZE]; size_t transferred = 0; dc_status_t rc = DC_STATUS_SUCCESS; unsigned int len = 0; @@ -108,7 +109,7 @@ receive_data (uwatec_g2_device_t *device, dc_event_progress_t *progress, unsigne static dc_status_t uwatec_g2_transfer (uwatec_g2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) { - unsigned char buf[PACKET_SIZE]; + unsigned char buf[TX_PACKET_SIZE + 1]; dc_status_t status = DC_STATUS_SUCCESS; size_t transferred = 0; @@ -122,7 +123,8 @@ uwatec_g2_transfer (uwatec_g2_device_t *device, const unsigned char command[], u buf[0] = 0; buf[1] = csize; memcpy(buf + 2, command, csize); - status = dc_usbhid_write (device->usbhid, buf, csize + 2, &transferred); + memset(buf + 2 + csize, 0, sizeof(buf) - (csize + 2)); + status = dc_usbhid_write (device->usbhid, buf, sizeof(buf), &transferred); if (status != DC_STATUS_SUCCESS) { ERROR (device->base.context, "Failed to send the command."); return status; From bcb64b3297b0366331de7aed12f1fdf7165ac0d6 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 22 Sep 2017 22:16:56 +0200 Subject: [PATCH 3/3] Workaround for a Windows libusb issue When libusb uses the Windows HID api internally, it does automatically prepend a zero report ID to the data for devices which support only a single report. But apparently it also returns a size of one byte extra! As a workaround, the number of bytes is limited to the actual size. See commit c9ed92d3f55c259931527a27d018eb5791a176dd for a similar issue in the hidapi library. --- src/usbhid.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/usbhid.c b/src/usbhid.c index b697f47..38931b8 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -45,6 +45,7 @@ #include "usbhid.h" #include "common-private.h" #include "context-private.h" +#include "platform.h" struct dc_usbhid_t { /* Library context. */ @@ -432,15 +433,16 @@ dc_usbhid_write (dc_usbhid_t *usbhid, const void *data, size_t size, size_t *act nbytes = 0; goto out; } - -#ifdef _WIN32 - if (nbytes > size) { - nbytes = size; - } -#endif #endif out: +#ifdef _WIN32 + if (nbytes > size) { + WARNING (usbhid->context, "Number of bytes exceeds the buffer size (" DC_PRINTF_SIZE " > " DC_PRINTF_SIZE ")!", nbytes, size); + nbytes = size; + } +#endif + HEXDUMP (usbhid->context, DC_LOGLEVEL_INFO, "Write", (unsigned char *) data, nbytes); out_invalidargs: