summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-04-08 11:46:55 +0100
committerPete Batard <pbatard@gmail.com>2010-04-08 11:46:55 +0100
commitbb3280741d3675dee6274be60ce352e3a2f5370a (patch)
tree7067af0e6fb4e494d9cc8139d90d3a0c927538f6
parentd102dd23992cadc056cf28a3aefb8cfbcf532e31 (diff)
downloadlibusb-bb3280741d3675dee6274be60ce352e3a2f5370a.tar.gz
workaround for MS's HidD_GetFeature bug with report IDs
When report IDs are in use, the payload starts at buffer+0 not buffer+1 as indicated at http://msdn.microsoft.com/en-us/library/ff538910.aspx Bug reported by Axel Rohde
-rw-r--r--libusb/os/windows_usb.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 42b7133..2d1526d 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -3220,11 +3220,28 @@ static int _hid_get_feature(struct hid_device_priv* dev, HANDLE hid_handle, int
usbi_dbg("report ID: 0x%02X", buf[0]);
if (HidD_GetFeature(hid_handle, buf, read_size)) {
- if (buf[0] != id) {
- usbi_dbg("program assertion failed - mismatched report ID (got %02X instead of %02X)",
- buf[0], id);
+ // There is a major bug with HidD_GetFeature where the actual data payload starts
+ // at buf+0 when report IDs are in use by the device, but buf+1 otherwise.
+ // To try to work around this bug, we assume that if the id provided is
+ // nonzero, then report IDs are in use by the device
+ if (id != 0) {
+ // Try to compensate for a wrong assumption
+ if ((buf[read_size-1] != 0) && (buf[0] == 0)) {
+ usbi_warn(NULL, "program assertion failed - report ID provided but device does not");
+ usbi_warn(NULL, "seem to use report IDs. Compensating by shifting payload data");
+ memcpy(data, buf+1, read_size);
+ } else {
+ memcpy(data, buf, read_size);
+ }
+ } else {
+ if (buf[0] != 0) {
+ usbi_warn(NULL, "program assertion failed - report ID received (0x%02X) was", buf[0]);
+ usbi_warn(NULL, "supposed to be zero. Compensating by shifting payload data");
+ memcpy(data, buf, read_size);
+ } else {
+ memcpy(data, buf+1, read_size);
+ }
}
- memcpy(data, buf+1, read_size);
r = LIBUSB_COMPLETED;
} else {
err = GetLastError();