summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-02-11 21:02:54 +0000
committerPete Batard <pbatard@gmail.com>2010-02-11 21:02:54 +0000
commit1cda5082f89d3e8a10fb35bdba74440241d7d822 (patch)
treebfe069ceeed2a6ac53c74e6dce16bdaf62add16a
parent9a8b0b955941158c1ed84f9311e3a01581803ebe (diff)
downloadlibusb-1cda5082f89d3e8a10fb35bdba74440241d7d822.tar.gz
added detection of HID report IDs for interrupt transfersr150
processing of HID report IDs in hid_open using HidP_GetValueCaps added corresponding DLL call
-rw-r--r--libusb/os/windows_usb.c64
-rw-r--r--libusb/os/windows_usb.h49
2 files changed, 105 insertions, 8 deletions
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index dadbb4f..a16b140 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -3025,7 +3025,7 @@ static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int i
return LIBUSB_ERROR_NO_MEM;
}
buf[0] = (uint8_t)id;
- usbi_dbg("report ID: %02X", buf[0]);
+ usbi_dbg("report ID: 0x%02X", buf[0]);
// NB: HidD_GetInputReport returns the last Input Report read whereas ReadFile
// waits for input to be generated => in case your HID device requires human
// action to generate a report, it may wait indefinitely.
@@ -3092,7 +3092,7 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i
}
buf[0] = (uint8_t)id;
- usbi_dbg("report ID: %02X", buf[0]);
+ usbi_dbg("report ID: 0x%02X", buf[0]);
memcpy(buf + 1, data, *size);
#if !defined(USE_HIDD_FOR_REPORTS)
@@ -3211,6 +3211,7 @@ static int hid_init(struct libusb_context *ctx)
DLL_LOAD(hid.dll, HidD_GetInputReport, FALSE);
DLL_LOAD(hid.dll, HidD_SetOutputReport, FALSE);
DLL_LOAD(hid.dll, HidD_FlushQueue, TRUE);
+ DLL_LOAD(hid.dll, HidP_GetValueCaps, TRUE);
api_hid_available = true;
return LIBUSB_SUCCESS;
@@ -3233,8 +3234,10 @@ static int hid_open(struct libusb_device_handle *dev_handle)
HIDD_ATTRIBUTES hid_attributes;
PHIDP_PREPARSED_DATA preparsed_data = NULL;
HIDP_CAPS capabilities;
+ HIDP_VALUE_CAPS *value_caps;
HANDLE hid_handle = INVALID_HANDLE_VALUE;
+ ULONG size;
int i;
CHECK_HID_AVAILABLE;
@@ -3298,6 +3301,54 @@ static int hid_open(struct libusb_device_handle *dev_handle)
usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
break;
}
+ // Get the default input and output report IDs to use with interrupt
+ size = capabilities.NumberInputValueCaps;
+ usbi_dbg("%d HID input report value(s) found", size);
+ priv->hid->input_report_id = 0;
+ if (size > 0) {
+ value_caps = malloc(size * sizeof(HIDP_VALUE_CAPS));
+ if ( (value_caps != NULL)
+ && (HidP_GetValueCaps(HidP_Input, value_caps, &size, preparsed_data) == HIDP_STATUS_SUCCESS)
+ && (size >= 1) ) {
+ priv->hid->input_report_id = value_caps[0].ReportID;
+ for (i=1; i<(int)size; i++) {
+ if (value_caps[i].ReportID != priv->hid->input_report_id) {
+ usbi_warn(ctx, "multiple input report IDs found for HID");
+ usbi_warn(ctx, " will only handle report ID 0x%02X for interrupt transfers",
+ priv->hid->input_report_id);
+ break;
+ }
+ }
+ usbi_dbg("will use report ID 0x%02X for interrupt transfers", priv->hid->input_report_id);
+ } else {
+ usbi_warn(ctx, "could process input report IDs");
+ }
+ safe_free(value_caps);
+ }
+
+ size = capabilities.NumberOutputValueCaps;
+ usbi_dbg("%d HID output report value(s) found", size);
+ priv->hid->output_report_id = 0;
+ if (size > 0) {
+ value_caps = malloc(size * sizeof(HIDP_VALUE_CAPS));
+ if ( (value_caps != NULL)
+ && (HidP_GetValueCaps(HidP_Output, value_caps, &size, preparsed_data) == HIDP_STATUS_SUCCESS)
+ && (size >= 1) ) {
+ priv->hid->output_report_id = value_caps[0].ReportID;
+ for (i=1; i<(int)size; i++) {
+ if (value_caps[i].ReportID != priv->hid->output_report_id) {
+ usbi_warn(ctx, "multiple output report IDs found for HID");
+ usbi_warn(ctx, " will only handle report ID 0x%02X for interrupt transfers",
+ priv->hid->output_report_id);
+ break;
+ }
+ }
+ usbi_dbg("will use report ID 0x%02X for interrupt transfers", priv->hid->output_report_id);
+ } else {
+ usbi_warn(ctx, "could process output report IDs");
+ }
+ safe_free(value_caps);
+ }
priv->hid->output_report_size = capabilities.OutputReportByteLength;
priv->hid->input_report_size = capabilities.InputReportByteLength;
priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
@@ -3554,14 +3605,13 @@ static int hid_submit_bulk_transfer(struct usbi_transfer *itransfer) {
if (transfer_priv->hid_buffer == NULL) {
return LIBUSB_ERROR_NO_MEM;
}
- // TODO: can we figure out report ID here?
- transfer_priv->hid_buffer[0] = 0;
-
if (direction_in) {
- usbi_dbg("reading %d bytes", transfer->length+1);
+ transfer_priv->hid_buffer[0] = priv->hid->input_report_id;
+ usbi_dbg("reading %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]);
ret = ReadFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
} else {
- usbi_dbg("writing %d bytes", transfer->length+1);
+ transfer_priv->hid_buffer[0] = priv->hid->output_report_id;
+ usbi_dbg("writing %d bytes (report ID: 0x%02X)", transfer->length+1, transfer_priv->hid_buffer[0]);
transfer_priv->hid_buffer[0] = 0;
ret = WriteFile(hid_handle, transfer_priv->hid_buffer, transfer->length+1, &size, wfd.overlapped);
}
diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h
index 90aa879..cd74e22 100644
--- a/libusb/os/windows_usb.h
+++ b/libusb/os/windows_usb.h
@@ -213,8 +213,11 @@ struct hid_device_priv {
uint16_t vid;
uint16_t pid;
uint8_t config;
- uint16_t output_report_size;
+ uint8_t input_report_id;
+ uint8_t output_report_id;
+ uint8_t feature_report_id;
uint16_t input_report_size;
+ uint16_t output_report_size;
uint16_t feature_report_size;
WCHAR man_string[MAX_USB_STRING_LENGTH];
WCHAR prod_string[MAX_USB_STRING_LENGTH];
@@ -721,6 +724,49 @@ typedef struct {
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
+typedef enum _HIDP_REPORT_TYPE {
+ HidP_Input,
+ HidP_Output,
+ HidP_Feature
+} HIDP_REPORT_TYPE;
+
+typedef struct _HIDP_VALUE_CAPS {
+ USAGE UsagePage;
+ UCHAR ReportID;
+ BOOLEAN IsAlias;
+ USHORT BitField;
+ USHORT LinkCollection;
+ USAGE LinkUsage;
+ USAGE LinkUsagePage;
+ BOOLEAN IsRange;
+ BOOLEAN IsStringRange;
+ BOOLEAN IsDesignatorRange;
+ BOOLEAN IsAbsolute;
+ BOOLEAN HasNull;
+ UCHAR Reserved;
+ USHORT BitSize;
+ USHORT ReportCount;
+ USHORT Reserved2[5];
+ ULONG UnitsExp;
+ ULONG Units;
+ LONG LogicalMin, LogicalMax;
+ LONG PhysicalMin, PhysicalMax;
+ union {
+ struct {
+ USAGE UsageMin, UsageMax;
+ USHORT StringMin, StringMax;
+ USHORT DesignatorMin, DesignatorMax;
+ USHORT DataIndexMin, DataIndexMax;
+ } Range;
+ struct {
+ USAGE Usage, Reserved1;
+ USHORT StringIndex, Reserved2;
+ USHORT DesignatorIndex, Reserved3;
+ USHORT DataIndex, Reserved4;
+ } NotRange;
+ };
+} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
+
DLL_DECLARE(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES));
DLL_DECLARE(WINAPI, VOID, HidD_GetHidGuid, (LPGUID));
DLL_DECLARE(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *));
@@ -736,3 +782,4 @@ DLL_DECLARE(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG));
DLL_DECLARE(WINAPI, BOOL, HidD_FlushQueue, (HANDLE));
+DLL_DECLARE(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA));