aboutsummaryrefslogtreecommitdiff
path: root/libusb/os/windows_winusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusb/os/windows_winusb.c')
-rw-r--r--libusb/os/windows_winusb.c475
1 files changed, 294 insertions, 181 deletions
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index f291b8e..ffc1612 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -28,14 +28,9 @@
#include <windows.h>
#include <setupapi.h>
#include <ctype.h>
-#include <fcntl.h>
-#include <process.h>
#include <stdio.h>
-#include <objbase.h>
-#include <winioctl.h>
#include "libusbi.h"
-#include "windows_common.h"
#include "windows_winusb.h"
#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE))
@@ -109,12 +104,12 @@ static struct winusb_interface WinUSBX[SUB_API_MAX];
} while (0)
#if defined(ENABLE_LOGGING)
-static const char *guid_to_string(const GUID *guid)
+static const char *guid_to_string(const GUID *guid, char guid_string[MAX_GUID_STRING_LENGTH])
{
- static char guid_string[MAX_GUID_STRING_LENGTH];
-
- if (guid == NULL)
- return "";
+ if (guid == NULL) {
+ guid_string[0] = '\0';
+ return guid_string;
+ }
sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
(unsigned int)guid->Data1, guid->Data2, guid->Data3,
@@ -125,6 +120,37 @@ static const char *guid_to_string(const GUID *guid)
}
#endif
+static bool string_to_guid(const char guid_string[MAX_GUID_STRING_LENGTH], GUID *guid)
+{
+ unsigned short tmp[4];
+ int num_chars = -1;
+ char extra;
+ int r;
+
+ // Unfortunately MinGW complains that '%hhx' is not a valid format specifier,
+ // even though Visual Studio 2013 and later support it. Rather than complicating
+ // the logic in this function with '#ifdef's, use a temporary array on the stack
+ // to store the conversions.
+ r = sscanf(guid_string, "{%8x-%4hx-%4hx-%4hx-%4hx%4hx%4hx}%n%c",
+ (unsigned int *)&guid->Data1, &guid->Data2, &guid->Data3,
+ &tmp[0], &tmp[1], &tmp[2], &tmp[3], &num_chars, &extra);
+
+ if ((r != 7) || (num_chars != 38))
+ return false;
+
+ // Extract the bytes from the 2-byte shorts
+ guid->Data4[0] = (unsigned char)((tmp[0] >> 8) & 0xFF);
+ guid->Data4[1] = (unsigned char)(tmp[0] & 0xFF);
+ guid->Data4[2] = (unsigned char)((tmp[1] >> 8) & 0xFF);
+ guid->Data4[3] = (unsigned char)(tmp[1] & 0xFF);
+ guid->Data4[4] = (unsigned char)((tmp[2] >> 8) & 0xFF);
+ guid->Data4[5] = (unsigned char)(tmp[2] & 0xFF);
+ guid->Data4[6] = (unsigned char)((tmp[3] >> 8) & 0xFF);
+ guid->Data4[7] = (unsigned char)(tmp[3] & 0xFF);
+
+ return true;
+}
+
/*
* Normalize Microsoft's paths: return a duplicate of the given path
* with all characters converted to uppercase
@@ -154,12 +180,9 @@ static bool init_dlls(struct libusb_context *ctx)
// Prefixed to avoid conflict with header files
DLL_GET_HANDLE(ctx, AdvAPI32);
- DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, true);
+ DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExA, true);
DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, true);
- DLL_GET_HANDLE(ctx, OLE32);
- DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, true);
-
DLL_GET_HANDLE(ctx, SetupAPI);
DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, true);
DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, true);
@@ -177,7 +200,6 @@ static bool init_dlls(struct libusb_context *ctx)
static void exit_dlls(void)
{
DLL_FREE_HANDLE(SetupAPI);
- DLL_FREE_HANDLE(OLE32);
DLL_FREE_HANDLE(AdvAPI32);
DLL_FREE_HANDLE(Cfgmgr32);
}
@@ -238,6 +260,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
{
SP_DEVICE_INTERFACE_DATA dev_interface_data;
PSP_DEVICE_INTERFACE_DETAIL_DATA_A dev_interface_details;
+ char guid_string[MAX_GUID_STRING_LENGTH];
DWORD size;
dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
@@ -246,7 +269,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
if (!pSetupDiEnumDeviceInfo(dev_info, *_index, dev_info_data)) {
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
usbi_err(ctx, "Could not obtain device info data for %s index %lu: %s",
- guid_to_string(guid), ULONG_CAST(*_index), windows_error_str(0));
+ guid_to_string(guid, guid_string), ULONG_CAST(*_index), windows_error_str(0));
return LIBUSB_ERROR_OTHER;
}
@@ -262,7 +285,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
usbi_err(ctx, "Could not obtain interface data for %s devInst %lX: %s",
- guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
return LIBUSB_ERROR_OTHER;
}
@@ -274,7 +297,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
usbi_err(ctx, "could not access interface data (dummy) for %s devInst %lX: %s",
- guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
return LIBUSB_ERROR_OTHER;
}
} else {
@@ -285,7 +308,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
dev_interface_details = malloc(size);
if (dev_interface_details == NULL) {
usbi_err(ctx, "could not allocate interface data for %s devInst %lX",
- guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst));
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst));
return LIBUSB_ERROR_NO_MEM;
}
@@ -293,7 +316,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
if (!pSetupDiGetDeviceInterfaceDetailA(dev_info, &dev_interface_data,
dev_interface_details, size, NULL, NULL)) {
usbi_err(ctx, "could not access interface data (actual) for %s devInst %lX: %s",
- guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst), windows_error_str(0));
free(dev_interface_details);
return LIBUSB_ERROR_OTHER;
}
@@ -303,7 +326,7 @@ static int get_interface_details(struct libusb_context *ctx, HDEVINFO dev_info,
if (*dev_interface_path == NULL) {
usbi_err(ctx, "could not allocate interface path for %s devInst %lX",
- guid_to_string(guid), ULONG_CAST(dev_info_data->DevInst));
+ guid_to_string(guid, guid_string), ULONG_CAST(dev_info_data->DevInst));
return LIBUSB_ERROR_NO_MEM;
}
@@ -386,14 +409,14 @@ static int get_interface_details_filter(struct libusb_context *ctx, HDEVINFO *de
DWORD value_length = sizeof(DWORD);
LONG status;
- status = pRegQueryValueExW(hkey_dev_interface, L"LUsb0", NULL, NULL,
+ status = pRegQueryValueExA(hkey_dev_interface, "LUsb0", NULL, NULL,
(LPBYTE)&libusb0_symboliclink_index, &value_length);
if (status == ERROR_SUCCESS) {
if (libusb0_symboliclink_index < 256) {
// libusb0.sys is connected to this device instance.
// If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
- usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
+ usbi_dbg(ctx, "assigned libusb0 symbolic link %s", filter_path);
} else {
// libusb0.sys was connected to this device instance at one time; but not anymore.
}
@@ -451,23 +474,23 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc,
intf_desc = &intf->altsetting[j];
for (k = 0; k < intf_desc->bNumEndpoints; k++) {
if (intf_desc->endpoint[k].bEndpointAddress == ep) {
- usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
+ usbi_dbg(NULL, "found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
return intf_desc->bInterfaceNumber;
}
}
}
}
- usbi_dbg("endpoint %02X not found on any interface", ep);
+ usbi_dbg(NULL, "endpoint %02X not found on any interface", ep);
return LIBUSB_ERROR_NOT_FOUND;
}
/*
* Open a device and associate the HANDLE with the context's I/O completion port
*/
-static HANDLE windows_open(struct libusb_device *dev, const char *path, DWORD access)
+static HANDLE windows_open(struct libusb_device_handle *dev_handle, const char *path, DWORD access)
{
- struct libusb_context *ctx = DEVICE_CTX(dev);
+ struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct windows_context_priv *priv = usbi_get_context_priv(ctx);
HANDLE handle;
@@ -475,7 +498,7 @@ static HANDLE windows_open(struct libusb_device *dev, const char *path, DWORD ac
if (handle == INVALID_HANDLE_VALUE)
return handle;
- if (CreateIoCompletionPort(handle, priv->completion_port, 0, 0) == NULL) {
+ if (CreateIoCompletionPort(handle, priv->completion_port, (ULONG_PTR)dev_handle, 0) == NULL) {
usbi_err(ctx, "failed to associate handle to I/O completion port: %s", windows_error_str(0));
CloseHandle(handle);
return INVALID_HANDLE_VALUE;
@@ -500,26 +523,26 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, uin
return r;
}
+ if (iface >= conf_desc->bNumInterfaces) {
+ usbi_err(HANDLE_CTX(dev_handle), "interface %d out of range for device", iface);
+ return LIBUSB_ERROR_NOT_FOUND;
+ }
if_desc = &conf_desc->interface[iface].altsetting[altsetting];
safe_free(priv->usb_interface[iface].endpoint);
if (if_desc->bNumEndpoints == 0) {
- usbi_dbg("no endpoints found for interface %u", iface);
- libusb_free_config_descriptor(conf_desc);
- priv->usb_interface[iface].current_altsetting = altsetting;
- return LIBUSB_SUCCESS;
- }
-
- priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
- if (priv->usb_interface[iface].endpoint == NULL) {
- libusb_free_config_descriptor(conf_desc);
- return LIBUSB_ERROR_NO_MEM;
- }
-
- priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
- for (i = 0; i < if_desc->bNumEndpoints; i++) {
- priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
- usbi_dbg("(re)assigned endpoint %02X to interface %u", priv->usb_interface[iface].endpoint[i], iface);
+ usbi_dbg(HANDLE_CTX(dev_handle), "no endpoints found for interface %u", iface);
+ } else {
+ priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
+ if (priv->usb_interface[iface].endpoint == NULL) {
+ libusb_free_config_descriptor(conf_desc);
+ return LIBUSB_ERROR_NO_MEM;
+ }
+ priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
+ for (i = 0; i < if_desc->bNumEndpoints; i++) {
+ priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
+ usbi_dbg(HANDLE_CTX(dev_handle), "(re)assigned endpoint %02X to interface %u", priv->usb_interface[iface].endpoint[i], iface);
+ }
}
libusb_free_config_descriptor(conf_desc);
@@ -570,7 +593,7 @@ static int get_sub_api(char *driver, int api)
static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
{
struct winusb_device_handle_priv *handle_priv =
- usbi_get_device_handle_priv(transfer->dev_handle);
+ get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
int current_interface = *interface_number;
int r = LIBUSB_SUCCESS;
@@ -589,7 +612,7 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i
// Must claim an interface of the same API type
if ((priv->usb_interface[current_interface].apib->id == api_type)
&& (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) {
- usbi_dbg("auto-claimed interface %d for control request", current_interface);
+ usbi_dbg(TRANSFER_CTX(transfer), "auto-claimed interface %d for control request", current_interface);
if (handle_priv->autoclaim_count[current_interface] != 0)
usbi_err(TRANSFER_CTX(transfer), "program assertion failed - autoclaim_count was nonzero");
handle_priv->autoclaim_count[current_interface]++;
@@ -617,7 +640,7 @@ static void auto_release(struct usbi_transfer *itransfer)
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
libusb_device_handle *dev_handle = transfer->dev_handle;
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
int r;
usbi_mutex_lock(&autoclaim_lock);
@@ -626,9 +649,9 @@ static void auto_release(struct usbi_transfer *itransfer)
if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) {
r = libusb_release_interface(dev_handle, transfer_priv->interface_number);
if (r == LIBUSB_SUCCESS)
- usbi_dbg("auto-released interface %d", transfer_priv->interface_number);
+ usbi_dbg(ITRANSFER_CTX(itransfer), "auto-released interface %d", transfer_priv->interface_number);
else
- usbi_dbg("failed to auto-release interface %d (%s)",
+ usbi_dbg(ITRANSFER_CTX(itransfer), "failed to auto-release interface %d (%s)",
transfer_priv->interface_number, libusb_error_name((enum libusb_error)r));
}
}
@@ -769,7 +792,7 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
continue;
}
- usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
+ usbi_dbg(ctx, "cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
i, cd_data->bConfigurationValue, cd_data->wTotalLength);
// Cache the descriptor
@@ -886,7 +909,7 @@ static int init_root_hub(struct libusb_device *dev)
}
num_ports = hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts;
- usbi_dbg("root hub '%s' reports %lu ports", priv->dev_id, ULONG_CAST(num_ports));
+ usbi_dbg(ctx, "root hub '%s' reports %lu ports", priv->dev_id, ULONG_CAST(num_ports));
if (windows_version >= WINDOWS_8) {
// Windows 8 and later is better at reporting the speed capabilities of the root hub,
@@ -1021,7 +1044,7 @@ make_descriptors:
static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev,
uint8_t port_number, DEVINST devinst)
{
- struct libusb_context *ctx;
+ struct libusb_context *ctx = NULL;
struct libusb_device *tmp_dev;
struct winusb_device_priv *priv, *parent_priv, *tmp_priv;
USB_NODE_CONNECTION_INFORMATION_EX conn_info;
@@ -1120,7 +1143,7 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
priv->active_config = conn_info.CurrentConfigurationValue;
if (priv->active_config == 0) {
- usbi_dbg("0x%x:0x%x found %u configurations (not configured)",
+ usbi_dbg(ctx, "0x%x:0x%x found %u configurations (not configured)",
dev->device_descriptor.idVendor,
dev->device_descriptor.idProduct,
dev->device_descriptor.bNumConfigurations);
@@ -1143,7 +1166,7 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
dev->device_descriptor.bNumConfigurations);
priv->active_config = 1;
} else {
- usbi_dbg("found %u configurations (current config: %u)", dev->device_descriptor.bNumConfigurations, priv->active_config);
+ usbi_dbg(ctx, "found %u configurations (current config: %u)", dev->device_descriptor.bNumConfigurations, priv->active_config);
}
// Cache as many config descriptors as we can
@@ -1194,12 +1217,53 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
priv->initialized = true;
- usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
+ usbi_dbg(ctx, "(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
dev->bus_number, dev->device_address, priv->depth, dev->port_number, priv->dev_id);
return LIBUSB_SUCCESS;
}
+static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_data, DWORD *port_nr)
+{
+ char buffer[MAX_KEY_LENGTH];
+ DWORD size;
+
+ // First try SPDRP_LOCATION_INFORMATION, which returns a REG_SZ. The string *may* have a format
+ // similar to "Port_#0002.Hub_#000D", in which case we can extract the port number. However, we
+ // cannot extract the port if the returned string does not follow this format.
+ if (pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_LOCATION_INFORMATION,
+ NULL, (PBYTE)buffer, sizeof(buffer), NULL)) {
+ // Check for the required format.
+ if (strncmp(buffer, "Port_#", 6) == 0) {
+ *port_nr = atoi(buffer + 6);
+ return true;
+ }
+ }
+
+ // Next try SPDRP_LOCATION_PATHS, which returns a REG_MULTI_SZ (but we only examine the first
+ // string in it). Each path has a format similar to,
+ // "PCIROOT(B2)#PCI(0300)#PCI(0000)#USBROOT(0)#USB(1)#USB(2)#USBMI(3)", and the port number is
+ // the number within the last "USB(x)" token.
+ if (pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_LOCATION_PATHS,
+ NULL, (PBYTE)buffer, sizeof(buffer), NULL)) {
+ // Find the last "#USB(x)" substring
+ for (char *token = strrchr(buffer, '#'); token != NULL; token = strrchr(buffer, '#')) {
+ if (strncmp(token, "#USB(", 5) == 0) {
+ *port_nr = atoi(token + 5);
+ return true;
+ }
+ // Shorten the string and try again.
+ *token = '\0';
+ }
+ }
+
+ // Lastly, try SPDRP_ADDRESS, which returns a REG_DWORD. The address *may* be the port number,
+ // which is true for the Microsoft driver but may not be true for other drivers. However, we
+ // have no other options here but to accept what it returns.
+ return pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_ADDRESS,
+ NULL, (PBYTE)port_nr, sizeof(*port_nr), &size) && (size == sizeof(*port_nr));
+}
+
static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id,
uint8_t bus_number, DEVINST devinst)
{
@@ -1222,7 +1286,7 @@ static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id
if (dev->bus_number == 0) {
// Only do this once
- usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number);
+ usbi_dbg(ctx, "assigning HCD '%s' bus number %u", dev_id, bus_number);
dev->bus_number = bus_number;
if (sscanf(dev_id, "PCI\\VEN_%04hx&DEV_%04hx%*s", &dev->device_descriptor.idVendor, &dev->device_descriptor.idProduct) != 2)
@@ -1266,10 +1330,10 @@ static void get_api_type(HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data,
if (lookup[k].list[l] == 0)
lookup[k].list[l] = LIST_SEPARATOR;
}
- usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
+ usbi_dbg(NULL, "%s(s): %s", lookup[k].designation, lookup[k].list);
} else {
if (GetLastError() != ERROR_INVALID_DATA)
- usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
+ usbi_dbg(NULL, "could not access %s: %s", lookup[k].designation, windows_error_str(0));
lookup[k].list[0] = 0;
}
}
@@ -1278,7 +1342,7 @@ static void get_api_type(HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data,
for (k = 0; k < 3; k++) {
j = get_sub_api(lookup[k].list, i);
if (j >= 0) {
- usbi_dbg("matched %s name against %s", lookup[k].designation,
+ usbi_dbg(NULL, "matched %s name against %s", lookup[k].designation,
(i != USB_API_WINUSBX) ? usb_api_backend[i].designation : usb_api_backend[i].driver_name_list[j]);
*api = i;
*sub_api = j;
@@ -1314,7 +1378,7 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
if (priv->usb_interface[interface_number].path != NULL) {
if (api == USB_API_HID) {
// HID devices can have multiple collections (COL##) for each MI_## interface
- usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
+ usbi_dbg(ctx, "interface[%d] already set - ignoring HID collection: %s",
interface_number, device_id);
return LIBUSB_ERROR_ACCESS;
}
@@ -1322,7 +1386,7 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
safe_free(priv->usb_interface[interface_number].path);
}
- usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path);
+ usbi_dbg(ctx, "interface[%d] = %s", interface_number, dev_interface_path);
priv->usb_interface[interface_number].path = dev_interface_path;
priv->usb_interface[interface_number].apib = &usb_api_backend[api];
priv->usb_interface[interface_number].sub_api = sub_api;
@@ -1351,14 +1415,14 @@ static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *d
for (i = 0; i < priv->hid->nb_interfaces; i++) {
if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
- usbi_dbg("interface[%u] already set to %s", i, dev_interface_path);
+ usbi_dbg(ctx, "interface[%u] already set to %s", i, dev_interface_path);
return LIBUSB_ERROR_ACCESS;
}
}
priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID];
- usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
+ usbi_dbg(ctx, "interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
priv->hid->nb_interfaces++;
return LIBUSB_SUCCESS;
}
@@ -1384,7 +1448,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
unsigned long session_id;
DWORD size, port_nr, reg_type, install_state;
HKEY key;
- WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
+ char guid_string[MAX_GUID_STRING_LENGTH];
GUID *if_guid;
LONG s;
#define HUB_PASS 0
@@ -1454,7 +1518,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
//#define ENUM_DEBUG
#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
const char * const passname[] = {"HUB", "DEV", "HCD", "GEN", "HID", "EXT"};
- usbi_dbg("#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass]));
+ usbi_dbg(ctx, "#### PROCESSING %ss %s", passname[MIN(pass, EXT_PASS)], guid_to_string(guid_list[pass], guid_string));
#endif
if ((pass == HID_PASS) && (guid_list[HID_PASS] == NULL))
continue;
@@ -1506,7 +1570,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
}
#ifdef ENUM_DEBUG
- usbi_dbg("PRO: %s", dev_id);
+ usbi_dbg(ctx, "PRO: %s", dev_id);
#endif
// Set API to use or get additional data from generic pass
@@ -1529,7 +1593,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
break;
}
if (j == nb_usb_enumerators) {
- usbi_dbg("found new PnP enumerator string '%s'", enumerator);
+ usbi_dbg(ctx, "found new PnP enumerator string '%s'", enumerator);
if (nb_usb_enumerators < ARRAYSIZE(usb_enumerator)) {
usb_enumerator[nb_usb_enumerators] = _strdup(enumerator);
if (usb_enumerator[nb_usb_enumerators] != NULL) {
@@ -1555,16 +1619,25 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
if (key == INVALID_HANDLE_VALUE)
break;
// Look for both DeviceInterfaceGUIDs *and* DeviceInterfaceGUID, in that order
- size = sizeof(guid_string_w);
- s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, &reg_type,
- (LPBYTE)guid_string_w, &size);
+ // If multiple GUIDs just process the first and ignore the others
+ size = sizeof(guid_string);
+ s = pRegQueryValueExA(key, "DeviceInterfaceGUIDs", NULL, &reg_type,
+ (LPBYTE)guid_string, &size);
if (s == ERROR_FILE_NOT_FOUND)
- s = pRegQueryValueExW(key, L"DeviceInterfaceGUID", NULL, &reg_type,
- (LPBYTE)guid_string_w, &size);
+ s = pRegQueryValueExA(key, "DeviceInterfaceGUID", NULL, &reg_type,
+ (LPBYTE)guid_string, &size);
pRegCloseKey(key);
- if ((s == ERROR_SUCCESS) &&
- (((reg_type == REG_SZ) && (size == (sizeof(guid_string_w) - sizeof(WCHAR)))) ||
- ((reg_type == REG_MULTI_SZ) && (size == sizeof(guid_string_w))))) {
+ if (s == ERROR_FILE_NOT_FOUND) {
+ break; /* no DeviceInterfaceGUID registered */
+ } else if (s != ERROR_SUCCESS && s != ERROR_MORE_DATA) {
+ usbi_warn(ctx, "unexpected error from pRegQueryValueExA for '%s'", dev_id);
+ break;
+ }
+ // https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa#remarks
+ // - "string may not have been stored with the proper terminating null characters"
+ // - "Note that REG_MULTI_SZ strings could have two terminating null characters"
+ if ((reg_type == REG_SZ && size >= sizeof(guid_string) - sizeof(char))
+ || (reg_type == REG_MULTI_SZ && size >= sizeof(guid_string) - 2 * sizeof(char))) {
if (nb_guids == guid_size) {
new_guid_list = realloc((void *)guid_list, (guid_size + GUID_SIZE_STEP) * sizeof(void *));
if (new_guid_list == NULL) {
@@ -1579,8 +1652,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
usbi_err(ctx, "failed to alloc if_guid");
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
}
- if (pIIDFromString(guid_string_w, if_guid) != 0) {
- usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string, skipping", dev_id);
+ if (!string_to_guid(guid_string, if_guid)) {
+ usbi_warn(ctx, "device '%s' has malformed DeviceInterfaceGUID string '%s', skipping", dev_id, guid_string);
free(if_guid);
} else {
// Check if we've already seen this GUID
@@ -1589,14 +1662,14 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
break;
}
if (j == nb_guids) {
- usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
+ usbi_dbg(ctx, "extra GUID: %s", guid_string);
guid_list[nb_guids++] = if_guid;
} else {
// Duplicate, ignore
free(if_guid);
}
}
- } else if (s == ERROR_SUCCESS) {
+ } else {
usbi_warn(ctx, "unexpected type/size of DeviceInterfaceGUID for '%s'", dev_id);
}
break;
@@ -1631,7 +1704,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
libusb_unref_device(dev);
}
- usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id);
+ usbi_dbg(ctx, "unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id);
continue;
}
@@ -1650,23 +1723,30 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
alloc_device:
- usbi_dbg("allocating new device for session [%lX]", session_id);
+ usbi_dbg(ctx, "allocating new device for session [%lX]", session_id);
dev = usbi_alloc_device(ctx, session_id);
if (dev == NULL)
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
priv = winusb_device_priv_init(dev);
priv->dev_id = _strdup(dev_id);
+ priv->class_guid = dev_info_data.ClassGuid;
if (priv->dev_id == NULL) {
libusb_unref_device(dev);
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
}
} else {
- usbi_dbg("found existing device for session [%lX]", session_id);
+ usbi_dbg(ctx, "found existing device for session [%lX]", session_id);
priv = usbi_get_device_priv(dev);
if (strcmp(priv->dev_id, dev_id) != 0) {
- usbi_dbg("device instance ID for session [%lX] changed", session_id);
+ usbi_dbg(ctx, "device instance ID for session [%lX] changed", session_id);
+ usbi_disconnect_device(dev);
+ libusb_unref_device(dev);
+ goto alloc_device;
+ }
+ if (!IsEqualGUID(&priv->class_guid, &dev_info_data.ClassGuid)) {
+ usbi_dbg(ctx, "device class GUID for session [%lX] changed", session_id);
usbi_disconnect_device(dev);
libusb_unref_device(dev);
goto alloc_device;
@@ -1724,10 +1804,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst);
break;
case GEN_PASS:
- // The SPDRP_ADDRESS for USB devices is the device port number on the hub
port_nr = 0;
- if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS,
- NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr)))
+ if (!get_dev_port_number(*dev_info, &dev_info_data, &port_nr))
usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0));
r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst);
if (r == LIBUSB_SUCCESS) {
@@ -1747,10 +1825,10 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
default: // HID_PASS and later
if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) {
if (parent_priv->apib->id == USB_API_HID) {
- usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data);
+ usbi_dbg(ctx, "setting HID interface for [%lX]:", parent_dev->session_data);
r = set_hid_interface(ctx, parent_dev, dev_interface_path);
} else {
- usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data);
+ usbi_dbg(ctx, "setting composite interface for [%lX]:", parent_dev->session_data);
r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id, api, sub_api);
}
switch (r) {
@@ -2001,8 +2079,6 @@ static int winusb_submit_transfer(struct usbi_transfer *itransfer)
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
- return LIBUSB_ERROR_NOT_SUPPORTED;
transfer_fn = priv->apib->submit_bulk_transfer;
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
@@ -2263,10 +2339,10 @@ cleanup_winusb:
KLIB_VERSION LibK_Version;
pLibK_GetVersion(&LibK_Version);
- usbi_dbg("libusbK DLL found, version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
+ usbi_dbg(ctx, "libusbK DLL found, version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
LibK_Version.Micro, LibK_Version.Nano);
} else {
- usbi_dbg("libusbK DLL found, version unknown");
+ usbi_dbg(ctx, "libusbK DLL found, version unknown");
}
pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(hlibusbK, "LibK_GetProcAddress");
@@ -2352,7 +2428,7 @@ static void winusbx_exit(void)
static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
{
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
HANDLE file_handle;
int i;
@@ -2362,7 +2438,7 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
for (i = 0; i < USB_MAXINTERFACES; i++) {
if ((priv->usb_interface[i].path != NULL)
&& (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) {
- file_handle = windows_open(dev_handle->dev, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
+ file_handle = windows_open(dev_handle, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
if (file_handle == INVALID_HANDLE_VALUE) {
usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
switch (GetLastError()) {
@@ -2384,7 +2460,7 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE handle;
int i;
@@ -2429,7 +2505,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
UCHAR policy;
@@ -2445,35 +2521,36 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle
endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i];
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout))
- usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
if ((i == -1) || (sub_api == SUB_API_LIBUSB0))
continue; // Other policies don't apply to control endpoint or libusb0
policy = false;
+ handle_priv->interface_handle[iface].zlp[endpoint_address] = WINUSB_ZLP_UNSET;
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy))
- usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy))
- usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
policy = true;
/* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy))
- usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
AUTO_CLEAR_STALL, sizeof(UCHAR), &policy))
- usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
if (sub_api == SUB_API_LIBUSBK) {
if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
ISO_ALWAYS_START_ASAP, sizeof(UCHAR), &policy))
- usbi_dbg("failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address);
+ usbi_dbg(HANDLE_CTX(dev_handle), "failed to enable ISO_ALWAYS_START_ASAP for endpoint %02X", endpoint_address);
}
}
@@ -2483,7 +2560,7 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle
static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
{
struct libusb_context *ctx = HANDLE_CTX(dev_handle);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
HDEVINFO dev_info;
@@ -2534,7 +2611,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
*dev_interface_path_guid_start = '\0';
if (strncmp(dev_interface_path, priv->usb_interface[iface].path, strlen(dev_interface_path)) == 0) {
- file_handle = windows_open(dev_handle->dev, filter_path, GENERIC_READ | GENERIC_WRITE);
+ file_handle = windows_open(dev_handle, filter_path, GENERIC_READ | GENERIC_WRITE);
if (file_handle != INVALID_HANDLE_VALUE) {
if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
// Replace the existing file handle with the working one
@@ -2591,7 +2668,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
}
handle_priv->interface_handle[iface].dev_handle = handle_priv->interface_handle[0].dev_handle;
}
- usbi_dbg("claimed interface %u", iface);
+ usbi_dbg(ctx, "claimed interface %u", iface);
handle_priv->active_interface = iface;
return LIBUSB_SUCCESS;
@@ -2599,7 +2676,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE winusb_handle;
@@ -2620,12 +2697,12 @@ static int winusbx_release_interface(int sub_api, struct libusb_device_handle *d
*/
static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
int i;
if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
- usbi_dbg("unsupported API ID");
+ usbi_dbg(HANDLE_CTX(dev_handle), "unsupported API ID");
return -1;
}
@@ -2644,14 +2721,14 @@ static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_
*/
static int check_valid_interface(struct libusb_device_handle *dev_handle, unsigned short interface, int api_id)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
if (interface >= USB_MAXINTERFACES)
return -1;
if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
- usbi_dbg("unsupported API ID");
+ usbi_dbg(HANDLE_CTX(dev_handle), "unsupported API ID");
return -1;
}
@@ -2691,9 +2768,9 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer;
- ULONG size;
+ ULONG size, transferred;
HANDLE winusb_handle;
OVERLAPPED *overlapped;
int current_interface;
@@ -2703,7 +2780,7 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
// Windows places upper limits on the control transfer size
- // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx
+ // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-bandwidth-allocation#maximum-transfer-size
if (size > MAX_CTRL_BUFFER_LENGTH)
return LIBUSB_ERROR_INVALID_PARAM;
@@ -2716,8 +2793,9 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("will use interface %d", current_interface);
+ usbi_dbg(ITRANSFER_CTX(itransfer), "will use interface %d", current_interface);
+ transfer_priv->interface_number = (uint8_t)current_interface;
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
overlapped = get_transfer_priv_overlapped(itransfer);
@@ -2732,22 +2810,22 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
}
windows_force_sync_completion(itransfer, 0);
} else {
- if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) {
+ if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, &transferred, overlapped)) {
if (GetLastError() != ERROR_IO_PENDING) {
usbi_warn(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
return LIBUSB_ERROR_IO;
}
+ } else {
+ windows_force_sync_completion(itransfer, transferred);
}
}
- transfer_priv->interface_number = (uint8_t)current_interface;
-
return LIBUSB_SUCCESS;
}
static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface, uint8_t altsetting)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE winusb_handle;
@@ -2803,7 +2881,7 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
HANDLE winusb_handle;
OVERLAPPED *overlapped;
@@ -2818,8 +2896,9 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+ usbi_dbg(TRANSFER_CTX(transfer), "matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+ transfer_priv->interface_number = (uint8_t)current_interface;
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
overlapped = get_transfer_priv_overlapped(itransfer);
@@ -2852,10 +2931,10 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
}
if (IS_XFERIN(transfer)) {
- usbi_dbg("reading %d iso packets", transfer->num_iso_packets);
+ usbi_dbg(TRANSFER_CTX(transfer), "reading %d iso packets", transfer->num_iso_packets);
ret = WinUSBX[sub_api].IsoReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
} else {
- usbi_dbg("writing %d iso packets", transfer->num_iso_packets);
+ usbi_dbg(TRANSFER_CTX(transfer), "writing %d iso packets", transfer->num_iso_packets);
ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
}
@@ -2864,8 +2943,6 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
return LIBUSB_ERROR_IO;
}
- transfer_priv->interface_number = (uint8_t)current_interface;
-
return LIBUSB_SUCCESS;
} else if (sub_api == SUB_API_WINUSB) {
WINUSB_PIPE_INFORMATION_EX pipe_info_ex = { 0 };
@@ -2913,7 +2990,11 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
// WinUSB only supports isoch transfers spanning a full USB frames. Later, we might be smarter about this
// and allocate a temporary buffer. However, this is harder than it seems as its destruction would depend on overlapped
// IO...
- iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
+ if (transfer->dev_handle->dev->speed >= LIBUSB_SPEED_HIGH) // Microframes (125us)
+ iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
+ else // Normal Frames (1ms)
+ iso_transfer_size_multiple = pipe_info_ex.MaximumBytesPerInterval / interval;
+
if (transfer->length % iso_transfer_size_multiple != 0) {
usbi_err(TRANSFER_CTX(transfer), "length of isoch buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
return LIBUSB_ERROR_INVALID_PARAM;
@@ -2980,8 +3061,6 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
transfer_priv->isoch_buffer_handle = buffer_handle;
- transfer_priv->interface_number = (uint8_t)current_interface;
-
return LIBUSB_SUCCESS;
} else {
PRINT_UNSUPPORTED_API(winusbx_submit_iso_transfer);
@@ -2993,7 +3072,7 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
HANDLE winusb_handle;
OVERLAPPED *overlapped;
@@ -3008,17 +3087,35 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+ usbi_dbg(TRANSFER_CTX(transfer), "matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+ transfer_priv->interface_number = (uint8_t)current_interface;
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
overlapped = get_transfer_priv_overlapped(itransfer);
if (IS_XFERIN(transfer)) {
- usbi_dbg("reading %d bytes", transfer->length);
+ usbi_dbg(TRANSFER_CTX(transfer), "reading %d bytes", transfer->length);
ret = WinUSBX[sub_api].ReadPipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
} else {
- usbi_dbg("writing %d bytes", transfer->length);
+ // Set SHORT_PACKET_TERMINATE if ZLP requested.
+ // Changing this can be a problem with packets in flight, so only allow on the first transfer.
+ UCHAR policy = (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) != 0;
+ uint8_t* current_zlp = &handle_priv->interface_handle[current_interface].zlp[transfer->endpoint];
+ if (*current_zlp == WINUSB_ZLP_UNSET) {
+ if (policy &&
+ !WinUSBX[sub_api].SetPipePolicy(winusb_handle, transfer->endpoint,
+ SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) {
+ usbi_err(TRANSFER_CTX(transfer), "failed to set SHORT_PACKET_TERMINATE for endpoint %02X", transfer->endpoint);
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ }
+ *current_zlp = policy ? WINUSB_ZLP_ON : WINUSB_ZLP_OFF;
+ } else if (policy != (*current_zlp == WINUSB_ZLP_ON)) {
+ usbi_err(TRANSFER_CTX(transfer), "cannot change ZERO_PACKET for endpoint %02X on Windows", transfer->endpoint);
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ }
+
+ usbi_dbg(TRANSFER_CTX(transfer), "writing %d bytes", transfer->length);
ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
}
@@ -3027,14 +3124,12 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
return LIBUSB_ERROR_IO;
}
- transfer_priv->interface_number = (uint8_t)current_interface;
-
return LIBUSB_SUCCESS;
}
static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE winusb_handle;
int current_interface;
@@ -3047,7 +3142,7 @@ static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_hand
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
+ usbi_dbg(HANDLE_CTX(dev_handle), "matched endpoint %02X with interface %d", endpoint, current_interface);
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
@@ -3061,7 +3156,7 @@ static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_hand
static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
int current_interface = transfer_priv->interface_number;
@@ -3069,7 +3164,7 @@ static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
CHECK_WINUSBX_AVAILABLE(sub_api);
- usbi_dbg("will use interface %d", current_interface);
+ usbi_dbg(TRANSFER_CTX(transfer), "will use interface %d", current_interface);
handle = handle_priv->interface_handle[current_interface].api_handle;
if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) {
@@ -3091,7 +3186,7 @@ static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE winusb_handle;
int i, j;
@@ -3103,7 +3198,7 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
winusb_handle = handle_priv->interface_handle[i].api_handle;
if (HANDLE_VALID(winusb_handle)) {
for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
- usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
+ usbi_dbg(HANDLE_CTX(dev_handle), "resetting ep %02X", priv->usb_interface[i].endpoint[j]);
if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
usbi_err(HANDLE_CTX(dev_handle), "AbortPipe (pipe address %02X) failed: %s",
priv->usb_interface[i].endpoint[j], windows_error_str(0));
@@ -3138,12 +3233,25 @@ static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struc
int i;
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
+ struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
+
+ if (sub_api == SUB_API_NOTSET)
+ sub_api = priv->sub_api;
+ if (WinUSBX[sub_api].hDll == NULL)
+ return LIBUSB_TRANSFER_ERROR;
+
// for isochronous, need to copy the individual iso packet actual_lengths and statuses
if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
// iso only supported on libusbk-based backends for now
PKISO_CONTEXT iso_context = transfer_priv->iso_context;
for (i = 0; i < transfer->num_iso_packets; i++) {
- transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length;
+ if (IS_XFERIN(transfer)) {
+ transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length;
+ } else {
+ // On Windows the usbd Length field is not used for OUT transfers.
+ // Copy the requested value back for consistency with other platforms.
+ transfer->iso_packet_desc[i].actual_length = transfer->iso_packet_desc[i].length;
+ }
// TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status
//transfer->iso_packet_desc[i].status = transfer_priv->iso_context->IsoPackets[i].status;
}
@@ -3164,6 +3272,9 @@ static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struc
} else {
for (i = 0; i < transfer->num_iso_packets; i++) {
transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_COMPLETED;
+ // On Windows the usbd Length field is not used for OUT transfers.
+ // Copy the requested value back for consistency with other platforms.
+ transfer->iso_packet_desc[i].actual_length = transfer->iso_packet_desc[i].length;
}
}
} else {
@@ -3439,28 +3550,28 @@ static int _hid_get_descriptor(struct libusb_device *dev, HANDLE hid_handle, int
switch (type) {
case LIBUSB_DT_DEVICE:
- usbi_dbg("LIBUSB_DT_DEVICE");
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_DEVICE");
return _hid_get_device_descriptor(priv->hid, data, size);
case LIBUSB_DT_CONFIG:
- usbi_dbg("LIBUSB_DT_CONFIG");
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_CONFIG");
if (!_index)
return _hid_get_config_descriptor(priv->hid, data, size);
return LIBUSB_ERROR_INVALID_PARAM;
case LIBUSB_DT_STRING:
- usbi_dbg("LIBUSB_DT_STRING");
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_STRING");
return _hid_get_string_descriptor(priv->hid, _index, data, size, hid_handle);
case LIBUSB_DT_HID:
- usbi_dbg("LIBUSB_DT_HID");
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_HID");
if (!_index)
return _hid_get_hid_descriptor(priv->hid, data, size);
return LIBUSB_ERROR_INVALID_PARAM;
case LIBUSB_DT_REPORT:
- usbi_dbg("LIBUSB_DT_REPORT");
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_REPORT");
if (!_index)
return _hid_get_report_descriptor(priv->hid, data, size);
return LIBUSB_ERROR_INVALID_PARAM;
case LIBUSB_DT_PHYSICAL:
- usbi_dbg("LIBUSB_DT_PHYSICAL");
+ usbi_dbg(DEVICE_CTX(dev), "LIBUSB_DT_PHYSICAL");
if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size))
return LIBUSB_COMPLETED;
return LIBUSB_ERROR_OTHER;
@@ -3502,7 +3613,7 @@ static int _hid_get_report(struct libusb_device *dev, HANDLE hid_handle, int id,
return LIBUSB_ERROR_NO_MEM;
buf[0] = (uint8_t)id; // Must be set always
- usbi_dbg("report ID: 0x%02X", buf[0]);
+ usbi_dbg(DEVICE_CTX(dev), "report ID: 0x%02X", buf[0]);
// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1,
@@ -3550,7 +3661,7 @@ static int _hid_set_report(struct libusb_device *dev, HANDLE hid_handle, int id,
return LIBUSB_ERROR_INVALID_PARAM;
}
- usbi_dbg("report ID: 0x%02X", id);
+ usbi_dbg(DEVICE_CTX(dev), "report ID: 0x%02X", id);
// When report IDs are not used (i.e. when id == 0), we must add
// a null report ID. Otherwise, we just use original data buffer
if (id == 0)
@@ -3644,7 +3755,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
{
struct libusb_device *dev = dev_handle->dev;
struct winusb_device_priv *priv = usbi_get_device_priv(dev);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
HIDD_ATTRIBUTES hid_attributes;
PHIDP_PREPARSED_DATA preparsed_data = NULL;
HIDP_CAPS capabilities;
@@ -3669,7 +3780,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
for (i = 0; i < USB_MAXINTERFACES; i++) {
if ((priv->usb_interface[i].path != NULL)
&& (priv->usb_interface[i].apib->id == USB_API_HID)) {
- hid_handle = windows_open(dev, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
+ hid_handle = windows_open(dev_handle, priv->usb_interface[i].path, GENERIC_READ | GENERIC_WRITE);
/*
* http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
* "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
@@ -3679,7 +3790,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
*/
if (hid_handle == INVALID_HANDLE_VALUE) {
usbi_warn(HANDLE_CTX(dev_handle), "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
- hid_handle = windows_open(dev, priv->usb_interface[i].path, 0);
+ hid_handle = windows_open(dev_handle, priv->usb_interface[i].path, 0);
if (hid_handle == INVALID_HANDLE_VALUE) {
usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
switch (GetLastError()) {
@@ -3709,7 +3820,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
// 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);
+ usbi_dbg(HANDLE_CTX(dev_handle), "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) {
@@ -3726,7 +3837,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
size[1] = capabilities.NumberOutputValueCaps;
size[2] = capabilities.NumberFeatureValueCaps;
for (j = HidP_Input; j <= HidP_Feature; j++) {
- usbi_dbg("%lu HID %s report value(s) found", ULONG_CAST(size[j]), type[j]);
+ usbi_dbg(HANDLE_CTX(dev_handle), "%lu HID %s report value(s) found", ULONG_CAST(size[j]), type[j]);
priv->hid->uses_report_ids[j] = false;
if (size[j] > 0) {
value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS));
@@ -3736,7 +3847,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
nb_ids[0] = 0;
nb_ids[1] = 0;
for (i = 0; i < (int)size[j]; i++) {
- usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID);
+ usbi_dbg(HANDLE_CTX(dev_handle), " Report ID: 0x%02X", value_caps[i].ReportID);
if (value_caps[i].ReportID != 0)
nb_ids[1]++;
else
@@ -3773,7 +3884,10 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
priv->hid->string_index[1] = dev->device_descriptor.iProduct;
if (priv->hid->string_index[1] != 0)
- HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1]));
+ // Using HidD_GetIndexedString() instead of HidD_GetProductString(), as the latter would otherwise return the name
+ // of the interface instead of the iProduct string whenever the iInterface member of the USB_INTERFACE_DESCRIPTOR
+ // structure for the interface is nonzero (see Remarks section in the documentation of the HID API routines)
+ HidD_GetIndexedString(hid_handle, priv->hid->string_index[1], priv->hid->string[1], sizeof(priv->hid->string[1]));
else
priv->hid->string[1][0] = 0;
@@ -3793,7 +3907,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
{
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
HANDLE file_handle;
int i;
@@ -3813,7 +3927,7 @@ static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
UNUSED(sub_api);
@@ -3829,7 +3943,7 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han
handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED;
- usbi_dbg("claimed interface %u", iface);
+ usbi_dbg(HANDLE_CTX(dev_handle), "claimed interface %u", iface);
handle_priv->active_interface = iface;
return LIBUSB_SUCCESS;
@@ -3837,7 +3951,7 @@ static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_han
static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, uint8_t iface)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
UNUSED(sub_api);
@@ -3874,7 +3988,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct libusb_device_handle *dev_handle = transfer->dev_handle;
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
HANDLE hid_handle;
@@ -3900,8 +4014,9 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("will use interface %d", current_interface);
+ usbi_dbg(ITRANSFER_CTX(itransfer), "will use interface %d", current_interface);
+ transfer_priv->interface_number = (uint8_t)current_interface;
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
set_transfer_priv_handle(itransfer, hid_handle);
overlapped = get_transfer_priv_overlapped(itransfer);
@@ -3963,8 +4078,6 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
r = LIBUSB_SUCCESS;
}
- transfer_priv->interface_number = (uint8_t)current_interface;
-
return LIBUSB_SUCCESS;
}
@@ -3972,7 +4085,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
HANDLE hid_handle;
OVERLAPPED *overlapped;
@@ -3983,6 +4096,9 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
UNUSED(sub_api);
CHECK_HID_AVAILABLE;
+ if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+
transfer_priv->hid_dest = NULL;
safe_free(transfer_priv->hid_buffer);
@@ -3992,8 +4108,9 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+ usbi_dbg(TRANSFER_CTX(transfer), "matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+ transfer_priv->interface_number = (uint8_t)current_interface;
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
set_transfer_priv_handle(itransfer, hid_handle);
overlapped = get_transfer_priv_overlapped(itransfer);
@@ -4015,7 +4132,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
if (direction_in) {
transfer_priv->hid_dest = transfer->buffer;
- usbi_dbg("reading %d bytes (report ID: 0x00)", length);
+ usbi_dbg(TRANSFER_CTX(transfer), "reading %d bytes (report ID: 0x00)", length);
ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, NULL, overlapped);
} else {
if (!priv->hid->uses_report_ids[1])
@@ -4024,7 +4141,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
// We could actually do without the calloc and memcpy in this case
memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
- usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
+ usbi_dbg(TRANSFER_CTX(transfer), "writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, NULL, overlapped);
}
@@ -4034,14 +4151,12 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
return LIBUSB_ERROR_IO;
}
- transfer_priv->interface_number = (uint8_t)current_interface;
-
return LIBUSB_SUCCESS;
}
static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
HANDLE hid_handle;
int current_interface;
@@ -4060,7 +4175,7 @@ static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle
static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
HANDLE hid_handle;
int current_interface;
@@ -4074,7 +4189,7 @@ static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle,
return LIBUSB_ERROR_NOT_FOUND;
}
- usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
+ usbi_dbg(HANDLE_CTX(dev_handle), "matched endpoint %02X with interface %d", endpoint, current_interface);
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
// No endpoint selection with Microsoft's implementation, so we try to flush the
@@ -4109,8 +4224,6 @@ static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct us
}
if (transfer_priv->hid_buffer[0] == 0) {
- // Discard the 1 byte report ID prefix
- length--;
memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, length);
} else {
memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, length);
@@ -4171,7 +4284,7 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
// open HID devices with a U2F usage unless running as administrator. We ignore this
// failure and proceed without the HID device opened.
if (r == LIBUSB_ERROR_ACCESS) {
- usbi_dbg("ignoring access denied error while opening HID interface of composite device");
+ usbi_dbg(HANDLE_CTX(dev_handle), "ignoring access denied error while opening HID interface of composite device");
r = LIBUSB_SUCCESS;
}
}
@@ -4280,7 +4393,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
// Try and target a specific interface if the control setup indicates such
if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
- usbi_dbg("attempting control transfer targeted to interface %d", iface);
+ usbi_dbg(TRANSFER_CTX(transfer), "attempting control transfer targeted to interface %d", iface);
if ((priv->usb_interface[iface].path != NULL)
&& (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
@@ -4296,10 +4409,10 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
if ((priv->usb_interface[iface].path != NULL)
&& (priv->usb_interface[iface].apib->submit_control_transfer != NULL)) {
if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
- usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
+ usbi_dbg(TRANSFER_CTX(transfer), "trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
continue;
}
- usbi_dbg("using interface %d", iface);
+ usbi_dbg(TRANSFER_CTX(transfer), "using interface %d", iface);
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
// If not supported on this API, it may be supported on another, so don't give up yet!!
if (r == LIBUSB_ERROR_NOT_SUPPORTED)
@@ -4316,7 +4429,7 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
int current_interface;
@@ -4337,7 +4450,7 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr
static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(transfer->dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(transfer->dev_handle->dev);
int current_interface;
@@ -4357,7 +4470,7 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra
static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct winusb_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
+ struct winusb_device_handle_priv *handle_priv = get_winusb_device_handle_priv(dev_handle);
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
int current_interface;