From 1d8a2cc6ae71cc445bc6d1c3f43a803e24a8fbb9 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Mon, 22 Feb 2010 16:45:18 +0000 Subject: improved HID feature reports --- libusb/os/windows_usb.c | 81 ++++++++++++++++++++++++++++++++----------------- libusb/os/windows_usb.h | 1 + 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index fed17b2..dae05ef 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -3,6 +3,7 @@ * Copyright (c) 2009-2010 Pete Batard * With contributions from Michael Plante, Orin Eman et al. * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -3150,51 +3151,75 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i static int _hid_get_feature(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, size_t *size) { - uint8_t buf[HID_MAX_REPORT_SIZE + 1]; - uint32_t r; + uint8_t *buf; + ULONG read_size = (ULONG)(*size + 1); + int r = LIBUSB_ERROR_OTHER; + uint32_t err; - if (*size >MAX_HID_REPORT_SIZE) + if (*size > MAX_HID_REPORT_SIZE) return LIBUSB_ERROR_INVALID_PARAM; + buf = (uint8_t*)calloc(1, read_size); + if (buf == NULL) { + return LIBUSB_ERROR_NO_MEM; + } buf[0] = (uint8_t)id; + usbi_dbg("report ID: 0x%02X", buf[0]); - *size += 1; - if (HidD_GetFeature(hid_handle, buf, (ULONG)*size)) { - return LIBUSB_COMPLETED; - } - r = GetLastError(); - switch (r) { - case ERROR_INVALID_FUNCTION: - return LIBUSB_ERROR_NOT_FOUND; - default: - usbi_dbg("error %s", windows_error_str(r)); - return LIBUSB_ERROR_OTHER; + 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); + } + memcpy(data, buf+1, read_size); + r = LIBUSB_COMPLETED; + } else { + err = GetLastError(); + switch (err) { + case ERROR_INVALID_FUNCTION: + r = LIBUSB_ERROR_NOT_FOUND; + default: + usbi_dbg("error %s", windows_error_str(r)); + r = LIBUSB_ERROR_OTHER; + } } + safe_free(buf); + return r; } static int _hid_set_feature(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data, size_t *size) { - uint8_t buf[HID_MAX_REPORT_SIZE + 1]; - uint32_t r; + uint8_t *buf; + uint32_t err; + int r = LIBUSB_ERROR_OTHER; + ULONG write_size = (ULONG)(*size + 1); if (*size >MAX_HID_REPORT_SIZE) return LIBUSB_ERROR_INVALID_PARAM; + buf = (uint8_t*)malloc(write_size); + if (buf == NULL) { + return LIBUSB_ERROR_NO_MEM; + } buf[0] = (uint8_t)id; - memcpy(buf + 1, data, *size); + usbi_dbg("report ID: 0x%02X", buf[0]); - *size += 1; - if (HidD_SetFeature(hid_handle, buf, (ULONG)*size)) { - return LIBUSB_COMPLETED; - } - r = GetLastError(); - switch (r) { - case ERROR_INVALID_FUNCTION: - return LIBUSB_ERROR_NOT_FOUND; - default: - usbi_dbg("error %s", windows_error_str(r)); - return LIBUSB_ERROR_OTHER; + memcpy(buf+1, data, *size); + + if (HidD_SetFeature(hid_handle, buf, write_size)) { + r = LIBUSB_COMPLETED; + } else { + err = GetLastError(); + switch (err) { + case ERROR_INVALID_FUNCTION: + r = LIBUSB_ERROR_NOT_FOUND; + default: + usbi_dbg("error %s", windows_error_str(r)); + r = LIBUSB_ERROR_OTHER; + } } + safe_free(buf); + return r; } static int _hid_class_request(struct hid_device_priv* dev, HANDLE hid_handle, int request_type, diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index 1d729e8..11b51a9 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -3,6 +3,7 @@ * Copyright (C) 2009-2010 Pete Batard * With contributions from Michael Plante, Orin Eman et al. * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer + * Major code testing contribution by Xiaofan Chen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public -- cgit v1.2.1