Home | History | Annotate | Download | only in os
      1 /*
      2  * Windows backend for libusb 1.0
      3  * Copyright (C) 2009-2010 Pete Batard <pbatard (at) gmail.com>
      4  * With contributions from Michael Plante, Orin Eman et al.
      5  * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
      6  * Major code testing contribution by Xiaofan Chen
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Lesser General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2.1 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Lesser General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Lesser General Public
     19  * License along with this library; if not, write to the Free Software
     20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     21  */
     22 
     23 #pragma once
     24 
     25 #if defined(_MSC_VER)
     26 // disable /W4 MSVC warnings that are benign
     27 #pragma warning(disable:4127) // conditional expression is constant
     28 #pragma warning(disable:4100) // unreferenced formal parameter
     29 #pragma warning(disable:4214) // bit field types other than int
     30 #pragma warning(disable:4201) // nameless struct/union
     31 #endif
     32 
     33 // Windows API default is uppercase - ugh!
     34 #if !defined(bool)
     35 #define bool BOOL
     36 #endif
     37 #if !defined(true)
     38 #define true TRUE
     39 #endif
     40 #if !defined(false)
     41 #define false FALSE
     42 #endif
     43 
     44 // Missing from MSVC6 setupapi.h
     45 #if !defined(SPDRP_ADDRESS)
     46 #define SPDRP_ADDRESS	28
     47 #endif
     48 #if !defined(SPDRP_INSTALL_STATE)
     49 #define SPDRP_INSTALL_STATE	34
     50 #endif
     51 
     52 #if defined(__CYGWIN__ )
     53 // cygwin produces a warning unless these prototypes are defined
     54 extern int _snprintf(char *buffer, size_t count, const char *format, ...);
     55 extern char *_strdup(const char *strSource);
     56 // _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
     57 #define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, f)
     58 #endif
     59 #define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
     60 #define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
     61 #define safe_min(a, b) min((size_t)(a), (size_t)(b))
     62 #define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
     63 	((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
     64 #define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
     65 #define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
     66 #define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
     67 #define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
     68 #define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
     69 #define safe_strlen(str) ((str==NULL)?0:strlen(str))
     70 #define safe_sprintf _snprintf
     71 #define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0)
     72 #define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL)
     73 static inline void upperize(char* str) {
     74 	size_t i;
     75 	if (str == NULL) return;
     76 	for (i=0; i<safe_strlen(str); i++)
     77 		str[i] = (char)toupper((int)str[i]);
     78 }
     79 
     80 #define MAX_CTRL_BUFFER_LENGTH      4096
     81 #define MAX_USB_DEVICES             256
     82 #define MAX_USB_STRING_LENGTH       128
     83 #define MAX_GUID_STRING_LENGTH      40
     84 #define MAX_PATH_LENGTH             128
     85 #define MAX_KEY_LENGTH              256
     86 #define MAX_TIMER_SEMAPHORES        128
     87 #define TIMER_REQUEST_RETRY_MS      100
     88 #define ERR_BUFFER_SIZE             256
     89 #define LIST_SEPARATOR              ';'
     90 #define HTAB_SIZE                   1021
     91 
     92 // http://msdn.microsoft.com/en-us/library/ff545978.aspx
     93 // http://msdn.microsoft.com/en-us/library/ff545972.aspx
     94 // http://msdn.microsoft.com/en-us/library/ff545982.aspx
     95 #if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER)
     96 const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} };
     97 #endif
     98 #if !defined(GUID_DEVINTERFACE_USB_DEVICE)
     99 const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
    100 #endif
    101 #if !defined(GUID_DEVINTERFACE_USB_HUB)
    102 const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} };
    103 #endif
    104 const GUID GUID_NULL = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
    105 
    106 
    107 /*
    108  * Multiple USB API backend support
    109  */
    110 #define USB_API_UNSUPPORTED 0
    111 #define USB_API_HUB         1
    112 #define USB_API_COMPOSITE   2
    113 #define USB_API_WINUSB      3
    114 #define USB_API_MAX         4
    115 
    116 #define CLASS_GUID_UNSUPPORTED      GUID_NULL
    117 const GUID CLASS_GUID_LIBUSB_WINUSB = { 0x78A1C341, 0x4539, 0x11D3, {0xB8, 0x8D, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71} };
    118 const GUID CLASS_GUID_COMPOSITE     = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
    119 
    120 struct windows_usb_api_backend {
    121 	const uint8_t id;
    122 	const char* designation;
    123 	const GUID *class_guid;  // The Class GUID (for fallback in case the driver name cannot be read)
    124 	const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
    125 	const uint8_t nb_driver_names;
    126 	int (*init)(struct libusb_context *ctx);
    127 	int (*exit)(void);
    128 	int (*open)(struct libusb_device_handle *dev_handle);
    129 	void (*close)(struct libusb_device_handle *dev_handle);
    130 	int (*claim_interface)(struct libusb_device_handle *dev_handle, int iface);
    131 	int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, int iface, int altsetting);
    132 	int (*release_interface)(struct libusb_device_handle *dev_handle, int iface);
    133 	int (*clear_halt)(struct libusb_device_handle *dev_handle, unsigned char endpoint);
    134 	int (*reset_device)(struct libusb_device_handle *dev_handle);
    135 	int (*submit_bulk_transfer)(struct usbi_transfer *itransfer);
    136 	int (*submit_iso_transfer)(struct usbi_transfer *itransfer);
    137 	int (*submit_control_transfer)(struct usbi_transfer *itransfer);
    138 	int (*abort_control)(struct usbi_transfer *itransfer);
    139 	int (*abort_transfers)(struct usbi_transfer *itransfer);
    140 	int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size);
    141 };
    142 
    143 extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
    144 
    145 #define PRINT_UNSUPPORTED_API(fname)              \
    146 	usbi_dbg("unsupported API call for '"         \
    147 		#fname "' (unrecognized device driver)"); \
    148 	return LIBUSB_ERROR_NOT_SUPPORTED;
    149 
    150 /*
    151  * private structures definition
    152  * with inline pseudo constructors/destructors
    153  */
    154 typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
    155 struct windows_device_priv {
    156 	uint8_t depth;						// distance to HCD
    157 	uint8_t port;						// port number on the hub
    158 	struct libusb_device *parent_dev;	// access to parent is required for usermode ops
    159 	char *path;							// device interface path
    160 	struct windows_usb_api_backend const *apib;
    161 	struct {
    162 		char *path;						// each interface needs a device interface path,
    163 		struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support),
    164 		int8_t nb_endpoints;			// and a set of endpoint addresses (USB_MAXENDPOINTS)
    165 		uint8_t *endpoint;
    166 	} usb_interface[USB_MAXINTERFACES];
    167 	uint8_t composite_api_flags;		// composite devices require additional data
    168 	uint8_t active_config;
    169 	USB_DEVICE_DESCRIPTOR dev_descriptor;
    170 	unsigned char **config_descriptor;	// list of pointers to the cached config descriptors
    171 };
    172 
    173 static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) {
    174 	return (struct windows_device_priv *)dev->os_priv;
    175 }
    176 
    177 static inline void windows_device_priv_init(libusb_device* dev) {
    178 	struct windows_device_priv* p = _device_priv(dev);
    179 	int i;
    180 	p->depth = 0;
    181 	p->port = 0;
    182 	p->parent_dev = NULL;
    183 	p->path = NULL;
    184 	p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
    185 	p->composite_api_flags = 0;
    186 	p->active_config = 0;
    187 	p->config_descriptor = NULL;
    188 	memset(&(p->dev_descriptor), 0, sizeof(USB_DEVICE_DESCRIPTOR));
    189 	for (i=0; i<USB_MAXINTERFACES; i++) {
    190 		p->usb_interface[i].path = NULL;
    191 		p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
    192 		p->usb_interface[i].nb_endpoints = 0;
    193 		p->usb_interface[i].endpoint = NULL;
    194 	}
    195 }
    196 
    197 static inline void windows_device_priv_release(libusb_device* dev) {
    198 	struct windows_device_priv* p = _device_priv(dev);
    199 	int i;
    200 	safe_free(p->path);
    201 	if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
    202 		for (i=0; i < dev->num_configurations; i++)
    203 			safe_free(p->config_descriptor[i]);
    204 	}
    205 	safe_free(p->config_descriptor);
    206 	for (i=0; i<USB_MAXINTERFACES; i++) {
    207 		safe_free(p->usb_interface[i].path);
    208 		safe_free(p->usb_interface[i].endpoint);
    209 	}
    210 }
    211 
    212 struct interface_handle_t {
    213 	HANDLE dev_handle; // WinUSB needs an extra handle for the file
    214 	HANDLE api_handle; // used by the API to communicate with the device
    215 };
    216 
    217 struct windows_device_handle_priv {
    218 	int active_interface;
    219 	struct interface_handle_t interface_handle[USB_MAXINTERFACES];
    220 	int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
    221 };
    222 
    223 static inline struct windows_device_handle_priv *_device_handle_priv(
    224 	struct libusb_device_handle *handle)
    225 {
    226 	return (struct windows_device_handle_priv *) handle->os_priv;
    227 }
    228 
    229 // used for async polling functions
    230 struct windows_transfer_priv {
    231 	struct winfd pollable_fd;
    232 	uint8_t interface_number;
    233 };
    234 
    235 // used to match a device driver (including filter drivers) against a supported API
    236 struct driver_lookup {
    237 	char list[MAX_KEY_LENGTH+1];// REG_MULTI_SZ list of services (driver) names
    238 	const DWORD reg_prop;		// SPDRP registry key to use to retreive list
    239 	const char* designation;	// internal designation (for debug output)
    240 };
    241 
    242 /*
    243  * API macros - from libusb-win32 1.x
    244  */
    245 #define DLL_DECLARE_PREFIXNAME(api, ret, prefixname, name, args)    \
    246 	typedef ret (api * __dll_##name##_t)args;                 \
    247 	static __dll_##name##_t prefixname = NULL
    248 
    249 #define DLL_LOAD_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
    250 	do {                                                      \
    251 		HMODULE h = GetModuleHandleA(#dll);                   \
    252 	if (!h)                                                   \
    253 		h = LoadLibraryA(#dll);                               \
    254 	if (!h) {                                                 \
    255 		if (ret_on_failure) { return LIBUSB_ERROR_NOT_FOUND; }\
    256 		else { break; }                                       \
    257 	}                                                         \
    258 	prefixname = (__dll_##name##_t)GetProcAddress(h, #name);       \
    259 	if (prefixname) break;                                         \
    260 	prefixname = (__dll_##name##_t)GetProcAddress(h, #name "A");   \
    261 	if (prefixname) break;                                         \
    262 	prefixname = (__dll_##name##_t)GetProcAddress(h, #name "W");   \
    263 	if (prefixname) break;                                         \
    264 	if(ret_on_failure)                                        \
    265 		return LIBUSB_ERROR_NOT_FOUND;                        \
    266 	} while(0)
    267 
    268 #define DLL_DECLARE(api, ret, name, args)   DLL_DECLARE_PREFIXNAME(api, ret, name, name, args)
    269 #define DLL_LOAD(dll, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, name, name, ret_on_failure)
    270 #define DLL_DECLARE_PREFIXED(api, ret, prefix, name, args)   DLL_DECLARE_PREFIXNAME(api, ret, prefix##name, name, args)
    271 #define DLL_LOAD_PREFIXED(dll, prefix, name, ret_on_failure) DLL_LOAD_PREFIXNAME(dll, prefix##name, name, ret_on_failure)
    272 
    273 /* OLE32 dependency */
    274 DLL_DECLARE_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID));
    275 
    276 /* SetupAPI dependencies */
    277 DLL_DECLARE_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD));
    278 DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA));
    279 DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA,
    280 			const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA));
    281 DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA,
    282 			PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA));
    283 DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO));
    284 DLL_DECLARE_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM));
    285 DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO,
    286 			PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD));
    287 DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD));
    288 DLL_DECLARE_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY));
    289 
    290 /*
    291  * Windows DDK API definitions. Most of it copied from MinGW's includes
    292  */
    293 typedef DWORD DEVNODE, DEVINST;
    294 typedef DEVNODE *PDEVNODE, *PDEVINST;
    295 typedef DWORD RETURN_TYPE;
    296 typedef RETURN_TYPE CONFIGRET;
    297 
    298 #define CR_SUCCESS                              0x00000000
    299 #define CR_NO_SUCH_DEVNODE                      0x0000000D
    300 
    301 #define USB_DEVICE_DESCRIPTOR_TYPE              LIBUSB_DT_DEVICE
    302 #define USB_CONFIGURATION_DESCRIPTOR_TYPE       LIBUSB_DT_CONFIG
    303 #define USB_STRING_DESCRIPTOR_TYPE              LIBUSB_DT_STRING
    304 #define USB_INTERFACE_DESCRIPTOR_TYPE           LIBUSB_DT_INTERFACE
    305 #define USB_ENDPOINT_DESCRIPTOR_TYPE            LIBUSB_DT_ENDPOINT
    306 
    307 #define USB_REQUEST_GET_STATUS                  LIBUSB_REQUEST_GET_STATUS
    308 #define USB_REQUEST_CLEAR_FEATURE               LIBUSB_REQUEST_CLEAR_FEATURE
    309 #define USB_REQUEST_SET_FEATURE                 LIBUSB_REQUEST_SET_FEATURE
    310 #define USB_REQUEST_SET_ADDRESS                 LIBUSB_REQUEST_SET_ADDRESS
    311 #define USB_REQUEST_GET_DESCRIPTOR              LIBUSB_REQUEST_GET_DESCRIPTOR
    312 #define USB_REQUEST_SET_DESCRIPTOR              LIBUSB_REQUEST_SET_DESCRIPTOR
    313 #define USB_REQUEST_GET_CONFIGURATION           LIBUSB_REQUEST_GET_CONFIGURATION
    314 #define USB_REQUEST_SET_CONFIGURATION           LIBUSB_REQUEST_SET_CONFIGURATION
    315 #define USB_REQUEST_GET_INTERFACE               LIBUSB_REQUEST_GET_INTERFACE
    316 #define USB_REQUEST_SET_INTERFACE               LIBUSB_REQUEST_SET_INTERFACE
    317 #define USB_REQUEST_SYNC_FRAME                  LIBUSB_REQUEST_SYNCH_FRAME
    318 
    319 #define USB_GET_NODE_INFORMATION                258
    320 #define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
    321 #define USB_GET_NODE_CONNECTION_NAME            261
    322 #define USB_GET_HUB_CAPABILITIES                271
    323 #if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX)
    324 #define USB_GET_NODE_CONNECTION_INFORMATION_EX  274
    325 #endif
    326 #if !defined(USB_GET_HUB_CAPABILITIES_EX)
    327 #define USB_GET_HUB_CAPABILITIES_EX             276
    328 #endif
    329 
    330 #ifndef METHOD_BUFFERED
    331 #define METHOD_BUFFERED                         0
    332 #endif
    333 #ifndef FILE_ANY_ACCESS
    334 #define FILE_ANY_ACCESS                         0x00000000
    335 #endif
    336 #ifndef FILE_DEVICE_UNKNOWN
    337 #define FILE_DEVICE_UNKNOWN                     0x00000022
    338 #endif
    339 #ifndef FILE_DEVICE_USB
    340 #define FILE_DEVICE_USB                         FILE_DEVICE_UNKNOWN
    341 #endif
    342 
    343 #ifndef CTL_CODE
    344 #define CTL_CODE(DeviceType, Function, Method, Access)( \
    345   ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
    346 #endif
    347 
    348 typedef enum USB_CONNECTION_STATUS {
    349 	NoDeviceConnected,
    350 	DeviceConnected,
    351 	DeviceFailedEnumeration,
    352 	DeviceGeneralFailure,
    353 	DeviceCausedOvercurrent,
    354 	DeviceNotEnoughPower,
    355 	DeviceNotEnoughBandwidth,
    356 	DeviceHubNestedTooDeeply,
    357 	DeviceInLegacyHub
    358 } USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;
    359 
    360 typedef enum USB_HUB_NODE {
    361 	UsbHub,
    362 	UsbMIParent
    363 } USB_HUB_NODE;
    364 
    365 /* Cfgmgr32.dll interface */
    366 DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
    367 DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
    368 DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
    369 DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG));
    370 
    371 #define IOCTL_USB_GET_HUB_CAPABILITIES_EX \
    372   CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
    373 
    374 #define IOCTL_USB_GET_HUB_CAPABILITIES \
    375   CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS)
    376 
    377 #define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \
    378   CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS)
    379 
    380 #define IOCTL_USB_GET_ROOT_HUB_NAME \
    381   CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
    382 
    383 #define IOCTL_USB_GET_NODE_INFORMATION \
    384   CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
    385 
    386 #define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
    387   CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
    388 
    389 #define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \
    390   CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS)
    391 
    392 #define IOCTL_USB_GET_NODE_CONNECTION_NAME \
    393   CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
    394 
    395 // Most of the structures below need to be packed
    396 #pragma pack(push, 1)
    397 
    398 typedef struct USB_INTERFACE_DESCRIPTOR {
    399   UCHAR  bLength;
    400   UCHAR  bDescriptorType;
    401   UCHAR  bInterfaceNumber;
    402   UCHAR  bAlternateSetting;
    403   UCHAR  bNumEndpoints;
    404   UCHAR  bInterfaceClass;
    405   UCHAR  bInterfaceSubClass;
    406   UCHAR  bInterfaceProtocol;
    407   UCHAR  iInterface;
    408 } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
    409 
    410 typedef struct USB_CONFIGURATION_DESCRIPTOR {
    411   UCHAR  bLength;
    412   UCHAR  bDescriptorType;
    413   USHORT wTotalLength;
    414   UCHAR  bNumInterfaces;
    415   UCHAR  bConfigurationValue;
    416   UCHAR  iConfiguration;
    417   UCHAR  bmAttributes;
    418   UCHAR  MaxPower;
    419 } USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
    420 
    421 typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT {
    422 	struct {
    423 		ULONG ConnectionIndex;
    424 		struct {
    425 			UCHAR bmRequest;
    426 			UCHAR bRequest;
    427 			USHORT wValue;
    428 			USHORT wIndex;
    429 			USHORT wLength;
    430 		} SetupPacket;
    431 	} req;
    432 	USB_CONFIGURATION_DESCRIPTOR data;
    433 } USB_CONFIGURATION_DESCRIPTOR_SHORT;
    434 
    435 typedef struct USB_ENDPOINT_DESCRIPTOR {
    436   UCHAR  bLength;
    437   UCHAR  bDescriptorType;
    438   UCHAR  bEndpointAddress;
    439   UCHAR  bmAttributes;
    440   USHORT  wMaxPacketSize;
    441   UCHAR  bInterval;
    442 } USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
    443 
    444 typedef struct USB_DESCRIPTOR_REQUEST {
    445 	ULONG  ConnectionIndex;
    446 	struct {
    447 		UCHAR  bmRequest;
    448 		UCHAR  bRequest;
    449 		USHORT  wValue;
    450 		USHORT  wIndex;
    451 		USHORT  wLength;
    452 	} SetupPacket;
    453 //	UCHAR  Data[0];
    454 } USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST;
    455 
    456 typedef struct USB_HUB_DESCRIPTOR {
    457 	UCHAR  bDescriptorLength;
    458 	UCHAR  bDescriptorType;
    459 	UCHAR  bNumberOfPorts;
    460 	USHORT  wHubCharacteristics;
    461 	UCHAR  bPowerOnToPowerGood;
    462 	UCHAR  bHubControlCurrent;
    463 	UCHAR  bRemoveAndPowerMask[64];
    464 } USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
    465 
    466 typedef struct USB_ROOT_HUB_NAME {
    467 	ULONG  ActualLength;
    468 	WCHAR  RootHubName[1];
    469 } USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;
    470 
    471 typedef struct USB_ROOT_HUB_NAME_FIXED {
    472 	ULONG ActualLength;
    473 	WCHAR RootHubName[MAX_PATH_LENGTH];
    474 } USB_ROOT_HUB_NAME_FIXED;
    475 
    476 typedef struct USB_NODE_CONNECTION_NAME {
    477 	ULONG  ConnectionIndex;
    478 	ULONG  ActualLength;
    479 	WCHAR  NodeName[1];
    480 } USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME;
    481 
    482 typedef struct USB_NODE_CONNECTION_NAME_FIXED {
    483 	ULONG ConnectionIndex;
    484 	ULONG ActualLength;
    485 	WCHAR NodeName[MAX_PATH_LENGTH];
    486 } USB_NODE_CONNECTION_NAME_FIXED;
    487 
    488 typedef struct USB_HUB_NAME_FIXED {
    489 	union {
    490 		USB_ROOT_HUB_NAME_FIXED root;
    491 		USB_NODE_CONNECTION_NAME_FIXED node;
    492 	} u;
    493 } USB_HUB_NAME_FIXED;
    494 
    495 typedef struct USB_HUB_INFORMATION {
    496 	USB_HUB_DESCRIPTOR  HubDescriptor;
    497 	BOOLEAN  HubIsBusPowered;
    498 } USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;
    499 
    500 typedef struct USB_MI_PARENT_INFORMATION {
    501   ULONG  NumberOfInterfaces;
    502 } USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION;
    503 
    504 typedef struct USB_NODE_INFORMATION {
    505 	USB_HUB_NODE  NodeType;
    506 	union {
    507 		USB_HUB_INFORMATION  HubInformation;
    508 		USB_MI_PARENT_INFORMATION  MiParentInformation;
    509 	} u;
    510 } USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;
    511 
    512 typedef struct USB_PIPE_INFO {
    513 	USB_ENDPOINT_DESCRIPTOR  EndpointDescriptor;
    514 	ULONG  ScheduleOffset;
    515 } USB_PIPE_INFO, *PUSB_PIPE_INFO;
    516 
    517 typedef struct USB_NODE_CONNECTION_INFORMATION_EX {
    518 	ULONG  ConnectionIndex;
    519 	USB_DEVICE_DESCRIPTOR  DeviceDescriptor;
    520 	UCHAR  CurrentConfigurationValue;
    521 	UCHAR  Speed;
    522 	BOOLEAN  DeviceIsHub;
    523 	USHORT  DeviceAddress;
    524 	ULONG  NumberOfOpenPipes;
    525 	USB_CONNECTION_STATUS  ConnectionStatus;
    526 //	USB_PIPE_INFO  PipeList[0];
    527 } USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX;
    528 
    529 typedef struct USB_HUB_CAP_FLAGS {
    530 	ULONG HubIsHighSpeedCapable:1;
    531 	ULONG HubIsHighSpeed:1;
    532 	ULONG HubIsMultiTtCapable:1;
    533 	ULONG HubIsMultiTt:1;
    534 	ULONG HubIsRoot:1;
    535 	ULONG HubIsArmedWakeOnConnect:1;
    536 	ULONG ReservedMBZ:26;
    537 } USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS;
    538 
    539 typedef struct USB_HUB_CAPABILITIES {
    540   ULONG  HubIs2xCapable : 1;
    541 } USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES;
    542 
    543 typedef struct USB_HUB_CAPABILITIES_EX {
    544 	USB_HUB_CAP_FLAGS CapabilityFlags;
    545 } USB_HUB_CAPABILITIES_EX, *PUSB_HUB_CAPABILITIES_EX;
    546 
    547 #pragma pack(pop)
    548 
    549 /* winusb.dll interface */
    550 
    551 #define SHORT_PACKET_TERMINATE  0x01
    552 #define AUTO_CLEAR_STALL        0x02
    553 #define PIPE_TRANSFER_TIMEOUT   0x03
    554 #define IGNORE_SHORT_PACKETS    0x04
    555 #define ALLOW_PARTIAL_READS     0x05
    556 #define AUTO_FLUSH              0x06
    557 #define RAW_IO                  0x07
    558 #define MAXIMUM_TRANSFER_SIZE   0x08
    559 #define AUTO_SUSPEND            0x81
    560 #define SUSPEND_DELAY           0x83
    561 #define DEVICE_SPEED            0x01
    562 #define LowSpeed                0x01
    563 #define FullSpeed               0x02
    564 #define HighSpeed               0x03
    565 
    566 typedef enum USBD_PIPE_TYPE {
    567 	UsbdPipeTypeControl,
    568 	UsbdPipeTypeIsochronous,
    569 	UsbdPipeTypeBulk,
    570 	UsbdPipeTypeInterrupt
    571 } USBD_PIPE_TYPE;
    572 
    573 typedef struct {
    574   USBD_PIPE_TYPE PipeType;
    575   UCHAR          PipeId;
    576   USHORT         MaximumPacketSize;
    577   UCHAR          Interval;
    578 } WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
    579 
    580 #pragma pack(1)
    581 typedef struct {
    582   UCHAR  request_type;
    583   UCHAR  request;
    584   USHORT value;
    585   USHORT index;
    586   USHORT length;
    587 } WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
    588 #pragma pack()
    589 
    590 typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
    591 
    592 DLL_DECLARE(WINAPI, BOOL, WinUsb_Initialize, (HANDLE, PWINUSB_INTERFACE_HANDLE));
    593 DLL_DECLARE(WINAPI, BOOL, WinUsb_Free, (WINUSB_INTERFACE_HANDLE));
    594 DLL_DECLARE(WINAPI, BOOL, WinUsb_GetAssociatedInterface, (WINUSB_INTERFACE_HANDLE, UCHAR, PWINUSB_INTERFACE_HANDLE));
    595 DLL_DECLARE(WINAPI, BOOL, WinUsb_GetDescriptor, (WINUSB_INTERFACE_HANDLE, UCHAR, UCHAR, USHORT, PUCHAR, ULONG, PULONG));
    596 DLL_DECLARE(WINAPI, BOOL, WinUsb_QueryInterfaceSettings, (WINUSB_INTERFACE_HANDLE, UCHAR, PUSB_INTERFACE_DESCRIPTOR));
    597 DLL_DECLARE(WINAPI, BOOL, WinUsb_QueryDeviceInformation, (WINUSB_INTERFACE_HANDLE, ULONG, PULONG, PVOID));
    598 DLL_DECLARE(WINAPI, BOOL, WinUsb_SetCurrentAlternateSetting, (WINUSB_INTERFACE_HANDLE, UCHAR));
    599 DLL_DECLARE(WINAPI, BOOL, WinUsb_GetCurrentAlternateSetting, (WINUSB_INTERFACE_HANDLE, PUCHAR));
    600 DLL_DECLARE(WINAPI, BOOL, WinUsb_QueryPipe, (WINUSB_INTERFACE_HANDLE, UCHAR, UCHAR, PWINUSB_PIPE_INFORMATION));
    601 DLL_DECLARE(WINAPI, BOOL, WinUsb_SetPipePolicy, (WINUSB_INTERFACE_HANDLE, UCHAR, ULONG, ULONG, PVOID));
    602 DLL_DECLARE(WINAPI, BOOL, WinUsb_GetPipePolicy, (WINUSB_INTERFACE_HANDLE, UCHAR, ULONG, PULONG, PVOID));
    603 DLL_DECLARE(WINAPI, BOOL, WinUsb_ReadPipe, (WINUSB_INTERFACE_HANDLE, UCHAR, PUCHAR, ULONG, PULONG, LPOVERLAPPED));
    604 DLL_DECLARE(WINAPI, BOOL, WinUsb_WritePipe, (WINUSB_INTERFACE_HANDLE, UCHAR, PUCHAR, ULONG, PULONG, LPOVERLAPPED));
    605 DLL_DECLARE(WINAPI, BOOL, WinUsb_ControlTransfer, (WINUSB_INTERFACE_HANDLE, WINUSB_SETUP_PACKET, PUCHAR, ULONG, PULONG, LPOVERLAPPED));
    606 DLL_DECLARE(WINAPI, BOOL, WinUsb_ResetPipe, (WINUSB_INTERFACE_HANDLE, UCHAR));
    607 DLL_DECLARE(WINAPI, BOOL, WinUsb_AbortPipe, (WINUSB_INTERFACE_HANDLE, UCHAR));
    608 DLL_DECLARE(WINAPI, BOOL, WinUsb_FlushPipe, (WINUSB_INTERFACE_HANDLE, UCHAR));
    609