summaryrefslogtreecommitdiff
path: root/libusb/os/windows_usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusb/os/windows_usb.c')
-rw-r--r--libusb/os/windows_usb.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 98dbb67..48eab9a 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -18,6 +18,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+// COMPILATION OPTIONS:
+// - Use HidD_Get(In/Out)putReport instead of (Read/Write)File for HID
+//#define HID_USE_LAST_REPORTS
+// - Should libusb automatically claim the interfaces it requires?
+#define AUTO_CLAIM
+
#if defined(_MSC_VER)
#include <config_msvc.h>
#else
@@ -1778,8 +1784,7 @@ static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t
switch(io_result) {
case NO_ERROR:
- status = LIBUSB_TRANSFER_COMPLETED;
- priv->apib->copy_transfer_data(itransfer, io_size);
+ status = priv->apib->copy_transfer_data(itransfer, io_size);
break;
case ERROR_GEN_FAILURE:
usbi_dbg("detected endpoint stall");
@@ -2259,17 +2264,26 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i
CHECK_WINUSB_AVAILABLE;
- winusb_handle = handle_priv->interface_handle[iface].api_handle;
-
// interfaces for composite devices are always independent, therefore
// "alt" interfaces are only found on non-composite
if ((!is_composite) && (iface != 0)) {
+ winusb_handle = handle_priv->interface_handle[0].api_handle;
// It is a requirement on Windows that to claim an interface >= 1
// on a non-composite WinUSB device, you must first have claimed interface 0
if ((winusb_handle == 0) || (winusb_handle == INVALID_HANDLE_VALUE)) {
+#if defined(AUTO_CLAIM)
+ file_handle = handle_priv->interface_handle[0].dev_handle;
+ if (WinUsb_Initialize(file_handle, &winusb_handle)) {
+ handle_priv->interface_handle[0].api_handle = winusb_handle;
+ usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface);
+ } else {
+ usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB)", iface);
+ return LIBUSB_ERROR_ACCESS;
+ }
+#else
return LIBUSB_ERROR_ACCESS;
+#endif
}
-
if (!WinUsb_GetAssociatedInterface(winusb_handle, (UCHAR)(iface-1),
&handle_priv->interface_handle[iface].api_handle)) {
handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
@@ -2287,6 +2301,7 @@ static int winusb_claim_interface(struct libusb_device_handle *dev_handle, int i
}
} else {
// composite device (independent interfaces) or interface 0
+ winusb_handle = handle_priv->interface_handle[iface].api_handle;
file_handle = handle_priv->interface_handle[iface].dev_handle;
if ((file_handle == 0) || (file_handle == INVALID_HANDLE_VALUE)) {
return LIBUSB_ERROR_NOT_FOUND;
@@ -2426,6 +2441,7 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer)
current_interface = get_valid_interface(transfer->dev_handle);
// Attempt to claim an interface if none was found
if (current_interface < 0) {
+#if defined(AUTO_CLAIM)
for (current_interface=0; current_interface<USB_MAXINTERFACES; current_interface++) {
if (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS) {
usbi_warn(ctx, "auto-claimed interface %d for control request", current_interface);
@@ -2437,6 +2453,10 @@ static int winusb_submit_control_transfer(struct usbi_transfer *itransfer)
usbi_err(ctx, "no active interface");
return LIBUSB_ERROR_NOT_FOUND;
}
+#else
+ return LIBUSB_ERROR_NOT_FOUND;
+ }
+#endif
usbi_dbg("will use interface %d", current_interface);
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
@@ -2671,7 +2691,7 @@ static int winusb_reset_device(struct libusb_device_handle *dev_handle)
static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
{
itransfer->transferred += io_size;
- return LIBUSB_SUCCESS;
+ return LIBUSB_TRANSFER_COMPLETED;
}
/*
@@ -2865,7 +2885,6 @@ static int _hid_get_hid_descriptor(struct hid_device_priv* dev, void *data, size
return LIBUSB_COMPLETED;
}
-// TODO: handle buffer OVERFLOWS!!!!
static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, size_t *size)
{
uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
@@ -2907,7 +2926,6 @@ static int _hid_get_report_descriptor(struct hid_device_priv* dev, void *data, s
/* output (data, variable, absolute) */
d[i++] = 0x91; d[i++] = 0x00;
}
- // TODO: feature report?
/* end collection */
d[i++] = 0xC0;
@@ -3202,7 +3220,6 @@ static int hid_open(struct libusb_device_handle *dev_handle)
*/
if (hid_handle == INVALID_HANDLE_VALUE) {
usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
- // TODO: can we confirm KB/mouse?
hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (hid_handle == INVALID_HANDLE_VALUE) {
@@ -3221,36 +3238,34 @@ static int hid_open(struct libusb_device_handle *dev_handle)
}
}
- // TODO: more comprehensive error messages
hid_attributes.Size = sizeof(hid_attributes);
do {
- if(!HidD_GetAttributes(hid_handle, &hid_attributes)) {
- usbi_err(ctx, "HidD_GetAttributes() failed");
+ if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
+ usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
break;
}
priv->hid->vid = hid_attributes.VendorID;
priv->hid->pid = hid_attributes.ProductID;
- /* set the maximum available input buffer size */
- i = 32;
- while(HidD_SetNumInputBuffers(hid_handle, i))
- i *= 2;
+ // Set the maximum available input buffer size
+ for (i=32; HidD_SetNumInputBuffers(hid_handle, i); i*=2);
+ usbi_dbg("set maximum input buffer size to %d", i/2);
- /* get the maximum input and output report size */
- if(!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
- usbi_err(ctx, "HidD_GetPreparsedData() failed");
+ // Get the maximum input and output report size
+ if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
+ usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
break;
}
- if(HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
- usbi_err(ctx, "HidP_GetCaps() failed");
+ if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
+ usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
break;
}
priv->hid->output_report_size = capabilities.OutputReportByteLength;
priv->hid->input_report_size = capabilities.InputReportByteLength;
priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
- /* fetch string descriptors */
+ // Fetch string descriptors
HidD_GetManufacturerString(hid_handle, priv->hid->man_string,
sizeof(priv->hid->man_string));
HidD_GetProductString(hid_handle, priv->hid->prod_string,
@@ -3259,8 +3274,9 @@ static int hid_open(struct libusb_device_handle *dev_handle)
sizeof(priv->hid->ser_string));
} while(0);
- if(preparsed_data)
+ if (preparsed_data) {
HidD_FreePreparsedData(preparsed_data);
+ }
return LIBUSB_SUCCESS;
}
@@ -3292,8 +3308,7 @@ static int hid_claim_interface(struct libusb_device_handle *dev_handle, int ifac
CHECK_HID_AVAILABLE;
- // TODO: device disconected (return LIBUSB_ERROR_NO_DEVICE;)
-
+ // NB: Disconnection detection is not possible in this function
if (priv->usb_interface[iface].path == NULL) {
return LIBUSB_ERROR_NOT_FOUND; // invalid iface
}
@@ -3607,7 +3622,7 @@ static int hid_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_s
struct libusb_transfer *transfer = __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- int r = LIBUSB_SUCCESS;
+ int r = LIBUSB_TRANSFER_COMPLETED;
uint32_t corrected_size = 0;
if (transfer_priv->hid_buffer != NULL) {
@@ -3617,7 +3632,7 @@ static int hid_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_s
if (corrected_size > transfer_priv->hid_expected_size) {
corrected_size = (uint32_t)transfer_priv->hid_expected_size;
usbi_err(ctx, "OVERFLOW!");
- r = LIBUSB_ERROR_OVERFLOW;
+ r = LIBUSB_TRANSFER_OVERFLOW;
}
memcpy(transfer->buffer, transfer_priv->hid_buffer+1, corrected_size);
safe_free(transfer_priv->hid_buffer);