2 * windows backend for libusbx 1.0
3 * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
4 * With contributions from Michael Plante, Orin Eman et al.
5 * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
6 * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
7 * Hash table functions adapted from glibc, by Ulrich Drepper et al.
8 * Major code testing contribution by Xiaofan Chen
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38 #include "poll_windows.h"
39 #include "windows_usb.h"
41 // The 2 macros below are used in conjunction with safe loops.
42 #define LOOP_CHECK(fcall) { r=fcall; if (r != LIBUSB_SUCCESS) continue; }
43 #define LOOP_BREAK(err) { r=err; continue; }
46 static int windows_get_active_config_descriptor(struct libusb_device
*dev
, unsigned char *buffer
, size_t len
, int *host_endian
);
47 static int windows_clock_gettime(int clk_id
, struct timespec
*tp
);
48 unsigned __stdcall
windows_clock_gettime_threaded(void* param
);
50 static int common_configure_endpoints(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
52 // WinUSB-like API prototypes
53 static int winusbx_init(int sub_api
, struct libusb_context
*ctx
);
54 static int winusbx_exit(int sub_api
);
55 static int winusbx_open(int sub_api
, struct libusb_device_handle
*dev_handle
);
56 static void winusbx_close(int sub_api
, struct libusb_device_handle
*dev_handle
);
57 static int winusbx_configure_endpoints(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
58 static int winusbx_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
59 static int winusbx_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
60 static int winusbx_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
61 static int winusbx_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
);
62 static int winusbx_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
63 static int winusbx_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
);
64 static int winusbx_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
);
65 static int winusbx_abort_control(int sub_api
, struct usbi_transfer
*itransfer
);
66 static int winusbx_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
);
67 static int winusbx_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
);
69 static int hid_init(int sub_api
, struct libusb_context
*ctx
);
70 static int hid_exit(int sub_api
);
71 static int hid_open(int sub_api
, struct libusb_device_handle
*dev_handle
);
72 static void hid_close(int sub_api
, struct libusb_device_handle
*dev_handle
);
73 static int hid_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
74 static int hid_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
75 static int hid_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
);
76 static int hid_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
77 static int hid_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
78 static int hid_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
);
79 static int hid_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
);
80 static int hid_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
);
81 static int hid_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
);
82 // Composite API prototypes
83 static int composite_init(int sub_api
, struct libusb_context
*ctx
);
84 static int composite_exit(int sub_api
);
85 static int composite_open(int sub_api
, struct libusb_device_handle
*dev_handle
);
86 static void composite_close(int sub_api
, struct libusb_device_handle
*dev_handle
);
87 static int composite_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
88 static int composite_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
);
89 static int composite_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
);
90 static int composite_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
91 static int composite_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
92 static int composite_submit_iso_transfer(int sub_api
, struct usbi_transfer
*itransfer
);
93 static int composite_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
);
94 static int composite_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
);
95 static int composite_abort_control(int sub_api
, struct usbi_transfer
*itransfer
);
96 static int composite_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
);
97 static int composite_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
);
101 uint64_t hires_frequency
, hires_ticks_to_ps
;
102 const uint64_t epoch_time
= UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
103 enum windows_version windows_version
= WINDOWS_UNSUPPORTED
;
105 static int concurrent_usage
= -1;
106 usbi_mutex_t autoclaim_lock
;
108 // NB: index 0 is for monotonic and 1 is for the thread exit event
109 HANDLE timer_thread
= NULL
;
110 HANDLE timer_mutex
= NULL
;
111 struct timespec timer_tp
;
112 volatile LONG request_count
[2] = {0, 1}; // last one must be > 0
113 HANDLE timer_request
[2] = { NULL
, NULL
};
114 HANDLE timer_response
= NULL
;
116 #define CHECK_WINUSBX_AVAILABLE(sub_api) do { if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; \
117 if (!WinUSBX[sub_api].initialized) return LIBUSB_ERROR_ACCESS; } while(0)
118 static struct winusb_interface WinUSBX
[SUB_API_MAX
];
119 const char* sub_api_name
[SUB_API_MAX
] = WINUSBX_DRV_NAMES
;
120 bool api_hid_available
= false;
121 #define CHECK_HID_AVAILABLE do { if (!api_hid_available) return LIBUSB_ERROR_ACCESS; } while (0)
123 static inline BOOLEAN
guid_eq(const GUID
*guid1
, const GUID
*guid2
) {
124 if ((guid1
!= NULL
) && (guid2
!= NULL
)) {
125 return (memcmp(guid1
, guid2
, sizeof(GUID
)) == 0);
130 #if defined(ENABLE_LOGGING)
131 static char* guid_to_string(const GUID
* guid
)
133 static char guid_string
[MAX_GUID_STRING_LENGTH
];
135 if (guid
== NULL
) return NULL
;
136 sprintf(guid_string
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
137 (unsigned int)guid
->Data1
, guid
->Data2
, guid
->Data3
,
138 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
139 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
145 * Converts a windows error to human readable string
146 * uses retval as errorcode, or, if 0, use GetLastError()
148 #if defined(ENABLE_LOGGING)
149 static char *windows_error_str(uint32_t retval
)
151 static char err_string
[ERR_BUFFER_SIZE
];
155 uint32_t error_code
, format_error
;
157 error_code
= retval
?retval
:GetLastError();
159 safe_sprintf(err_string
, ERR_BUFFER_SIZE
, "[%u] ", error_code
);
161 // Translate codes returned by SetupAPI. The ones we are dealing with are either
162 // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
163 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
164 switch (error_code
& 0xE0000000) {
166 error_code
= HRESULT_FROM_WIN32(error_code
); // Still leaves ERROR_SUCCESS unmodified
169 error_code
= 0x80000000 | (FACILITY_SETUPAPI
<< 16) | (error_code
& 0x0000FFFF);
175 size
= FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error_code
,
176 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), &err_string
[safe_strlen(err_string
)],
177 ERR_BUFFER_SIZE
- (DWORD
)safe_strlen(err_string
), NULL
);
179 format_error
= GetLastError();
181 safe_sprintf(err_string
, ERR_BUFFER_SIZE
,
182 "Windows error code %u (FormatMessage error code %u)", error_code
, format_error
);
184 safe_sprintf(err_string
, ERR_BUFFER_SIZE
, "Unknown error code %u", error_code
);
186 // Remove CR/LF terminators
187 for (i
=safe_strlen(err_string
)-1; (i
>=0) && ((err_string
[i
]==0x0A) || (err_string
[i
]==0x0D)); i
--) {
196 * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
197 * Return an allocated sanitized string or NULL on error.
199 static char* sanitize_path(const char* path
)
201 const char root_prefix
[] = "\\\\.\\";
202 size_t j
, size
, root_size
;
203 char* ret_path
= NULL
;
209 size
= safe_strlen(path
)+1;
210 root_size
= sizeof(root_prefix
)-1;
212 // Microsoft indiscriminatly uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
213 if (!((size
> 3) && (((path
[0] == '\\') && (path
[1] == '\\') && (path
[3] == '\\')) ||
214 ((path
[0] == '#') && (path
[1] == '#') && (path
[3] == '#'))))) {
215 add_root
= root_size
;
219 if ((ret_path
= (char*) calloc(size
, 1)) == NULL
)
222 safe_strcpy(&ret_path
[add_root
], size
-add_root
, path
);
224 // Ensure consistancy with root prefix
225 for (j
=0; j
<root_size
; j
++)
226 ret_path
[j
] = root_prefix
[j
];
228 // Same goes for '\' and '#' after the root prefix. Ensure '#' is used
229 for(j
=root_size
; j
<size
; j
++) {
230 ret_path
[j
] = (char)toupper((int)ret_path
[j
]); // Fix case too
231 if (ret_path
[j
] == '\\')
239 * Cfgmgr32, OLE32 and SetupAPI DLL functions
241 static int init_dlls(void)
243 DLL_LOAD(Cfgmgr32
.dll
, CM_Get_Parent
, TRUE
);
244 DLL_LOAD(Cfgmgr32
.dll
, CM_Get_Child
, TRUE
);
245 DLL_LOAD(Cfgmgr32
.dll
, CM_Get_Sibling
, TRUE
);
246 DLL_LOAD(Cfgmgr32
.dll
, CM_Get_Device_IDA
, TRUE
);
247 // Prefixed to avoid conflict with header files
248 DLL_LOAD_PREFIXED(OLE32
.dll
, p
, CLSIDFromString
, TRUE
);
249 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiGetClassDevsA
, TRUE
);
250 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiEnumDeviceInfo
, TRUE
);
251 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiEnumDeviceInterfaces
, TRUE
);
252 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiGetDeviceInterfaceDetailA
, TRUE
);
253 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiDestroyDeviceInfoList
, TRUE
);
254 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiOpenDevRegKey
, TRUE
);
255 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiGetDeviceRegistryPropertyA
, TRUE
);
256 DLL_LOAD_PREFIXED(SetupAPI
.dll
, p
, SetupDiOpenDeviceInterfaceRegKey
, TRUE
);
257 DLL_LOAD_PREFIXED(AdvAPI32
.dll
, p
, RegQueryValueExW
, TRUE
);
258 DLL_LOAD_PREFIXED(AdvAPI32
.dll
, p
, RegCloseKey
, TRUE
);
259 return LIBUSB_SUCCESS
;
263 * enumerate interfaces for the whole USB class
266 * dev_info: a pointer to a dev_info list
267 * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
268 * usb_class: the generic USB class for which to retrieve interface details
269 * index: zero based index of the interface in the device info list
271 * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
272 * structure returned and call this function repeatedly using the same guid (with an
273 * incremented index starting at zero) until all interfaces have been returned.
275 static bool get_devinfo_data(struct libusb_context
*ctx
,
276 HDEVINFO
*dev_info
, SP_DEVINFO_DATA
*dev_info_data
, const char* usb_class
, unsigned _index
)
279 *dev_info
= pSetupDiGetClassDevsA(NULL
, usb_class
, NULL
, DIGCF_PRESENT
|DIGCF_ALLCLASSES
);
280 if (*dev_info
== INVALID_HANDLE_VALUE
) {
285 dev_info_data
->cbSize
= sizeof(SP_DEVINFO_DATA
);
286 if (!pSetupDiEnumDeviceInfo(*dev_info
, _index
, dev_info_data
)) {
287 if (GetLastError() != ERROR_NO_MORE_ITEMS
) {
288 usbi_err(ctx
, "Could not obtain device info data for index %u: %s",
289 _index
, windows_error_str(0));
291 pSetupDiDestroyDeviceInfoList(*dev_info
);
292 *dev_info
= INVALID_HANDLE_VALUE
;
299 * enumerate interfaces for a specific GUID
302 * dev_info: a pointer to a dev_info list
303 * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
304 * guid: the GUID for which to retrieve interface details
305 * index: zero based index of the interface in the device info list
307 * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
308 * structure returned and call this function repeatedly using the same guid (with an
309 * incremented index starting at zero) until all interfaces have been returned.
311 static SP_DEVICE_INTERFACE_DETAIL_DATA_A
*get_interface_details(struct libusb_context
*ctx
,
312 HDEVINFO
*dev_info
, SP_DEVINFO_DATA
*dev_info_data
, const GUID
* guid
, unsigned _index
)
314 SP_DEVICE_INTERFACE_DATA dev_interface_data
;
315 SP_DEVICE_INTERFACE_DETAIL_DATA_A
*dev_interface_details
= NULL
;
319 *dev_info
= pSetupDiGetClassDevsA(guid
, NULL
, NULL
, DIGCF_PRESENT
|DIGCF_DEVICEINTERFACE
);
322 if (dev_info_data
!= NULL
) {
323 dev_info_data
->cbSize
= sizeof(SP_DEVINFO_DATA
);
324 if (!pSetupDiEnumDeviceInfo(*dev_info
, _index
, dev_info_data
)) {
325 if (GetLastError() != ERROR_NO_MORE_ITEMS
) {
326 usbi_err(ctx
, "Could not obtain device info data for index %u: %s",
327 _index
, windows_error_str(0));
329 pSetupDiDestroyDeviceInfoList(*dev_info
);
330 *dev_info
= INVALID_HANDLE_VALUE
;
335 dev_interface_data
.cbSize
= sizeof(SP_DEVICE_INTERFACE_DATA
);
336 if (!pSetupDiEnumDeviceInterfaces(*dev_info
, NULL
, guid
, _index
, &dev_interface_data
)) {
337 if (GetLastError() != ERROR_NO_MORE_ITEMS
) {
338 usbi_err(ctx
, "Could not obtain interface data for index %u: %s",
339 _index
, windows_error_str(0));
341 pSetupDiDestroyDeviceInfoList(*dev_info
);
342 *dev_info
= INVALID_HANDLE_VALUE
;
346 // Read interface data (dummy + actual) to access the device path
347 if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info
, &dev_interface_data
, NULL
, 0, &size
, NULL
)) {
348 // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
349 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
) {
350 usbi_err(ctx
, "could not access interface data (dummy) for index %u: %s",
351 _index
, windows_error_str(0));
355 usbi_err(ctx
, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
359 if ((dev_interface_details
= (SP_DEVICE_INTERFACE_DETAIL_DATA_A
*) calloc(size
, 1)) == NULL
) {
360 usbi_err(ctx
, "could not allocate interface data for index %u.", _index
);
364 dev_interface_details
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
);
365 if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info
, &dev_interface_data
,
366 dev_interface_details
, size
, &size
, NULL
)) {
367 usbi_err(ctx
, "could not access interface data (actual) for index %u: %s",
368 _index
, windows_error_str(0));
371 return dev_interface_details
;
374 pSetupDiDestroyDeviceInfoList(*dev_info
);
375 *dev_info
= INVALID_HANDLE_VALUE
;
379 /* For libusb0 filter */
380 static SP_DEVICE_INTERFACE_DETAIL_DATA_A
*get_interface_details_filter(struct libusb_context
*ctx
,
381 HDEVINFO
*dev_info
, SP_DEVINFO_DATA
*dev_info_data
, const GUID
* guid
, unsigned _index
, char* filter_path
){
382 SP_DEVICE_INTERFACE_DATA dev_interface_data
;
383 SP_DEVICE_INTERFACE_DETAIL_DATA_A
*dev_interface_details
= NULL
;
386 *dev_info
= pSetupDiGetClassDevsA(guid
, NULL
, NULL
, DIGCF_PRESENT
|DIGCF_DEVICEINTERFACE
);
388 if (dev_info_data
!= NULL
) {
389 dev_info_data
->cbSize
= sizeof(SP_DEVINFO_DATA
);
390 if (!pSetupDiEnumDeviceInfo(*dev_info
, _index
, dev_info_data
)) {
391 if (GetLastError() != ERROR_NO_MORE_ITEMS
) {
392 usbi_err(ctx
, "Could not obtain device info data for index %u: %s",
393 _index
, windows_error_str(0));
395 pSetupDiDestroyDeviceInfoList(*dev_info
);
396 *dev_info
= INVALID_HANDLE_VALUE
;
400 dev_interface_data
.cbSize
= sizeof(SP_DEVICE_INTERFACE_DATA
);
401 if (!pSetupDiEnumDeviceInterfaces(*dev_info
, NULL
, guid
, _index
, &dev_interface_data
)) {
402 if (GetLastError() != ERROR_NO_MORE_ITEMS
) {
403 usbi_err(ctx
, "Could not obtain interface data for index %u: %s",
404 _index
, windows_error_str(0));
406 pSetupDiDestroyDeviceInfoList(*dev_info
);
407 *dev_info
= INVALID_HANDLE_VALUE
;
410 // Read interface data (dummy + actual) to access the device path
411 if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info
, &dev_interface_data
, NULL
, 0, &size
, NULL
)) {
412 // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
413 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
) {
414 usbi_err(ctx
, "could not access interface data (dummy) for index %u: %s",
415 _index
, windows_error_str(0));
419 usbi_err(ctx
, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
422 if ((dev_interface_details
= malloc(size
)) == NULL
) {
423 usbi_err(ctx
, "could not allocate interface data for index %u.", _index
);
426 dev_interface_details
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
);
427 if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info
, &dev_interface_data
,
428 dev_interface_details
, size
, &size
, NULL
)) {
429 usbi_err(ctx
, "could not access interface data (actual) for index %u: %s",
430 _index
, windows_error_str(0));
432 // [trobinso] lookup the libusb0 symbolic index.
433 if (dev_interface_details
) {
434 HKEY hkey_device_interface
=pSetupDiOpenDeviceInterfaceRegKey(*dev_info
,&dev_interface_data
,0,KEY_READ
);
435 if (hkey_device_interface
!= INVALID_HANDLE_VALUE
) {
436 DWORD libusb0_symboliclink_index
=0;
437 DWORD value_length
=sizeof(DWORD
);
440 status
= pRegQueryValueExW(hkey_device_interface
, L
"LUsb0", NULL
, &value_type
,
441 (LPBYTE
) &libusb0_symboliclink_index
, &value_length
);
442 if (status
== ERROR_SUCCESS
) {
443 if (libusb0_symboliclink_index
< 256) {
444 // libusb0.sys is connected to this device instance.
445 // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
446 safe_sprintf(filter_path
, sizeof("\\\\.\\libusb0-0000"), "\\\\.\\libusb0-%04d", libusb0_symboliclink_index
);
447 usbi_dbg("assigned libusb0 symbolic link %s", filter_path
);
449 // libusb0.sys was connected to this device instance at one time; but not anymore.
452 pRegCloseKey(hkey_device_interface
);
455 return dev_interface_details
;
457 pSetupDiDestroyDeviceInfoList(*dev_info
);
458 *dev_info
= INVALID_HANDLE_VALUE
;
461 /* Hash table functions - modified From glibc 2.3.2:
462 [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
463 [Knuth] The Art of Computer Programming, part 3 (6.4) */
464 typedef struct htab_entry
{
468 htab_entry
* htab_table
= NULL
;
469 usbi_mutex_t htab_write_mutex
= NULL
;
470 unsigned long htab_size
, htab_filled
;
472 /* For the used double hash method the table size has to be a prime. To
473 correct the user given table size we need a prime test. This trivial
474 algorithm is adequate because the code is called only during init and
475 the number is likely to be small */
476 static int isprime(unsigned long number
)
478 // no even number will be passed
479 unsigned int divider
= 3;
481 while((divider
* divider
< number
) && (number
% divider
!= 0))
484 return (number
% divider
!= 0);
487 /* Before using the hash table we must allocate memory for it.
488 We allocate one element more as the found prime number says.
489 This is done for more effective indexing as explained in the
490 comment for the hash function. */
491 static int htab_create(struct libusb_context
*ctx
, unsigned long nel
)
493 if (htab_table
!= NULL
) {
494 usbi_err(ctx
, "hash table already allocated");
498 usbi_mutex_init(&htab_write_mutex
, NULL
);
500 // Change nel to the first prime number not smaller as nel.
506 usbi_dbg("using %d entries hash table", nel
);
509 // allocate memory and zero out.
510 htab_table
= (htab_entry
*) calloc(htab_size
+ 1, sizeof(htab_entry
));
511 if (htab_table
== NULL
) {
512 usbi_err(ctx
, "could not allocate space for hash table");
519 /* After using the hash table it has to be destroyed. */
520 static void htab_destroy(void)
523 if (htab_table
== NULL
) {
527 for (i
=0; i
<htab_size
; i
++) {
528 if (htab_table
[i
].used
) {
529 safe_free(htab_table
[i
].str
);
532 usbi_mutex_destroy(&htab_write_mutex
);
533 safe_free(htab_table
);
536 /* This is the search function. It uses double hashing with open addressing.
537 We use an trick to speed up the lookup. The table is created with one
538 more element available. This enables us to use the index zero special.
539 This index will never be used because we store the first hash index in
540 the field used where zero means not used. Every other value means used.
541 The used field can be used as a first fast comparison for equality of
542 the stored and the parameter value. This helps to prevent unnecessary
543 expensive calls of strcmp. */
544 static unsigned long htab_hash(char* str
)
546 unsigned long hval
, hval2
;
548 unsigned long r
= 5381;
555 // Compute main hash value (algorithm suggested by Nokia)
556 while ((c
= *sz
++) != 0)
557 r
= ((r
<< 5) + r
) + c
;
561 // compute table hash: simply take the modulus
562 hval
= r
% htab_size
;
566 // Try the first index
569 if (htab_table
[idx
].used
) {
570 if ( (htab_table
[idx
].used
== hval
)
571 && (safe_strcmp(str
, htab_table
[idx
].str
) == 0) ) {
575 usbi_dbg("hash collision ('%s' vs '%s')", str
, htab_table
[idx
].str
);
577 // Second hash function, as suggested in [Knuth]
578 hval2
= 1 + hval
% (htab_size
- 2);
581 // Because size is prime this guarantees to step through all available indexes
583 idx
= htab_size
+ idx
- hval2
;
588 // If we visited all entries leave the loop unsuccessfully
593 // If entry is found use it.
594 if ( (htab_table
[idx
].used
== hval
)
595 && (safe_strcmp(str
, htab_table
[idx
].str
) == 0) ) {
599 while (htab_table
[idx
].used
);
602 // Not found => New entry
604 // If the table is full return an error
605 if (htab_filled
>= htab_size
) {
606 usbi_err(NULL
, "hash table is full (%d entries)", htab_size
);
610 // Concurrent threads might be storing the same entry at the same time
611 // (eg. "simultaneous" enums from different threads) => use a mutex
612 usbi_mutex_lock(&htab_write_mutex
);
613 // Just free any previously allocated string (which should be the same as
614 // new one). The possibility of concurrent threads storing a collision
615 // string (same hash, different string) at the same time is extremely low
616 safe_free(htab_table
[idx
].str
);
617 htab_table
[idx
].used
= hval
;
618 htab_table
[idx
].str
= (char*) malloc(safe_strlen(str
)+1);
619 if (htab_table
[idx
].str
== NULL
) {
620 usbi_err(NULL
, "could not duplicate string for hash table");
621 usbi_mutex_unlock(&htab_write_mutex
);
624 memcpy(htab_table
[idx
].str
, str
, safe_strlen(str
)+1);
626 usbi_mutex_unlock(&htab_write_mutex
);
632 * Returns the session ID of a device's nth level ancestor
633 * If there's no device at the nth level, return 0
635 static unsigned long get_ancestor_session_id(DWORD devinst
, unsigned level
)
637 DWORD parent_devinst
;
638 unsigned long session_id
= 0;
639 char* sanitized_path
= NULL
;
640 char path
[MAX_PATH_LENGTH
];
643 if (level
< 1) return 0;
644 for (i
= 0; i
<level
; i
++) {
645 if (CM_Get_Parent(&parent_devinst
, devinst
, 0) != CR_SUCCESS
) {
648 devinst
= parent_devinst
;
650 if (CM_Get_Device_IDA(devinst
, path
, MAX_PATH_LENGTH
, 0) != CR_SUCCESS
) {
653 // TODO: (post hotplug): try without sanitizing
654 sanitized_path
= sanitize_path(path
);
655 if (sanitized_path
== NULL
) {
658 session_id
= htab_hash(sanitized_path
);
659 safe_free(sanitized_path
);
664 * Populate the endpoints addresses of the device_priv interface helper structs
666 static int windows_assign_endpoints(struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
)
669 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
670 struct libusb_config_descriptor
*conf_desc
;
671 const struct libusb_interface_descriptor
*if_desc
;
672 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
674 r
= libusb_get_config_descriptor(dev_handle
->dev
, 0, &conf_desc
);
675 if (r
!= LIBUSB_SUCCESS
) {
676 usbi_warn(ctx
, "could not read config descriptor: error %d", r
);
680 if_desc
= &conf_desc
->interface
[iface
].altsetting
[altsetting
];
681 safe_free(priv
->usb_interface
[iface
].endpoint
);
683 if (if_desc
->bNumEndpoints
== 0) {
684 usbi_dbg("no endpoints found for interface %d", iface
);
685 return LIBUSB_SUCCESS
;
688 priv
->usb_interface
[iface
].endpoint
= (uint8_t*) malloc(if_desc
->bNumEndpoints
);
689 if (priv
->usb_interface
[iface
].endpoint
== NULL
) {
690 return LIBUSB_ERROR_NO_MEM
;
693 priv
->usb_interface
[iface
].nb_endpoints
= if_desc
->bNumEndpoints
;
694 for (i
=0; i
<if_desc
->bNumEndpoints
; i
++) {
695 priv
->usb_interface
[iface
].endpoint
[i
] = if_desc
->endpoint
[i
].bEndpointAddress
;
696 usbi_dbg("(re)assigned endpoint %02X to interface %d", priv
->usb_interface
[iface
].endpoint
[i
], iface
);
698 libusb_free_config_descriptor(conf_desc
);
700 // Extra init may be required to configure endpoints
701 return priv
->apib
->configure_endpoints(SUB_API_NOTSET
, dev_handle
, iface
);
704 // Lookup for a match in the list of API driver names
705 // return -1 if not found, driver match number otherwise
706 static int get_sub_api(char* driver
, int api
){
708 const char sep_str
[2] = {LIST_SEPARATOR
, 0};
710 size_t len
= safe_strlen(driver
);
712 if (len
== 0) return SUB_API_NOTSET
;
713 tmp_str
= (char*) calloc(len
+1, 1);
714 if (tmp_str
== NULL
) return SUB_API_NOTSET
;
715 memcpy(tmp_str
, driver
, len
+1);
716 tok
= strtok(tmp_str
, sep_str
);
717 while (tok
!= NULL
) {
718 for (i
=0; i
<usb_api_backend
[api
].nb_driver_names
; i
++) {
719 if (safe_stricmp(tok
, usb_api_backend
[api
].driver_name_list
[i
]) == 0) {
724 tok
= strtok(NULL
, sep_str
);
727 return SUB_API_NOTSET
;
731 * auto-claiming and auto-release helper functions
733 static int auto_claim(struct libusb_transfer
*transfer
, int *interface_number
, int api_type
)
735 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
736 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(
737 transfer
->dev_handle
);
738 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
739 int current_interface
= *interface_number
;
740 int r
= LIBUSB_SUCCESS
;
743 case USB_API_WINUSBX
:
747 return LIBUSB_ERROR_INVALID_PARAM
;
750 usbi_mutex_lock(&autoclaim_lock
);
751 if (current_interface
< 0) // No serviceable interface was found
753 for (current_interface
=0; current_interface
<USB_MAXINTERFACES
; current_interface
++) {
754 // Must claim an interface of the same API type
755 if ( (priv
->usb_interface
[current_interface
].apib
->id
== api_type
)
756 && (libusb_claim_interface(transfer
->dev_handle
, current_interface
) == LIBUSB_SUCCESS
) ) {
757 usbi_dbg("auto-claimed interface %d for control request", current_interface
);
758 if (handle_priv
->autoclaim_count
[current_interface
] != 0) {
759 usbi_warn(ctx
, "program assertion failed - autoclaim_count was nonzero");
761 handle_priv
->autoclaim_count
[current_interface
]++;
765 if (current_interface
== USB_MAXINTERFACES
) {
766 usbi_err(ctx
, "could not auto-claim any interface");
767 r
= LIBUSB_ERROR_NOT_FOUND
;
770 // If we have a valid interface that was autoclaimed, we must increment
771 // its autoclaim count so that we can prevent an early release.
772 if (handle_priv
->autoclaim_count
[current_interface
] != 0) {
773 handle_priv
->autoclaim_count
[current_interface
]++;
776 usbi_mutex_unlock(&autoclaim_lock
);
778 *interface_number
= current_interface
;
783 static void auto_release(struct usbi_transfer
*itransfer
)
785 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
786 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
787 libusb_device_handle
*dev_handle
= transfer
->dev_handle
;
788 struct windows_device_handle_priv
* handle_priv
= _device_handle_priv(dev_handle
);
791 usbi_mutex_lock(&autoclaim_lock
);
792 if (handle_priv
->autoclaim_count
[transfer_priv
->interface_number
] > 0) {
793 handle_priv
->autoclaim_count
[transfer_priv
->interface_number
]--;
794 if (handle_priv
->autoclaim_count
[transfer_priv
->interface_number
] == 0) {
795 r
= libusb_release_interface(dev_handle
, transfer_priv
->interface_number
);
796 if (r
== LIBUSB_SUCCESS
) {
797 usbi_dbg("auto-released interface %d", transfer_priv
->interface_number
);
799 usbi_dbg("failed to auto-release interface %d (%s)",
800 transfer_priv
->interface_number
, libusb_error_name((enum libusb_error
)r
));
804 usbi_mutex_unlock(&autoclaim_lock
);
808 * init: libusbx backend init function
810 * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list
811 * In our implementation, we equate Windows' "HCD" to libusbx's "bus". Note that bus is zero indexed.
812 * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?)
814 static int windows_init(struct libusb_context
*ctx
)
816 int i
, r
= LIBUSB_ERROR_OTHER
;
817 OSVERSIONINFO os_version
;
819 char sem_name
[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
821 sprintf(sem_name
, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
822 semaphore
= CreateSemaphoreA(NULL
, 1, 1, sem_name
);
823 if (semaphore
== NULL
) {
824 usbi_err(ctx
, "could not create semaphore: %s", windows_error_str(0));
825 return LIBUSB_ERROR_NO_MEM
;
828 // A successful wait brings our semaphore count to 0 (unsignaled)
829 // => any concurent wait stalls until the semaphore's release
830 if (WaitForSingleObject(semaphore
, INFINITE
) != WAIT_OBJECT_0
) {
831 usbi_err(ctx
, "failure to access semaphore: %s", windows_error_str(0));
832 CloseHandle(semaphore
);
833 return LIBUSB_ERROR_NO_MEM
;
836 // NB: concurrent usage supposes that init calls are equally balanced with
837 // exit calls. If init is called more than exit, we will not exit properly
838 if ( ++concurrent_usage
== 0 ) { // First init?
840 memset(&os_version
, 0, sizeof(OSVERSIONINFO
));
841 os_version
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
842 windows_version
= WINDOWS_UNSUPPORTED
;
843 if ((GetVersionEx(&os_version
) != 0) && (os_version
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)) {
844 if ((os_version
.dwMajorVersion
== 5) && (os_version
.dwMinorVersion
== 1)) {
845 windows_version
= WINDOWS_XP
;
846 } else if ((os_version
.dwMajorVersion
== 5) && (os_version
.dwMinorVersion
== 2)) {
847 windows_version
= WINDOWS_2003
; // also includes XP 64
848 } else if (os_version
.dwMajorVersion
>= 6) {
849 windows_version
= WINDOWS_VISTA_AND_LATER
;
852 if (windows_version
== WINDOWS_UNSUPPORTED
) {
853 usbi_err(ctx
, "This version of Windows is NOT supported");
854 r
= LIBUSB_ERROR_NOT_SUPPORTED
;
858 // We need a lock for proper auto-release
859 usbi_mutex_init(&autoclaim_lock
, NULL
);
861 // Initialize pollable file descriptors
865 if (init_dlls() != LIBUSB_SUCCESS
) {
866 usbi_err(ctx
, "could not resolve DLL functions");
867 return LIBUSB_ERROR_NOT_FOUND
;
870 // Initialize the low level APIs (we don't care about errors at this stage)
871 for (i
=0; i
<USB_API_MAX
; i
++) {
872 usb_api_backend
[i
].init(SUB_API_NOTSET
, ctx
);
875 // Because QueryPerformanceCounter might report different values when
876 // running on different cores, we create a separate thread for the timer
877 // calls, which we glue to the first core always to prevent timing discrepancies.
878 r
= LIBUSB_ERROR_NO_MEM
;
879 for (i
= 0; i
< 2; i
++) {
880 timer_request
[i
] = CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
881 if (timer_request
[i
] == NULL
) {
882 usbi_err(ctx
, "could not create timer request event %d - aborting", i
);
886 timer_response
= CreateSemaphore(NULL
, 0, MAX_TIMER_SEMAPHORES
, NULL
);
887 if (timer_response
== NULL
) {
888 usbi_err(ctx
, "could not create timer response semaphore - aborting");
891 timer_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
892 if (timer_mutex
== NULL
) {
893 usbi_err(ctx
, "could not create timer mutex - aborting");
896 timer_thread
= (HANDLE
)_beginthreadex(NULL
, 0, windows_clock_gettime_threaded
, NULL
, 0, NULL
);
897 if (timer_thread
== NULL
) {
898 usbi_err(ctx
, "Unable to create timer thread - aborting");
901 SetThreadAffinityMask(timer_thread
, 0);
903 // Wait for timer thread to init before continuing.
904 if (WaitForSingleObject(timer_response
, INFINITE
) != WAIT_OBJECT_0
) {
905 usbi_err(ctx
, "Failed to wait for timer thread to become ready - aborting");
909 // Create a hash table to store session ids. Second parameter is better if prime
910 htab_create(ctx
, HTAB_SIZE
);
912 // At this stage, either we went through full init successfully, or didn't need to
915 init_exit
: // Holds semaphore here.
916 if (!concurrent_usage
&& r
!= LIBUSB_SUCCESS
) { // First init failed?
918 SetEvent(timer_request
[1]); // actually the signal to quit the thread.
919 if (WAIT_OBJECT_0
!= WaitForSingleObject(timer_thread
, INFINITE
)) {
920 usbi_warn(ctx
, "could not wait for timer thread to quit");
921 TerminateThread(timer_thread
, 1); // shouldn't happen, but we're destroying
922 // all objects it might have held anyway.
924 CloseHandle(timer_thread
);
927 for (i
= 0; i
< 2; i
++) {
928 if (timer_request
[i
]) {
929 CloseHandle(timer_request
[i
]);
930 timer_request
[i
] = NULL
;
933 if (timer_response
) {
934 CloseHandle(timer_response
);
935 timer_response
= NULL
;
938 CloseHandle(timer_mutex
);
944 if (r
!= LIBUSB_SUCCESS
)
945 --concurrent_usage
; // Not expected to call libusb_exit if we failed.
947 ReleaseSemaphore(semaphore
, 1, NULL
); // increase count back to 1
948 CloseHandle(semaphore
);
953 * HCD (root) hubs need to have their device descriptor manually populated
955 * Note that, like Microsoft does in the device manager, we populate the
956 * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device.
958 static int force_hcd_device_descriptor(struct libusb_device
*dev
)
960 struct windows_device_priv
*parent_priv
, *priv
= _device_priv(dev
);
961 struct libusb_context
*ctx
= DEVICE_CTX(dev
);
964 dev
->num_configurations
= 1;
965 priv
->dev_descriptor
.bLength
= sizeof(USB_DEVICE_DESCRIPTOR
);
966 priv
->dev_descriptor
.bDescriptorType
= USB_DEVICE_DESCRIPTOR_TYPE
;
967 priv
->dev_descriptor
.bNumConfigurations
= 1;
968 priv
->active_config
= 1;
970 if (priv
->parent_dev
== NULL
) {
971 usbi_err(ctx
, "program assertion failed - HCD hub has no parent");
972 return LIBUSB_ERROR_NO_DEVICE
;
974 parent_priv
= _device_priv(priv
->parent_dev
);
975 if (sscanf(parent_priv
->path
, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid
, &pid
) == 2) {
976 priv
->dev_descriptor
.idVendor
= (uint16_t)vid
;
977 priv
->dev_descriptor
.idProduct
= (uint16_t)pid
;
979 usbi_warn(ctx
, "could not infer VID/PID of HCD hub from '%s'", parent_priv
->path
);
980 priv
->dev_descriptor
.idVendor
= 0x1d6b; // Linux Foundation root hub
981 priv
->dev_descriptor
.idProduct
= 1;
983 return LIBUSB_SUCCESS
;
987 * fetch and cache all the config descriptors through I/O
989 static int cache_config_descriptors(struct libusb_device
*dev
, HANDLE hub_handle
, char* device_id
)
991 DWORD size
, ret_size
;
992 struct libusb_context
*ctx
= DEVICE_CTX(dev
);
993 struct windows_device_priv
*priv
= _device_priv(dev
);
997 USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short
; // dummy request
998 PUSB_DESCRIPTOR_REQUEST cd_buf_actual
= NULL
; // actual request
999 PUSB_CONFIGURATION_DESCRIPTOR cd_data
= NULL
;
1001 if (dev
->num_configurations
== 0)
1002 return LIBUSB_ERROR_INVALID_PARAM
;
1004 priv
->config_descriptor
= (unsigned char**) calloc(dev
->num_configurations
, sizeof(unsigned char*));
1005 if (priv
->config_descriptor
== NULL
)
1006 return LIBUSB_ERROR_NO_MEM
;
1007 for (i
=0; i
<dev
->num_configurations
; i
++)
1008 priv
->config_descriptor
[i
] = NULL
;
1010 for (i
=0, r
=LIBUSB_SUCCESS
; ; i
++)
1012 // safe loop: release all dynamic resources
1013 safe_free(cd_buf_actual
);
1015 // safe loop: end of loop condition
1016 if ((i
>= dev
->num_configurations
) || (r
!= LIBUSB_SUCCESS
))
1019 size
= sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT
);
1020 memset(&cd_buf_short
, 0, size
);
1022 cd_buf_short
.req
.ConnectionIndex
= (ULONG
)priv
->port
;
1023 cd_buf_short
.req
.SetupPacket
.bmRequest
= LIBUSB_ENDPOINT_IN
;
1024 cd_buf_short
.req
.SetupPacket
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1025 cd_buf_short
.req
.SetupPacket
.wValue
= (USB_CONFIGURATION_DESCRIPTOR_TYPE
<< 8) | i
;
1026 cd_buf_short
.req
.SetupPacket
.wIndex
= i
;
1027 cd_buf_short
.req
.SetupPacket
.wLength
= (USHORT
)(size
- sizeof(USB_DESCRIPTOR_REQUEST
));
1029 // Dummy call to get the required data size. Initial failures are reported as info rather
1030 // than error as they can occur for non-penalizing situations, such as with some hubs.
1031 if (!DeviceIoControl(hub_handle
, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
, &cd_buf_short
, size
,
1032 &cd_buf_short
, size
, &ret_size
, NULL
)) {
1033 usbi_info(ctx
, "could not access configuration descriptor (dummy) for '%s': %s", device_id
, windows_error_str(0));
1034 LOOP_BREAK(LIBUSB_ERROR_IO
);
1037 if ((ret_size
!= size
) || (cd_buf_short
.data
.wTotalLength
< sizeof(USB_CONFIGURATION_DESCRIPTOR
))) {
1038 usbi_info(ctx
, "unexpected configuration descriptor size (dummy) for '%s'.", device_id
);
1039 LOOP_BREAK(LIBUSB_ERROR_IO
);
1042 size
= sizeof(USB_DESCRIPTOR_REQUEST
) + cd_buf_short
.data
.wTotalLength
;
1043 if ((cd_buf_actual
= (PUSB_DESCRIPTOR_REQUEST
) calloc(1, size
)) == NULL
) {
1044 usbi_err(ctx
, "could not allocate configuration descriptor buffer for '%s'.", device_id
);
1045 LOOP_BREAK(LIBUSB_ERROR_NO_MEM
);
1047 memset(cd_buf_actual
, 0, size
);
1050 cd_buf_actual
->ConnectionIndex
= (ULONG
)priv
->port
;
1051 cd_buf_actual
->SetupPacket
.bmRequest
= LIBUSB_ENDPOINT_IN
;
1052 cd_buf_actual
->SetupPacket
.bRequest
= USB_REQUEST_GET_DESCRIPTOR
;
1053 cd_buf_actual
->SetupPacket
.wValue
= (USB_CONFIGURATION_DESCRIPTOR_TYPE
<< 8) | i
;
1054 cd_buf_actual
->SetupPacket
.wIndex
= i
;
1055 cd_buf_actual
->SetupPacket
.wLength
= (USHORT
)(size
- sizeof(USB_DESCRIPTOR_REQUEST
));
1057 if (!DeviceIoControl(hub_handle
, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
, cd_buf_actual
, size
,
1058 cd_buf_actual
, size
, &ret_size
, NULL
)) {
1059 usbi_err(ctx
, "could not access configuration descriptor (actual) for '%s': %s", device_id
, windows_error_str(0));
1060 LOOP_BREAK(LIBUSB_ERROR_IO
);
1063 cd_data
= (PUSB_CONFIGURATION_DESCRIPTOR
)((UCHAR
*)cd_buf_actual
+sizeof(USB_DESCRIPTOR_REQUEST
));
1065 if ((size
!= ret_size
) || (cd_data
->wTotalLength
!= cd_buf_short
.data
.wTotalLength
)) {
1066 usbi_err(ctx
, "unexpected configuration descriptor size (actual) for '%s'.", device_id
);
1067 LOOP_BREAK(LIBUSB_ERROR_IO
);
1070 if (cd_data
->bDescriptorType
!= USB_CONFIGURATION_DESCRIPTOR_TYPE
) {
1071 usbi_err(ctx
, "not a configuration descriptor for '%s'", device_id
);
1072 LOOP_BREAK(LIBUSB_ERROR_IO
);
1075 usbi_dbg("cached config descriptor %d (bConfigurationValue=%d, %d bytes)",
1076 i
, cd_data
->bConfigurationValue
, cd_data
->wTotalLength
);
1078 // Cache the descriptor
1079 priv
->config_descriptor
[i
] = (unsigned char*) malloc(cd_data
->wTotalLength
);
1080 if (priv
->config_descriptor
[i
] == NULL
)
1081 return LIBUSB_ERROR_NO_MEM
;
1082 memcpy(priv
->config_descriptor
[i
], cd_data
, cd_data
->wTotalLength
);
1084 return LIBUSB_SUCCESS
;
1088 * Populate a libusbx device structure
1090 static int init_device(struct libusb_device
* dev
, struct libusb_device
* parent_dev
,
1091 uint8_t port_number
, char* device_id
, DWORD devinst
)
1095 USB_NODE_CONNECTION_INFORMATION_EX conn_info
;
1096 struct windows_device_priv
*priv
, *parent_priv
;
1097 struct libusb_context
*ctx
= DEVICE_CTX(dev
);
1098 struct libusb_device
* tmp_dev
;
1101 if ((dev
== NULL
) || (parent_dev
== NULL
)) {
1102 return LIBUSB_ERROR_NOT_FOUND
;
1104 priv
= _device_priv(dev
);
1105 parent_priv
= _device_priv(parent_dev
);
1106 if (parent_priv
->apib
->id
!= USB_API_HUB
) {
1107 usbi_warn(ctx
, "parent for device '%s' is not a hub", device_id
);
1108 return LIBUSB_ERROR_NOT_FOUND
;
1111 // It is possible for the parent hub not to have been initialized yet
1112 // If that's the case, lookup the ancestors to set the bus number
1113 if (parent_dev
->bus_number
== 0) {
1115 tmp_dev
= usbi_get_device_by_session_id(ctx
, get_ancestor_session_id(devinst
, i
));
1116 if (tmp_dev
== NULL
) break;
1117 if (tmp_dev
->bus_number
!= 0) {
1118 usbi_dbg("got bus number from ancestor #%d", i
);
1119 parent_dev
->bus_number
= tmp_dev
->bus_number
;
1120 libusb_unref_device(tmp_dev
);
1123 libusb_unref_device(tmp_dev
);
1126 if (parent_dev
->bus_number
== 0) {
1127 usbi_err(ctx
, "program assertion failed: unable to find ancestor bus number for '%s'", device_id
);
1128 return LIBUSB_ERROR_NOT_FOUND
;
1130 dev
->bus_number
= parent_dev
->bus_number
;
1131 priv
->port
= port_number
;
1132 dev
->port_number
= port_number
;
1133 priv
->depth
= parent_priv
->depth
+ 1;
1134 priv
->parent_dev
= parent_dev
;
1135 dev
->parent_dev
= parent_dev
;
1137 // If the device address is already set, we can stop here
1138 if (dev
->device_address
!= 0) {
1139 return LIBUSB_SUCCESS
;
1141 memset(&conn_info
, 0, sizeof(conn_info
));
1142 if (priv
->depth
!= 0) { // Not a HCD hub
1143 handle
= CreateFileA(parent_priv
->path
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
,
1144 FILE_FLAG_OVERLAPPED
, NULL
);
1145 if (handle
== INVALID_HANDLE_VALUE
) {
1146 usbi_warn(ctx
, "could not open hub %s: %s", parent_priv
->path
, windows_error_str(0));
1147 return LIBUSB_ERROR_ACCESS
;
1149 size
= sizeof(conn_info
);
1150 conn_info
.ConnectionIndex
= (ULONG
)port_number
;
1151 if (!DeviceIoControl(handle
, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
, &conn_info
, size
,
1152 &conn_info
, size
, &size
, NULL
)) {
1153 usbi_warn(ctx
, "could not get node connection information for device '%s': %s",
1154 device_id
, windows_error_str(0));
1155 safe_closehandle(handle
);
1156 return LIBUSB_ERROR_NO_DEVICE
;
1158 if (conn_info
.ConnectionStatus
== NoDeviceConnected
) {
1159 usbi_err(ctx
, "device '%s' is no longer connected!", device_id
);
1160 safe_closehandle(handle
);
1161 return LIBUSB_ERROR_NO_DEVICE
;
1163 memcpy(&priv
->dev_descriptor
, &(conn_info
.DeviceDescriptor
), sizeof(USB_DEVICE_DESCRIPTOR
));
1164 dev
->num_configurations
= priv
->dev_descriptor
.bNumConfigurations
;
1165 priv
->active_config
= conn_info
.CurrentConfigurationValue
;
1166 usbi_dbg("found %d configurations (active conf: %d)", dev
->num_configurations
, priv
->active_config
);
1167 // If we can't read the config descriptors, just set the number of confs to zero
1168 if (cache_config_descriptors(dev
, handle
, device_id
) != LIBUSB_SUCCESS
) {
1169 dev
->num_configurations
= 0;
1170 priv
->dev_descriptor
.bNumConfigurations
= 0;
1172 safe_closehandle(handle
);
1174 if (conn_info
.DeviceAddress
> UINT8_MAX
) {
1175 usbi_err(ctx
, "program assertion failed: device address overflow");
1177 dev
->device_address
= (uint8_t)conn_info
.DeviceAddress
+ 1;
1178 if (dev
->device_address
== 1) {
1179 usbi_err(ctx
, "program assertion failed: device address collision with root hub");
1181 switch (conn_info
.Speed
) {
1182 case 0: dev
->speed
= LIBUSB_SPEED_LOW
; break;
1183 case 1: dev
->speed
= LIBUSB_SPEED_FULL
; break;
1184 case 2: dev
->speed
= LIBUSB_SPEED_HIGH
; break;
1185 case 3: dev
->speed
= LIBUSB_SPEED_SUPER
; break;
1187 usbi_warn(ctx
, "Got unknown device speed %d", conn_info
.Speed
);
1191 dev
->device_address
= 1; // root hubs are set to use device number 1
1192 force_hcd_device_descriptor(dev
);
1195 usbi_sanitize_device(dev
);
1197 usbi_dbg("(bus: %d, addr: %d, depth: %d, port: %d): '%s'",
1198 dev
->bus_number
, dev
->device_address
, priv
->depth
, priv
->port
, device_id
);
1200 return LIBUSB_SUCCESS
;
1203 // Returns the api type, or 0 if not found/unsupported
1204 static void get_api_type(struct libusb_context
*ctx
, HDEVINFO
*dev_info
,
1205 SP_DEVINFO_DATA
*dev_info_data
, int *api
, int *sub_api
)
1207 // Precedence for filter drivers vs driver is in the order of this array
1208 struct driver_lookup lookup
[3] = {
1209 {"\0\0", SPDRP_SERVICE
, "driver"},
1210 {"\0\0", SPDRP_UPPERFILTERS
, "upper filter driver"},
1211 {"\0\0", SPDRP_LOWERFILTERS
, "lower filter driver"}
1213 DWORD size
, reg_type
;
1217 *api
= USB_API_UNSUPPORTED
;
1218 *sub_api
= SUB_API_NOTSET
;
1219 // Check the service & filter names to know the API we should use
1220 for (k
=0; k
<3; k
++) {
1221 if (pSetupDiGetDeviceRegistryPropertyA(*dev_info
, dev_info_data
, lookup
[k
].reg_prop
,
1222 ®_type
, (BYTE
*)lookup
[k
].list
, MAX_KEY_LENGTH
, &size
)) {
1223 // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ
1224 if (lookup
[k
].reg_prop
== SPDRP_SERVICE
) {
1225 // our buffers are MAX_KEY_LENGTH+1 so we can overflow if needed
1226 lookup
[k
].list
[safe_strlen(lookup
[k
].list
)+1] = 0;
1228 // MULTI_SZ is a pain to work with. Turn it into something much more manageable
1229 // NB: none of the driver names we check against contain LIST_SEPARATOR,
1230 // (currently ';'), so even if an unsuported one does, it's not an issue
1231 for (l
=0; (lookup
[k
].list
[l
] != 0) || (lookup
[k
].list
[l
+1] != 0); l
++) {
1232 if (lookup
[k
].list
[l
] == 0) {
1233 lookup
[k
].list
[l
] = LIST_SEPARATOR
;
1236 usbi_dbg("%s(s): %s", lookup
[k
].designation
, lookup
[k
].list
);
1238 if (GetLastError() != ERROR_INVALID_DATA
) {
1239 usbi_dbg("could not access %s: %s", lookup
[k
].designation
, windows_error_str(0));
1241 lookup
[k
].list
[0] = 0;
1245 for (i
=1; i
<USB_API_MAX
; i
++) {
1246 for (k
=0; k
<3; k
++) {
1247 j
= get_sub_api(lookup
[k
].list
, i
);
1249 usbi_dbg("matched %s name against %s API",
1250 lookup
[k
].designation
, (i
!=USB_API_WINUSBX
)?usb_api_backend
[i
].designation
:sub_api_name
[j
]);
1259 static int set_composite_interface(struct libusb_context
* ctx
, struct libusb_device
* dev
,
1260 char* dev_interface_path
, char* device_id
, int api
, int sub_api
)
1263 struct windows_device_priv
*priv
= _device_priv(dev
);
1264 int interface_number
;
1266 if (priv
->apib
->id
!= USB_API_COMPOSITE
) {
1267 usbi_err(ctx
, "program assertion failed: '%s' is not composite", device_id
);
1268 return LIBUSB_ERROR_NO_DEVICE
;
1271 // Because MI_## are not necessarily in sequential order (some composite
1272 // devices will have only MI_00 & MI_03 for instance), we retrieve the actual
1273 // interface number from the path's MI value
1274 interface_number
= 0;
1275 for (i
=0; device_id
[i
] != 0; ) {
1276 if ( (device_id
[i
++] == 'M') && (device_id
[i
++] == 'I')
1277 && (device_id
[i
++] == '_') ) {
1278 interface_number
= (device_id
[i
++] - '0')*10;
1279 interface_number
+= device_id
[i
] - '0';
1284 if (device_id
[i
] == 0) {
1285 usbi_warn(ctx
, "failure to read interface number for %s. Using default value %d",
1286 device_id
, interface_number
);
1289 if (priv
->usb_interface
[interface_number
].path
!= NULL
) {
1290 if (api
== USB_API_HID
) {
1291 // HID devices can have multiple collections (COL##) for each MI_## interface
1292 usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
1293 interface_number
, device_id
);
1294 return LIBUSB_ERROR_ACCESS
;
1296 // In other cases, just use the latest data
1297 safe_free(priv
->usb_interface
[interface_number
].path
);
1300 usbi_dbg("interface[%d] = %s", interface_number
, dev_interface_path
);
1301 priv
->usb_interface
[interface_number
].path
= dev_interface_path
;
1302 priv
->usb_interface
[interface_number
].apib
= &usb_api_backend
[api
];
1303 priv
->usb_interface
[interface_number
].sub_api
= sub_api
;
1304 if ((api
== USB_API_HID
) && (priv
->hid
== NULL
)) {
1305 priv
->hid
= (struct hid_device_priv
*) calloc(1, sizeof(struct hid_device_priv
));
1306 if (priv
->hid
== NULL
)
1307 return LIBUSB_ERROR_NO_MEM
;
1310 return LIBUSB_SUCCESS
;
1313 static int set_hid_interface(struct libusb_context
* ctx
, struct libusb_device
* dev
,
1314 char* dev_interface_path
)
1317 struct windows_device_priv
*priv
= _device_priv(dev
);
1319 if (priv
->hid
== NULL
) {
1320 usbi_err(ctx
, "program assertion failed: parent is not HID");
1321 return LIBUSB_ERROR_NO_DEVICE
;
1323 if (priv
->hid
->nb_interfaces
== USB_MAXINTERFACES
) {
1324 usbi_err(ctx
, "program assertion failed: max USB interfaces reached for HID device");
1325 return LIBUSB_ERROR_NO_DEVICE
;
1327 for (i
=0; i
<priv
->hid
->nb_interfaces
; i
++) {
1328 if (safe_strcmp(priv
->usb_interface
[i
].path
, dev_interface_path
) == 0) {
1329 usbi_dbg("interface[%d] already set to %s", i
, dev_interface_path
);
1330 return LIBUSB_SUCCESS
;
1334 priv
->usb_interface
[priv
->hid
->nb_interfaces
].path
= dev_interface_path
;
1335 priv
->usb_interface
[priv
->hid
->nb_interfaces
].apib
= &usb_api_backend
[USB_API_HID
];
1336 usbi_dbg("interface[%d] = %s", priv
->hid
->nb_interfaces
, dev_interface_path
);
1337 priv
->hid
->nb_interfaces
++;
1338 return LIBUSB_SUCCESS
;
1342 * get_device_list: libusbx backend device enumeration function
1344 static int windows_get_device_list(struct libusb_context
*ctx
, struct discovered_devs
**_discdevs
)
1346 struct discovered_devs
*discdevs
;
1347 HDEVINFO dev_info
= { 0 };
1348 const char* usb_class
[] = {"USB", "NUSB3", "IUSB3"};
1349 SP_DEVINFO_DATA dev_info_data
= { 0 };
1350 SP_DEVICE_INTERFACE_DETAIL_DATA_A
*dev_interface_details
= NULL
;
1352 #define MAX_ENUM_GUIDS 64
1353 const GUID
* guid
[MAX_ENUM_GUIDS
];
1359 int r
= LIBUSB_SUCCESS
;
1361 size_t class_index
= 0;
1362 unsigned int nb_guids
, pass
, i
, j
, ancestor
;
1363 char path
[MAX_PATH_LENGTH
];
1364 char strbuf
[MAX_PATH_LENGTH
];
1365 struct libusb_device
*dev
, *parent_dev
;
1366 struct windows_device_priv
*priv
, *parent_priv
;
1367 char* dev_interface_path
= NULL
;
1368 char* dev_id_path
= NULL
;
1369 unsigned long session_id
;
1370 DWORD size
, reg_type
, port_nr
, install_state
;
1372 WCHAR guid_string_w
[MAX_GUID_STRING_LENGTH
];
1375 // Keep a list of newly allocated devs to unref
1376 libusb_device
** unref_list
;
1377 unsigned int unref_size
= 64;
1378 unsigned int unref_cur
= 0;
1380 // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug)
1381 // PASS 2 : (re)enumerate HUBS
1382 // PASS 3 : (re)enumerate generic USB devices (including driverless)
1383 // and list additional USB device interface GUIDs to explore
1384 // PASS 4 : (re)enumerate master USB devices that have a device interface
1385 // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and
1386 // set the device interfaces.
1388 // Init the GUID table
1389 guid
[HCD_PASS
] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER
;
1390 guid
[HUB_PASS
] = &GUID_DEVINTERFACE_USB_HUB
;
1391 guid
[GEN_PASS
] = NULL
;
1392 guid
[DEV_PASS
] = &GUID_DEVINTERFACE_USB_DEVICE
;
1393 HidD_GetHidGuid(&hid_guid
);
1394 guid
[HID_PASS
] = &hid_guid
;
1395 nb_guids
= HID_PASS
+1;
1397 unref_list
= (libusb_device
**) calloc(unref_size
, sizeof(libusb_device
*));
1398 if (unref_list
== NULL
) {
1399 return LIBUSB_ERROR_NO_MEM
;
1402 for (pass
= 0; ((pass
< nb_guids
) && (r
== LIBUSB_SUCCESS
)); pass
++) {
1403 //#define ENUM_DEBUG
1405 const char *passname
[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" };
1406 usbi_dbg("\n#### PROCESSING %ss %s", passname
[(pass
<=HID_PASS
)?pass
:HID_PASS
+1],
1407 (pass
!=GEN_PASS
)?guid_to_string(guid
[pass
]):"");
1409 for (i
= 0; ; i
++) {
1410 // safe loop: free up any (unprotected) dynamic resource
1411 // NB: this is always executed before breaking the loop
1412 safe_free(dev_interface_details
);
1413 safe_free(dev_interface_path
);
1414 safe_free(dev_id_path
);
1415 priv
= parent_priv
= NULL
;
1416 dev
= parent_dev
= NULL
;
1418 // Safe loop: end of loop conditions
1419 if (r
!= LIBUSB_SUCCESS
) {
1422 if ((pass
== HCD_PASS
) && (i
== UINT8_MAX
)) {
1423 usbi_warn(ctx
, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX
);
1426 if (pass
!= GEN_PASS
) {
1427 // Except for GEN, all passes deal with device interfaces
1428 dev_interface_details
= get_interface_details(ctx
, &dev_info
, &dev_info_data
, guid
[pass
], i
);
1429 if (dev_interface_details
== NULL
) {
1432 dev_interface_path
= sanitize_path(dev_interface_details
->DevicePath
);
1433 if (dev_interface_path
== NULL
) {
1434 usbi_warn(ctx
, "could not sanitize device interface path for '%s'", dev_interface_details
->DevicePath
);
1439 // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are
1440 // being listed under the "NUSB3" PnP Symbolic Name rather than "USB".
1441 // The Intel USB 3.0 driver behaves similar, but uses "IUSB3"
1442 for (; class_index
< ARRAYSIZE(usb_class
); class_index
++) {
1443 if (get_devinfo_data(ctx
, &dev_info
, &dev_info_data
, usb_class
[class_index
], i
))
1447 if (class_index
>= ARRAYSIZE(usb_class
))
1451 // Read the Device ID path. This is what we'll use as UID
1452 // Note that if the device is plugged in a different port or hub, the Device ID changes
1453 if (CM_Get_Device_IDA(dev_info_data
.DevInst
, path
, sizeof(path
), 0) != CR_SUCCESS
) {
1454 usbi_warn(ctx
, "could not read the device id path for devinst %X, skipping",
1455 dev_info_data
.DevInst
);
1458 dev_id_path
= sanitize_path(path
);
1459 if (dev_id_path
== NULL
) {
1460 usbi_warn(ctx
, "could not sanitize device id path for devinst %X, skipping",
1461 dev_info_data
.DevInst
);
1465 usbi_dbg("PRO: %s", dev_id_path
);
1468 // The SPDRP_ADDRESS for USB devices is the device port number on the hub
1470 if ((pass
>= HUB_PASS
) && (pass
<= GEN_PASS
)) {
1471 if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info
, &dev_info_data
, SPDRP_ADDRESS
,
1472 ®_type
, (BYTE
*)&port_nr
, 4, &size
))
1474 usbi_warn(ctx
, "could not retrieve port number for device '%s', skipping: %s",
1475 dev_id_path
, windows_error_str(0));
1480 // Set API to use or get additional data from generic pass
1481 api
= USB_API_UNSUPPORTED
;
1482 sub_api
= SUB_API_NOTSET
;
1487 // We use the GEN pass to detect driverless devices...
1488 size
= sizeof(strbuf
);
1489 if (!pSetupDiGetDeviceRegistryPropertyA(dev_info
, &dev_info_data
, SPDRP_DRIVER
,
1490 ®_type
, (BYTE
*)strbuf
, size
, &size
)) {
1491 usbi_info(ctx
, "The following device has no driver: '%s'", dev_id_path
);
1492 usbi_info(ctx
, "libusbx will not be able to access it.");
1494 // ...and to add the additional device interface GUIDs
1495 key
= pSetupDiOpenDevRegKey(dev_info
, &dev_info_data
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_READ
);
1496 if (key
!= INVALID_HANDLE_VALUE
) {
1497 size
= sizeof(guid_string_w
);
1498 s
= pRegQueryValueExW(key
, L
"DeviceInterfaceGUIDs", NULL
, ®_type
,
1499 (BYTE
*)guid_string_w
, &size
);
1501 if (s
== ERROR_SUCCESS
) {
1502 if (nb_guids
>= MAX_ENUM_GUIDS
) {
1503 // If this assert is ever reported, grow a GUID table dynamically
1504 usbi_err(ctx
, "program assertion failed: too many GUIDs");
1505 LOOP_BREAK(LIBUSB_ERROR_OVERFLOW
);
1507 if_guid
= (GUID
*) calloc(1, sizeof(GUID
));
1508 pCLSIDFromString(guid_string_w
, if_guid
);
1509 guid
[nb_guids
++] = if_guid
;
1510 usbi_dbg("extra GUID: %s", guid_to_string(if_guid
));
1518 // Get the API type (after checking that the driver installation is OK)
1519 if ( (!pSetupDiGetDeviceRegistryPropertyA(dev_info
, &dev_info_data
, SPDRP_INSTALL_STATE
,
1520 ®_type
, (BYTE
*)&install_state
, 4, &size
))
1522 usbi_warn(ctx
, "could not detect installation state of driver for '%s': %s",
1523 dev_id_path
, windows_error_str(0));
1524 } else if (install_state
!= 0) {
1525 usbi_warn(ctx
, "driver for device '%s' is reporting an issue (code: %d) - skipping",
1526 dev_id_path
, install_state
);
1529 get_api_type(ctx
, &dev_info
, &dev_info_data
, &api
, &sub_api
);
1533 // Find parent device (for the passes that need it)
1540 // Go through the ancestors until we see a face we recognize
1542 for (ancestor
= 1; parent_dev
== NULL
; ancestor
++) {
1543 session_id
= get_ancestor_session_id(dev_info_data
.DevInst
, ancestor
);
1544 if (session_id
== 0) {
1547 parent_dev
= usbi_get_device_by_session_id(ctx
, session_id
);
1549 if (parent_dev
== NULL
) {
1550 usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path
);
1553 parent_priv
= _device_priv(parent_dev
);
1554 // virtual USB devices are also listed during GEN - don't process these yet
1555 if ( (pass
== GEN_PASS
) && (parent_priv
->apib
->id
!= USB_API_HUB
) ) {
1556 libusb_unref_device(parent_dev
);
1562 // Create new or match existing device, using the (hashed) device_id as session id
1563 if (pass
<= DEV_PASS
) { // For subsequent passes, we'll lookup the parent
1564 // These are the passes that create "new" devices
1565 session_id
= htab_hash(dev_id_path
);
1566 dev
= usbi_get_device_by_session_id(ctx
, session_id
);
1568 if (pass
== DEV_PASS
) {
1569 // This can occur if the OS only reports a newly plugged device after we started enum
1570 usbi_warn(ctx
, "'%s' was only detected in late pass (newly connected device?)"
1571 " - ignoring", dev_id_path
);
1574 usbi_dbg("allocating new device for session [%X]", session_id
);
1575 if ((dev
= usbi_alloc_device(ctx
, session_id
)) == NULL
) {
1576 LOOP_BREAK(LIBUSB_ERROR_NO_MEM
);
1578 windows_device_priv_init(dev
);
1580 usbi_dbg("found existing device for session [%X] (%d.%d)",
1581 session_id
, dev
->bus_number
, dev
->device_address
);
1583 // Keep track of devices that need unref
1584 unref_list
[unref_cur
++] = dev
;
1585 if (unref_cur
>= unref_size
) {
1587 unref_list
= usbi_reallocf(unref_list
, unref_size
*sizeof(libusb_device
*));
1588 if (unref_list
== NULL
) {
1589 usbi_err(ctx
, "could not realloc list for unref - aborting.");
1590 LOOP_BREAK(LIBUSB_ERROR_NO_MEM
);
1593 priv
= _device_priv(dev
);
1599 dev
->bus_number
= (uint8_t)(i
+ 1); // bus 0 is reserved for disconnected
1600 dev
->device_address
= 0;
1601 dev
->num_configurations
= 0;
1602 priv
->apib
= &usb_api_backend
[USB_API_HUB
];
1603 priv
->sub_api
= SUB_API_NOTSET
;
1604 priv
->depth
= UINT8_MAX
; // Overflow to 0 for HCD Hubs
1605 priv
->path
= dev_interface_path
; dev_interface_path
= NULL
;
1609 // If the device has already been setup, don't do it again
1610 if (priv
->path
!= NULL
)
1612 // Take care of API initialization
1613 priv
->path
= dev_interface_path
; dev_interface_path
= NULL
;
1614 priv
->apib
= &usb_api_backend
[api
];
1615 priv
->sub_api
= sub_api
;
1617 case USB_API_COMPOSITE
:
1621 priv
->hid
= calloc(1, sizeof(struct hid_device_priv
));
1622 if (priv
->hid
== NULL
) {
1623 LOOP_BREAK(LIBUSB_ERROR_NO_MEM
);
1625 priv
->hid
->nb_interfaces
= 0;
1628 // For other devices, the first interface is the same as the device
1629 priv
->usb_interface
[0].path
= (char*) calloc(safe_strlen(priv
->path
)+1, 1);
1630 if (priv
->usb_interface
[0].path
!= NULL
) {
1631 safe_strcpy(priv
->usb_interface
[0].path
, safe_strlen(priv
->path
)+1, priv
->path
);
1633 usbi_warn(ctx
, "could not duplicate interface path '%s'", priv
->path
);
1635 // The following is needed if we want API calls to work for both simple
1636 // and composite devices.
1637 for(j
=0; j
<USB_MAXINTERFACES
; j
++) {
1638 priv
->usb_interface
[j
].apib
= &usb_api_backend
[api
];
1644 r
= init_device(dev
, parent_dev
, (uint8_t)port_nr
, dev_id_path
, dev_info_data
.DevInst
);
1645 if (r
== LIBUSB_SUCCESS
) {
1646 // Append device to the list of discovered devices
1647 discdevs
= discovered_devs_append(*_discdevs
, dev
);
1649 LOOP_BREAK(LIBUSB_ERROR_NO_MEM
);
1651 *_discdevs
= discdevs
;
1652 } else if (r
== LIBUSB_ERROR_NO_DEVICE
) {
1653 // This can occur if the device was disconnected but Windows hasn't
1654 // refreshed its enumeration yet - in that case, we ignore the device
1658 default: // HID_PASS and later
1659 if (parent_priv
->apib
->id
== USB_API_HID
) {
1660 usbi_dbg("setting HID interface for [%lX]:", parent_dev
->session_data
);
1661 r
= set_hid_interface(ctx
, parent_dev
, dev_interface_path
);
1662 if (r
!= LIBUSB_SUCCESS
) LOOP_BREAK(r
);
1663 dev_interface_path
= NULL
;
1664 } else if (parent_priv
->apib
->id
== USB_API_COMPOSITE
) {
1665 usbi_dbg("setting composite interface for [%lX]:", parent_dev
->session_data
);
1666 switch (set_composite_interface(ctx
, parent_dev
, dev_interface_path
, dev_id_path
, api
, sub_api
)) {
1667 case LIBUSB_SUCCESS
:
1668 dev_interface_path
= NULL
;
1670 case LIBUSB_ERROR_ACCESS
:
1671 // interface has already been set => make sure dev_interface_path is freed then
1678 libusb_unref_device(parent_dev
);
1684 // Free any additional GUIDs
1685 for (pass
= HID_PASS
+1; pass
< nb_guids
; pass
++) {
1686 safe_free(guid
[pass
]);
1689 // Unref newly allocated devs
1690 for (i
=0; i
<unref_cur
; i
++) {
1691 safe_unref_device(unref_list
[i
]);
1693 safe_free(unref_list
);
1699 * exit: libusbx backend deinitialization function
1701 static void windows_exit(void)
1705 char sem_name
[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
1707 sprintf(sem_name
, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
1708 semaphore
= CreateSemaphoreA(NULL
, 1, 1, sem_name
);
1709 if (semaphore
== NULL
) {
1713 // A successful wait brings our semaphore count to 0 (unsignaled)
1714 // => any concurent wait stalls until the semaphore release
1715 if (WaitForSingleObject(semaphore
, INFINITE
) != WAIT_OBJECT_0
) {
1716 CloseHandle(semaphore
);
1720 // Only works if exits and inits are balanced exactly
1721 if (--concurrent_usage
< 0) { // Last exit
1722 for (i
=0; i
<USB_API_MAX
; i
++) {
1723 usb_api_backend
[i
].exit(SUB_API_NOTSET
);
1728 SetEvent(timer_request
[1]); // actually the signal to quit the thread.
1729 if (WAIT_OBJECT_0
!= WaitForSingleObject(timer_thread
, INFINITE
)) {
1730 usbi_dbg("could not wait for timer thread to quit");
1731 TerminateThread(timer_thread
, 1);
1733 CloseHandle(timer_thread
);
1734 timer_thread
= NULL
;
1736 for (i
= 0; i
< 2; i
++) {
1737 if (timer_request
[i
]) {
1738 CloseHandle(timer_request
[i
]);
1739 timer_request
[i
] = NULL
;
1742 if (timer_response
) {
1743 CloseHandle(timer_response
);
1744 timer_response
= NULL
;
1747 CloseHandle(timer_mutex
);
1753 ReleaseSemaphore(semaphore
, 1, NULL
); // increase count back to 1
1754 CloseHandle(semaphore
);
1757 static int windows_get_device_descriptor(struct libusb_device
*dev
, unsigned char *buffer
, int *host_endian
)
1759 struct windows_device_priv
*priv
= _device_priv(dev
);
1761 memcpy(buffer
, &(priv
->dev_descriptor
), DEVICE_DESC_LENGTH
);
1764 return LIBUSB_SUCCESS
;
1767 static int windows_get_config_descriptor(struct libusb_device
*dev
, uint8_t config_index
, unsigned char *buffer
, size_t len
, int *host_endian
)
1769 struct windows_device_priv
*priv
= _device_priv(dev
);
1770 PUSB_CONFIGURATION_DESCRIPTOR config_header
;
1773 // config index is zero based
1774 if (config_index
>= dev
->num_configurations
)
1775 return LIBUSB_ERROR_INVALID_PARAM
;
1777 if ((priv
->config_descriptor
== NULL
) || (priv
->config_descriptor
[config_index
] == NULL
))
1778 return LIBUSB_ERROR_NOT_FOUND
;
1780 config_header
= (PUSB_CONFIGURATION_DESCRIPTOR
)priv
->config_descriptor
[config_index
];
1782 size
= min(config_header
->wTotalLength
, len
);
1783 memcpy(buffer
, priv
->config_descriptor
[config_index
], size
);
1790 * return the cached copy of the active config descriptor
1792 static int windows_get_active_config_descriptor(struct libusb_device
*dev
, unsigned char *buffer
, size_t len
, int *host_endian
)
1794 struct windows_device_priv
*priv
= _device_priv(dev
);
1796 if (priv
->active_config
== 0)
1797 return LIBUSB_ERROR_NOT_FOUND
;
1799 // config index is zero based
1800 return windows_get_config_descriptor(dev
, (uint8_t)(priv
->active_config
-1), buffer
, len
, host_endian
);
1803 static int windows_open(struct libusb_device_handle
*dev_handle
)
1805 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1806 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
1808 if (priv
->apib
== NULL
) {
1809 usbi_err(ctx
, "program assertion failed - device is not initialized");
1810 return LIBUSB_ERROR_NO_DEVICE
;
1813 return priv
->apib
->open(SUB_API_NOTSET
, dev_handle
);
1816 static void windows_close(struct libusb_device_handle
*dev_handle
)
1818 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1820 priv
->apib
->close(SUB_API_NOTSET
, dev_handle
);
1823 static int windows_get_configuration(struct libusb_device_handle
*dev_handle
, int *config
)
1825 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1827 if (priv
->active_config
== 0) {
1829 return LIBUSB_ERROR_NOT_FOUND
;
1832 *config
= priv
->active_config
;
1833 return LIBUSB_SUCCESS
;
1837 * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver
1838 * does not currently expose a service that allows higher-level drivers to set
1839 * the configuration."
1841 static int windows_set_configuration(struct libusb_device_handle
*dev_handle
, int config
)
1843 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1844 int r
= LIBUSB_SUCCESS
;
1846 if (config
>= USB_MAXCONFIG
)
1847 return LIBUSB_ERROR_INVALID_PARAM
;
1849 r
= libusb_control_transfer(dev_handle
, LIBUSB_ENDPOINT_OUT
|
1850 LIBUSB_REQUEST_TYPE_STANDARD
| LIBUSB_RECIPIENT_DEVICE
,
1851 LIBUSB_REQUEST_SET_CONFIGURATION
, (uint16_t)config
,
1854 if (r
== LIBUSB_SUCCESS
) {
1855 priv
->active_config
= (uint8_t)config
;
1860 static int windows_claim_interface(struct libusb_device_handle
*dev_handle
, int iface
)
1862 int r
= LIBUSB_SUCCESS
;
1863 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1865 if (iface
>= USB_MAXINTERFACES
)
1866 return LIBUSB_ERROR_INVALID_PARAM
;
1868 safe_free(priv
->usb_interface
[iface
].endpoint
);
1869 priv
->usb_interface
[iface
].nb_endpoints
= 0;
1871 r
= priv
->apib
->claim_interface(SUB_API_NOTSET
, dev_handle
, iface
);
1873 if (r
== LIBUSB_SUCCESS
) {
1874 r
= windows_assign_endpoints(dev_handle
, iface
, 0);
1880 static int windows_set_interface_altsetting(struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
)
1882 int r
= LIBUSB_SUCCESS
;
1883 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1885 safe_free(priv
->usb_interface
[iface
].endpoint
);
1886 priv
->usb_interface
[iface
].nb_endpoints
= 0;
1888 r
= priv
->apib
->set_interface_altsetting(SUB_API_NOTSET
, dev_handle
, iface
, altsetting
);
1890 if (r
== LIBUSB_SUCCESS
) {
1891 r
= windows_assign_endpoints(dev_handle
, iface
, altsetting
);
1897 static int windows_release_interface(struct libusb_device_handle
*dev_handle
, int iface
)
1899 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1901 return priv
->apib
->release_interface(SUB_API_NOTSET
, dev_handle
, iface
);
1904 static int windows_clear_halt(struct libusb_device_handle
*dev_handle
, unsigned char endpoint
)
1906 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1907 return priv
->apib
->clear_halt(SUB_API_NOTSET
, dev_handle
, endpoint
);
1910 static int windows_reset_device(struct libusb_device_handle
*dev_handle
)
1912 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
1913 return priv
->apib
->reset_device(SUB_API_NOTSET
, dev_handle
);
1916 // The 3 functions below are unlikely to ever get supported on Windows
1917 static int windows_kernel_driver_active(struct libusb_device_handle
*dev_handle
, int iface
)
1919 return LIBUSB_ERROR_NOT_SUPPORTED
;
1922 static int windows_attach_kernel_driver(struct libusb_device_handle
*dev_handle
, int iface
)
1924 return LIBUSB_ERROR_NOT_SUPPORTED
;
1927 static int windows_detach_kernel_driver(struct libusb_device_handle
*dev_handle
, int iface
)
1929 return LIBUSB_ERROR_NOT_SUPPORTED
;
1932 static void windows_destroy_device(struct libusb_device
*dev
)
1934 windows_device_priv_release(dev
);
1937 static void windows_clear_transfer_priv(struct usbi_transfer
*itransfer
)
1939 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
1941 usbi_free_fd(&transfer_priv
->pollable_fd
);
1942 safe_free(transfer_priv
->hid_buffer
);
1943 // When auto claim is in use, attempt to release the auto-claimed interface
1944 auto_release(itransfer
);
1947 static int submit_bulk_transfer(struct usbi_transfer
*itransfer
)
1949 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
1950 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
1951 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
1952 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
1955 r
= priv
->apib
->submit_bulk_transfer(SUB_API_NOTSET
, itransfer
);
1956 if (r
!= LIBUSB_SUCCESS
) {
1960 usbi_add_pollfd(ctx
, transfer_priv
->pollable_fd
.fd
,
1961 (short)(IS_XFERIN(transfer
) ? POLLIN
: POLLOUT
));
1963 itransfer
->flags
|= USBI_TRANSFER_UPDATED_FDS
;
1964 return LIBUSB_SUCCESS
;
1967 static int submit_iso_transfer(struct usbi_transfer
*itransfer
)
1969 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
1970 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
1971 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
1972 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
1975 r
= priv
->apib
->submit_iso_transfer(SUB_API_NOTSET
, itransfer
);
1976 if (r
!= LIBUSB_SUCCESS
) {
1980 usbi_add_pollfd(ctx
, transfer_priv
->pollable_fd
.fd
,
1981 (short)(IS_XFERIN(transfer
) ? POLLIN
: POLLOUT
));
1983 itransfer
->flags
|= USBI_TRANSFER_UPDATED_FDS
;
1984 return LIBUSB_SUCCESS
;
1987 static int submit_control_transfer(struct usbi_transfer
*itransfer
)
1989 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
1990 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
1991 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
1992 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
1995 r
= priv
->apib
->submit_control_transfer(SUB_API_NOTSET
, itransfer
);
1996 if (r
!= LIBUSB_SUCCESS
) {
2000 usbi_add_pollfd(ctx
, transfer_priv
->pollable_fd
.fd
, POLLIN
);
2002 itransfer
->flags
|= USBI_TRANSFER_UPDATED_FDS
;
2003 return LIBUSB_SUCCESS
;
2007 static int windows_submit_transfer(struct usbi_transfer
*itransfer
)
2009 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2011 switch (transfer
->type
) {
2012 case LIBUSB_TRANSFER_TYPE_CONTROL
:
2013 return submit_control_transfer(itransfer
);
2014 case LIBUSB_TRANSFER_TYPE_BULK
:
2015 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
2016 if (IS_XFEROUT(transfer
) &&
2017 transfer
->flags
& LIBUSB_TRANSFER_ADD_ZERO_PACKET
)
2018 return LIBUSB_ERROR_NOT_SUPPORTED
;
2019 return submit_bulk_transfer(itransfer
);
2020 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
2021 return submit_iso_transfer(itransfer
);
2023 usbi_err(TRANSFER_CTX(transfer
), "unknown endpoint type %d", transfer
->type
);
2024 return LIBUSB_ERROR_INVALID_PARAM
;
2028 static int windows_abort_control(struct usbi_transfer
*itransfer
)
2030 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2031 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
2033 return priv
->apib
->abort_control(SUB_API_NOTSET
, itransfer
);
2036 static int windows_abort_transfers(struct usbi_transfer
*itransfer
)
2038 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2039 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
2041 return priv
->apib
->abort_transfers(SUB_API_NOTSET
, itransfer
);
2044 static int windows_cancel_transfer(struct usbi_transfer
*itransfer
)
2046 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2048 switch (transfer
->type
) {
2049 case LIBUSB_TRANSFER_TYPE_CONTROL
:
2050 return windows_abort_control(itransfer
);
2051 case LIBUSB_TRANSFER_TYPE_BULK
:
2052 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
2053 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
2054 return windows_abort_transfers(itransfer
);
2056 usbi_err(ITRANSFER_CTX(itransfer
), "unknown endpoint type %d", transfer
->type
);
2057 return LIBUSB_ERROR_INVALID_PARAM
;
2061 static void windows_transfer_callback(struct usbi_transfer
*itransfer
, uint32_t io_result
, uint32_t io_size
)
2063 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2064 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
2065 int status
, istatus
;
2067 usbi_dbg("handling I/O completion with errcode %d, size %d", io_result
, io_size
);
2071 status
= priv
->apib
->copy_transfer_data(SUB_API_NOTSET
, itransfer
, io_size
);
2073 case ERROR_GEN_FAILURE
:
2074 usbi_dbg("detected endpoint stall");
2075 status
= LIBUSB_TRANSFER_STALL
;
2077 case ERROR_SEM_TIMEOUT
:
2078 usbi_dbg("detected semaphore timeout");
2079 status
= LIBUSB_TRANSFER_TIMED_OUT
;
2081 case ERROR_OPERATION_ABORTED
:
2082 istatus
= priv
->apib
->copy_transfer_data(SUB_API_NOTSET
, itransfer
, io_size
);
2083 if (istatus
!= LIBUSB_TRANSFER_COMPLETED
) {
2084 usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus
);
2086 if (itransfer
->flags
& USBI_TRANSFER_TIMED_OUT
) {
2087 usbi_dbg("detected timeout");
2088 status
= LIBUSB_TRANSFER_TIMED_OUT
;
2090 usbi_dbg("detected operation aborted");
2091 status
= LIBUSB_TRANSFER_CANCELLED
;
2095 usbi_err(ITRANSFER_CTX(itransfer
), "detected I/O error %d: %s", io_result
, windows_error_str(io_result
));
2096 status
= LIBUSB_TRANSFER_ERROR
;
2099 windows_clear_transfer_priv(itransfer
); // Cancel polling
2100 usbi_handle_transfer_completion(itransfer
, (enum libusb_transfer_status
)status
);
2103 static void windows_handle_callback (struct usbi_transfer
*itransfer
, uint32_t io_result
, uint32_t io_size
)
2105 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2107 switch (transfer
->type
) {
2108 case LIBUSB_TRANSFER_TYPE_CONTROL
:
2109 case LIBUSB_TRANSFER_TYPE_BULK
:
2110 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
2111 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
2112 windows_transfer_callback (itransfer
, io_result
, io_size
);
2115 usbi_err(ITRANSFER_CTX(itransfer
), "unknown endpoint type %d", transfer
->type
);
2119 static int windows_handle_events(struct libusb_context
*ctx
, struct pollfd
*fds
, POLL_NFDS_TYPE nfds
, int num_ready
)
2121 struct windows_transfer_priv
* transfer_priv
= NULL
;
2122 POLL_NFDS_TYPE i
= 0;
2124 struct usbi_transfer
*transfer
;
2125 DWORD io_size
, io_result
;
2127 usbi_mutex_lock(&ctx
->open_devs_lock
);
2128 for (i
= 0; i
< nfds
&& num_ready
> 0; i
++) {
2130 usbi_dbg("checking fd %d with revents = %04x", fds
[i
].fd
, fds
[i
].revents
);
2132 if (!fds
[i
].revents
) {
2138 // Because a Windows OVERLAPPED is used for poll emulation,
2139 // a pollable fd is created and stored with each transfer
2140 usbi_mutex_lock(&ctx
->flying_transfers_lock
);
2141 list_for_each_entry(transfer
, &ctx
->flying_transfers
, list
, struct usbi_transfer
) {
2142 transfer_priv
= usbi_transfer_get_os_priv(transfer
);
2143 if (transfer_priv
->pollable_fd
.fd
== fds
[i
].fd
) {
2148 usbi_mutex_unlock(&ctx
->flying_transfers_lock
);
2151 // Handle async requests that completed synchronously first
2152 if (HasOverlappedIoCompletedSync(transfer_priv
->pollable_fd
.overlapped
)) {
2153 io_result
= NO_ERROR
;
2154 io_size
= (DWORD
)transfer_priv
->pollable_fd
.overlapped
->InternalHigh
;
2155 // Regular async overlapped
2156 } else if (GetOverlappedResult(transfer_priv
->pollable_fd
.handle
,
2157 transfer_priv
->pollable_fd
.overlapped
, &io_size
, false)) {
2158 io_result
= NO_ERROR
;
2160 io_result
= GetLastError();
2162 usbi_remove_pollfd(ctx
, transfer_priv
->pollable_fd
.fd
);
2163 // let handle_callback free the event using the transfer wfd
2164 // If you don't use the transfer wfd, you run a risk of trying to free a
2165 // newly allocated wfd that took the place of the one from the transfer.
2166 windows_handle_callback(transfer
, io_result
, io_size
);
2168 usbi_err(ctx
, "could not find a matching transfer for fd %x", fds
[i
]);
2169 return LIBUSB_ERROR_NOT_FOUND
;
2173 usbi_mutex_unlock(&ctx
->open_devs_lock
);
2174 return LIBUSB_SUCCESS
;
2178 * Monotonic and real time functions
2180 unsigned __stdcall
windows_clock_gettime_threaded(void* param
)
2182 LARGE_INTEGER hires_counter
, li_frequency
;
2186 // Init - find out if we have access to a monotonic (hires) timer
2187 if (!QueryPerformanceFrequency(&li_frequency
)) {
2188 usbi_dbg("no hires timer available on this platform");
2189 hires_frequency
= 0;
2190 hires_ticks_to_ps
= UINT64_C(0);
2192 hires_frequency
= li_frequency
.QuadPart
;
2193 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
2194 // to picoseconds to compute the tv_nsecs part in clock_gettime
2195 hires_ticks_to_ps
= UINT64_C(1000000000000) / hires_frequency
;
2196 usbi_dbg("hires timer available (Frequency: %"PRIu64
" Hz)", hires_frequency
);
2199 // Signal windows_init() that we're ready to service requests
2200 if (ReleaseSemaphore(timer_response
, 1, NULL
) == 0) {
2201 usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
2204 // Main loop - wait for requests
2206 timer_index
= WaitForMultipleObjects(2, timer_request
, FALSE
, INFINITE
) - WAIT_OBJECT_0
;
2207 if ( (timer_index
!= 0) && (timer_index
!= 1) ) {
2208 usbi_dbg("failure to wait on requests: %s", windows_error_str(0));
2211 if (request_count
[timer_index
] == 0) {
2212 // Request already handled
2213 ResetEvent(timer_request
[timer_index
]);
2214 // There's still a possiblity that a thread sends a request between the
2215 // time we test request_count[] == 0 and we reset the event, in which case
2216 // the request would be ignored. The simple solution to that is to test
2217 // request_count again and process requests if non zero.
2218 if (request_count
[timer_index
] == 0)
2221 switch (timer_index
) {
2223 WaitForSingleObject(timer_mutex
, INFINITE
);
2224 // Requests to this thread are for hires always
2225 if (QueryPerformanceCounter(&hires_counter
) != 0) {
2226 timer_tp
.tv_sec
= (long)(hires_counter
.QuadPart
/ hires_frequency
);
2227 timer_tp
.tv_nsec
= (long)(((hires_counter
.QuadPart
% hires_frequency
)/1000) * hires_ticks_to_ps
);
2229 // Fallback to real-time if we can't get monotonic value
2230 // Note that real-time clock does not wait on the mutex or this thread.
2231 windows_clock_gettime(USBI_CLOCK_REALTIME
, &timer_tp
);
2233 ReleaseMutex(timer_mutex
);
2235 nb_responses
= InterlockedExchange((LONG
*)&request_count
[0], 0);
2237 && (ReleaseSemaphore(timer_response
, nb_responses
, NULL
) == 0) ) {
2238 usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
2241 case 1: // time to quit
2242 usbi_dbg("timer thread quitting");
2248 static int windows_clock_gettime(int clk_id
, struct timespec
*tp
)
2251 ULARGE_INTEGER rtime
;
2254 case USBI_CLOCK_MONOTONIC
:
2255 if (hires_frequency
!= 0) {
2257 InterlockedIncrement((LONG
*)&request_count
[0]);
2258 SetEvent(timer_request
[0]);
2259 r
= WaitForSingleObject(timer_response
, TIMER_REQUEST_RETRY_MS
);
2262 WaitForSingleObject(timer_mutex
, INFINITE
);
2264 ReleaseMutex(timer_mutex
);
2265 return LIBUSB_SUCCESS
;
2267 usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
2268 break; // Retry until successful
2270 usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0));
2271 return LIBUSB_ERROR_OTHER
;
2275 // Fall through and return real-time if monotonic was not detected @ timer init
2276 case USBI_CLOCK_REALTIME
:
2277 // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
2278 // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
2279 // Note however that our resolution is bounded by the Windows system time
2280 // functions and is at best of the order of 1 ms (or, usually, worse)
2281 GetSystemTimeAsFileTime(&filetime
);
2282 rtime
.LowPart
= filetime
.dwLowDateTime
;
2283 rtime
.HighPart
= filetime
.dwHighDateTime
;
2284 rtime
.QuadPart
-= epoch_time
;
2285 tp
->tv_sec
= (long)(rtime
.QuadPart
/ 10000000);
2286 tp
->tv_nsec
= (long)((rtime
.QuadPart
% 10000000)*100);
2287 return LIBUSB_SUCCESS
;
2289 return LIBUSB_ERROR_INVALID_PARAM
;
2294 // NB: MSVC6 does not support named initializers.
2295 const struct usbi_os_backend windows_backend
= {
2297 USBI_CAP_HAS_HID_ACCESS
,
2301 windows_get_device_list
,
2302 NULL
, /* hotplug_poll */
2306 windows_get_device_descriptor
,
2307 windows_get_active_config_descriptor
,
2308 windows_get_config_descriptor
,
2309 NULL
, /* get_config_descriptor_by_value() */
2311 windows_get_configuration
,
2312 windows_set_configuration
,
2313 windows_claim_interface
,
2314 windows_release_interface
,
2316 windows_set_interface_altsetting
,
2318 windows_reset_device
,
2320 windows_kernel_driver_active
,
2321 windows_detach_kernel_driver
,
2322 windows_attach_kernel_driver
,
2324 windows_destroy_device
,
2326 windows_submit_transfer
,
2327 windows_cancel_transfer
,
2328 windows_clear_transfer_priv
,
2330 windows_handle_events
,
2332 windows_clock_gettime
,
2333 #if defined(USBI_TIMERFD_AVAILABLE)
2336 sizeof(struct windows_device_priv
),
2337 sizeof(struct windows_device_handle_priv
),
2338 sizeof(struct windows_transfer_priv
),
2346 static int unsupported_init(int sub_api
, struct libusb_context
*ctx
) {
2347 return LIBUSB_SUCCESS
;
2349 static int unsupported_exit(int sub_api
) {
2350 return LIBUSB_SUCCESS
;
2352 static int unsupported_open(int sub_api
, struct libusb_device_handle
*dev_handle
) {
2353 PRINT_UNSUPPORTED_API(open
);
2355 static void unsupported_close(int sub_api
, struct libusb_device_handle
*dev_handle
) {
2356 usbi_dbg("unsupported API call for 'close'");
2358 static int unsupported_configure_endpoints(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
) {
2359 PRINT_UNSUPPORTED_API(configure_endpoints
);
2361 static int unsupported_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
) {
2362 PRINT_UNSUPPORTED_API(claim_interface
);
2364 static int unsupported_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
) {
2365 PRINT_UNSUPPORTED_API(set_interface_altsetting
);
2367 static int unsupported_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
) {
2368 PRINT_UNSUPPORTED_API(release_interface
);
2370 static int unsupported_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
) {
2371 PRINT_UNSUPPORTED_API(clear_halt
);
2373 static int unsupported_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
) {
2374 PRINT_UNSUPPORTED_API(reset_device
);
2376 static int unsupported_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
) {
2377 PRINT_UNSUPPORTED_API(submit_bulk_transfer
);
2379 static int unsupported_submit_iso_transfer(int sub_api
, struct usbi_transfer
*itransfer
) {
2380 PRINT_UNSUPPORTED_API(submit_iso_transfer
);
2382 static int unsupported_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
) {
2383 PRINT_UNSUPPORTED_API(submit_control_transfer
);
2385 static int unsupported_abort_control(int sub_api
, struct usbi_transfer
*itransfer
) {
2386 PRINT_UNSUPPORTED_API(abort_control
);
2388 static int unsupported_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
) {
2389 PRINT_UNSUPPORTED_API(abort_transfers
);
2391 static int unsupported_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
) {
2392 PRINT_UNSUPPORTED_API(copy_transfer_data
);
2394 static int common_configure_endpoints(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
) {
2395 return LIBUSB_SUCCESS
;
2397 // These names must be uppercase
2398 const char* hub_driver_names
[] = {"USBHUB", "USBHUB3", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB"};
2399 const char* composite_driver_names
[] = {"USBCCGP"};
2400 const char* winusbx_driver_names
[] = WINUSBX_DRV_NAMES
;
2401 const char* hid_driver_names
[] = {"HIDUSB", "MOUHID", "KBDHID"};
2402 const struct windows_usb_api_backend usb_api_backend
[USB_API_MAX
] = {
2404 USB_API_UNSUPPORTED
,
2412 unsupported_configure_endpoints
,
2413 unsupported_claim_interface
,
2414 unsupported_set_interface_altsetting
,
2415 unsupported_release_interface
,
2416 unsupported_clear_halt
,
2417 unsupported_reset_device
,
2418 unsupported_submit_bulk_transfer
,
2419 unsupported_submit_iso_transfer
,
2420 unsupported_submit_control_transfer
,
2421 unsupported_abort_control
,
2422 unsupported_abort_transfers
,
2423 unsupported_copy_transfer_data
,
2428 ARRAYSIZE(hub_driver_names
),
2433 unsupported_configure_endpoints
,
2434 unsupported_claim_interface
,
2435 unsupported_set_interface_altsetting
,
2436 unsupported_release_interface
,
2437 unsupported_clear_halt
,
2438 unsupported_reset_device
,
2439 unsupported_submit_bulk_transfer
,
2440 unsupported_submit_iso_transfer
,
2441 unsupported_submit_control_transfer
,
2442 unsupported_abort_control
,
2443 unsupported_abort_transfers
,
2444 unsupported_copy_transfer_data
,
2448 composite_driver_names
,
2449 ARRAYSIZE(composite_driver_names
),
2454 common_configure_endpoints
,
2455 composite_claim_interface
,
2456 composite_set_interface_altsetting
,
2457 composite_release_interface
,
2458 composite_clear_halt
,
2459 composite_reset_device
,
2460 composite_submit_bulk_transfer
,
2461 composite_submit_iso_transfer
,
2462 composite_submit_control_transfer
,
2463 composite_abort_control
,
2464 composite_abort_transfers
,
2465 composite_copy_transfer_data
,
2469 winusbx_driver_names
,
2470 ARRAYSIZE(winusbx_driver_names
),
2475 winusbx_configure_endpoints
,
2476 winusbx_claim_interface
,
2477 winusbx_set_interface_altsetting
,
2478 winusbx_release_interface
,
2480 winusbx_reset_device
,
2481 winusbx_submit_bulk_transfer
,
2482 unsupported_submit_iso_transfer
,
2483 winusbx_submit_control_transfer
,
2484 winusbx_abort_control
,
2485 winusbx_abort_transfers
,
2486 winusbx_copy_transfer_data
,
2491 ARRAYSIZE(hid_driver_names
),
2496 common_configure_endpoints
,
2497 hid_claim_interface
,
2498 hid_set_interface_altsetting
,
2499 hid_release_interface
,
2502 hid_submit_bulk_transfer
,
2503 unsupported_submit_iso_transfer
,
2504 hid_submit_control_transfer
,
2505 hid_abort_transfers
,
2506 hid_abort_transfers
,
2507 hid_copy_transfer_data
,
2513 * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
2515 #define WinUSBX_Set(fn) do { if (native_winusb) WinUSBX[i].fn = (WinUsb_##fn##_t) GetProcAddress(h, "WinUsb_" #fn); \
2516 else pLibK_GetProcAddress((PVOID*)&WinUSBX[i].fn, i, KUSB_FNID_##fn); } while (0)
2518 static int winusbx_init(int sub_api
, struct libusb_context
*ctx
)
2521 bool native_winusb
= false;
2523 KLIB_VERSION LibK_Version
;
2524 LibK_GetProcAddress_t pLibK_GetProcAddress
= NULL
;
2525 LibK_GetVersion_t pLibK_GetVersion
= NULL
;
2527 h
= GetModuleHandleA("libusbK");
2529 h
= LoadLibraryA("libusbK");
2532 usbi_info(ctx
, "libusbK DLL is not available, will use native WinUSB");
2533 h
= GetModuleHandleA("WinUSB");
2535 h
= LoadLibraryA("WinUSB");
2537 usbi_warn(ctx
, "WinUSB DLL is not available either,\n"
2538 "you will not be able to access devices outside of enumeration");
2539 return LIBUSB_ERROR_NOT_FOUND
;
2542 usbi_dbg("using libusbK DLL for universal access");
2543 pLibK_GetVersion
= (LibK_GetVersion_t
) GetProcAddress(h
, "LibK_GetVersion");
2544 if (pLibK_GetVersion
!= NULL
) {
2545 pLibK_GetVersion(&LibK_Version
);
2546 usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version
.Major
, LibK_Version
.Minor
,
2547 LibK_Version
.Micro
, LibK_Version
.Nano
);
2549 pLibK_GetProcAddress
= (LibK_GetProcAddress_t
) GetProcAddress(h
, "LibK_GetProcAddress");
2550 if (pLibK_GetProcAddress
== NULL
) {
2551 usbi_err(ctx
, "LibK_GetProcAddress() not found in libusbK DLL");
2552 return LIBUSB_ERROR_NOT_FOUND
;
2555 native_winusb
= (pLibK_GetProcAddress
== NULL
);
2556 for (i
=SUB_API_LIBUSBK
; i
<SUB_API_MAX
; i
++) {
2557 WinUSBX_Set(AbortPipe
);
2558 WinUSBX_Set(ControlTransfer
);
2559 WinUSBX_Set(FlushPipe
);
2561 WinUSBX_Set(GetAssociatedInterface
);
2562 WinUSBX_Set(GetCurrentAlternateSetting
);
2563 WinUSBX_Set(GetDescriptor
);
2564 WinUSBX_Set(GetOverlappedResult
);
2565 WinUSBX_Set(GetPipePolicy
);
2566 WinUSBX_Set(GetPowerPolicy
);
2567 WinUSBX_Set(Initialize
);
2568 WinUSBX_Set(QueryDeviceInformation
);
2569 WinUSBX_Set(QueryInterfaceSettings
);
2570 WinUSBX_Set(QueryPipe
);
2571 WinUSBX_Set(ReadPipe
);
2572 WinUSBX_Set(ResetPipe
);
2573 WinUSBX_Set(SetCurrentAlternateSetting
);
2574 WinUSBX_Set(SetPipePolicy
);
2575 WinUSBX_Set(SetPowerPolicy
);
2576 WinUSBX_Set(WritePipe
);
2577 if (!native_winusb
) {
2578 WinUSBX_Set(ResetDevice
);
2580 if (WinUSBX
[i
].Initialize
!= NULL
) {
2581 WinUSBX
[i
].initialized
= true;
2582 usbi_dbg("initalized sub API %s", sub_api_name
[i
]);
2584 usbi_warn(ctx
, "Failed to initalize sub API %s", sub_api_name
[i
]);
2585 WinUSBX
[i
].initialized
= false;
2588 return LIBUSB_SUCCESS
;
2591 static int winusbx_exit(int sub_api
)
2593 return LIBUSB_SUCCESS
;
2596 // NB: open and close must ensure that they only handle interface of
2597 // the right API type, as these functions can be called wholesale from
2598 // composite_open(), with interfaces belonging to different APIs
2599 static int winusbx_open(int sub_api
, struct libusb_device_handle
*dev_handle
)
2601 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
2602 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2603 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2608 CHECK_WINUSBX_AVAILABLE(sub_api
);
2610 // WinUSB requires a seperate handle for each interface
2611 for (i
= 0; i
< USB_MAXINTERFACES
; i
++) {
2612 if ( (priv
->usb_interface
[i
].path
!= NULL
)
2613 && (priv
->usb_interface
[i
].apib
->id
== USB_API_WINUSBX
) ) {
2614 file_handle
= CreateFileA(priv
->usb_interface
[i
].path
, GENERIC_WRITE
| GENERIC_READ
, FILE_SHARE_WRITE
| FILE_SHARE_READ
,
2615 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
2616 if (file_handle
== INVALID_HANDLE_VALUE
) {
2617 usbi_err(ctx
, "could not open device %s (interface %d): %s", priv
->usb_interface
[i
].path
, i
, windows_error_str(0));
2618 switch(GetLastError()) {
2619 case ERROR_FILE_NOT_FOUND
: // The device was disconnected
2620 return LIBUSB_ERROR_NO_DEVICE
;
2621 case ERROR_ACCESS_DENIED
:
2622 return LIBUSB_ERROR_ACCESS
;
2624 return LIBUSB_ERROR_IO
;
2627 handle_priv
->interface_handle
[i
].dev_handle
= file_handle
;
2631 return LIBUSB_SUCCESS
;
2634 static void winusbx_close(int sub_api
, struct libusb_device_handle
*dev_handle
)
2636 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2637 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2641 if (sub_api
== SUB_API_NOTSET
)
2642 sub_api
= priv
->sub_api
;
2643 if (!WinUSBX
[sub_api
].initialized
)
2646 for (i
= 0; i
< USB_MAXINTERFACES
; i
++) {
2647 if (priv
->usb_interface
[i
].apib
->id
== USB_API_WINUSBX
) {
2648 file_handle
= handle_priv
->interface_handle
[i
].dev_handle
;
2649 if ( (file_handle
!= 0) && (file_handle
!= INVALID_HANDLE_VALUE
)) {
2650 CloseHandle(file_handle
);
2656 static int winusbx_configure_endpoints(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
2658 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2659 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2660 HANDLE winusb_handle
= handle_priv
->interface_handle
[iface
].api_handle
;
2663 uint8_t endpoint_address
;
2666 CHECK_WINUSBX_AVAILABLE(sub_api
);
2668 // With handle and enpoints set (in parent), we can setup the default pipe properties
2669 // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
2670 for (i
=-1; i
<priv
->usb_interface
[iface
].nb_endpoints
; i
++) {
2671 endpoint_address
=(i
==-1)?0:priv
->usb_interface
[iface
].endpoint
[i
];
2672 if (!WinUSBX
[sub_api
].SetPipePolicy(winusb_handle
, endpoint_address
,
2673 PIPE_TRANSFER_TIMEOUT
, sizeof(ULONG
), &timeout
)) {
2674 usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address
);
2676 if ((i
== -1) || (sub_api
== SUB_API_LIBUSB0
)) {
2677 continue; // Other policies don't apply to control endpoint or libusb0
2680 if (!WinUSBX
[sub_api
].SetPipePolicy(winusb_handle
, endpoint_address
,
2681 SHORT_PACKET_TERMINATE
, sizeof(UCHAR
), &policy
)) {
2682 usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address
);
2684 if (!WinUSBX
[sub_api
].SetPipePolicy(winusb_handle
, endpoint_address
,
2685 IGNORE_SHORT_PACKETS
, sizeof(UCHAR
), &policy
)) {
2686 usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address
);
2689 /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
2690 https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
2691 if (!WinUSBX
[sub_api
].SetPipePolicy(winusb_handle
, endpoint_address
,
2692 ALLOW_PARTIAL_READS
, sizeof(UCHAR
), &policy
)) {
2693 usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address
);
2695 if (!WinUSBX
[sub_api
].SetPipePolicy(winusb_handle
, endpoint_address
,
2696 AUTO_CLEAR_STALL
, sizeof(UCHAR
), &policy
)) {
2697 usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address
);
2701 return LIBUSB_SUCCESS
;
2704 static int winusbx_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
2706 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
2707 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2708 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2709 bool is_using_usbccgp
= (priv
->apib
->id
== USB_API_COMPOSITE
);
2710 HANDLE file_handle
, winusb_handle
;
2713 SP_DEVICE_INTERFACE_DETAIL_DATA_A
*dev_interface_details
= NULL
;
2714 HDEVINFO dev_info
= INVALID_HANDLE_VALUE
;
2715 SP_DEVINFO_DATA dev_info_data
;
2716 char* dev_path_no_guid
= NULL
;
2717 char filter_path
[] = "\\\\.\\libusb0-0000";
2718 bool found_filter
= false;
2720 CHECK_WINUSBX_AVAILABLE(sub_api
);
2722 // If the device is composite, but using the default Windows composite parent driver (usbccgp)
2723 // or if it's the first WinUSB-like interface, we get a handle through Initialize().
2724 if ((is_using_usbccgp
) || (iface
== 0)) {
2725 // composite device (independent interfaces) or interface 0
2726 file_handle
= handle_priv
->interface_handle
[iface
].dev_handle
;
2727 if ((file_handle
== 0) || (file_handle
== INVALID_HANDLE_VALUE
)) {
2728 return LIBUSB_ERROR_NOT_FOUND
;
2731 if (!WinUSBX
[sub_api
].Initialize(file_handle
, &winusb_handle
)) {
2732 handle_priv
->interface_handle
[iface
].api_handle
= INVALID_HANDLE_VALUE
;
2733 err
= GetLastError();
2735 case ERROR_BAD_COMMAND
:
2736 // The device was disconnected
2737 usbi_err(ctx
, "could not access interface %d: %s", iface
, windows_error_str(0));
2738 return LIBUSB_ERROR_NO_DEVICE
;
2740 // it may be that we're using the libusb0 filter driver.
2741 // TODO: can we move this whole business into the K/0 DLL?
2742 for (i
= 0; ; i
++) {
2743 safe_free(dev_interface_details
);
2744 safe_free(dev_path_no_guid
);
2745 dev_interface_details
= get_interface_details_filter(ctx
, &dev_info
, &dev_info_data
, &GUID_DEVINTERFACE_LIBUSB0_FILTER
, i
, filter_path
);
2746 if ((found_filter
) || (dev_interface_details
== NULL
)) {
2750 dev_path_no_guid
= sanitize_path(strtok(dev_interface_details
->DevicePath
, "{"));
2751 if (safe_strncmp(dev_path_no_guid
, priv
->usb_interface
[iface
].path
, safe_strlen(dev_path_no_guid
)) == 0) {
2752 file_handle
= CreateFileA(filter_path
, GENERIC_WRITE
| GENERIC_READ
, FILE_SHARE_WRITE
| FILE_SHARE_READ
,
2753 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
2754 if (file_handle
== INVALID_HANDLE_VALUE
) {
2755 usbi_err(ctx
, "could not open device %s: %s", filter_path
, windows_error_str(0));
2757 WinUSBX
[sub_api
].Free(winusb_handle
);
2758 if (!WinUSBX
[sub_api
].Initialize(file_handle
, &winusb_handle
)) {
2761 found_filter
= true;
2766 if (!found_filter
) {
2767 usbi_err(ctx
, "could not access interface %d: %s", iface
, windows_error_str(err
));
2768 return LIBUSB_ERROR_ACCESS
;
2772 handle_priv
->interface_handle
[iface
].api_handle
= winusb_handle
;
2774 // For all other interfaces, use GetAssociatedInterface()
2775 winusb_handle
= handle_priv
->interface_handle
[0].api_handle
;
2776 // It is a requirement for multiple interface devices on Windows that, to you
2777 // must first claim the first interface before you claim the others
2778 if ((winusb_handle
== 0) || (winusb_handle
== INVALID_HANDLE_VALUE
)) {
2779 file_handle
= handle_priv
->interface_handle
[0].dev_handle
;
2780 if (WinUSBX
[sub_api
].Initialize(file_handle
, &winusb_handle
)) {
2781 handle_priv
->interface_handle
[0].api_handle
= winusb_handle
;
2782 usbi_warn(ctx
, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface
);
2784 usbi_warn(ctx
, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface
, windows_error_str(0));
2785 return LIBUSB_ERROR_ACCESS
;
2788 if (!WinUSBX
[sub_api
].GetAssociatedInterface(winusb_handle
, (UCHAR
)(iface
-1),
2789 &handle_priv
->interface_handle
[iface
].api_handle
)) {
2790 handle_priv
->interface_handle
[iface
].api_handle
= INVALID_HANDLE_VALUE
;
2791 switch(GetLastError()) {
2792 case ERROR_NO_MORE_ITEMS
: // invalid iface
2793 return LIBUSB_ERROR_NOT_FOUND
;
2794 case ERROR_BAD_COMMAND
: // The device was disconnected
2795 return LIBUSB_ERROR_NO_DEVICE
;
2796 case ERROR_ALREADY_EXISTS
: // already claimed
2797 return LIBUSB_ERROR_BUSY
;
2799 usbi_err(ctx
, "could not claim interface %d: %s", iface
, windows_error_str(0));
2800 return LIBUSB_ERROR_ACCESS
;
2804 usbi_dbg("claimed interface %d", iface
);
2805 handle_priv
->active_interface
= iface
;
2807 return LIBUSB_SUCCESS
;
2810 static int winusbx_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
2812 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2813 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2814 HANDLE winusb_handle
;
2816 CHECK_WINUSBX_AVAILABLE(sub_api
);
2818 winusb_handle
= handle_priv
->interface_handle
[iface
].api_handle
;
2819 if ((winusb_handle
== 0) || (winusb_handle
== INVALID_HANDLE_VALUE
)) {
2820 return LIBUSB_ERROR_NOT_FOUND
;
2823 WinUSBX
[sub_api
].Free(winusb_handle
);
2824 handle_priv
->interface_handle
[iface
].api_handle
= INVALID_HANDLE_VALUE
;
2826 return LIBUSB_SUCCESS
;
2830 * Return the first valid interface (of the same API type), for control transfers
2832 static int get_valid_interface(struct libusb_device_handle
*dev_handle
, int api_id
)
2834 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2835 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2838 if ((api_id
< USB_API_WINUSBX
) || (api_id
> USB_API_HID
)) {
2839 usbi_dbg("unsupported API ID");
2843 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
2844 if ( (handle_priv
->interface_handle
[i
].dev_handle
!= 0)
2845 && (handle_priv
->interface_handle
[i
].dev_handle
!= INVALID_HANDLE_VALUE
)
2846 && (handle_priv
->interface_handle
[i
].api_handle
!= 0)
2847 && (handle_priv
->interface_handle
[i
].api_handle
!= INVALID_HANDLE_VALUE
)
2848 && (priv
->usb_interface
[i
].apib
->id
== api_id
) ) {
2856 * Lookup interface by endpoint address. -1 if not found
2858 static int interface_by_endpoint(struct windows_device_priv
*priv
,
2859 struct windows_device_handle_priv
*handle_priv
, uint8_t endpoint_address
)
2862 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
2863 if (handle_priv
->interface_handle
[i
].api_handle
== INVALID_HANDLE_VALUE
)
2865 if (handle_priv
->interface_handle
[i
].api_handle
== 0)
2867 if (priv
->usb_interface
[i
].endpoint
== NULL
)
2869 for (j
=0; j
<priv
->usb_interface
[i
].nb_endpoints
; j
++) {
2870 if (priv
->usb_interface
[i
].endpoint
[j
] == endpoint_address
) {
2878 static int winusbx_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
)
2880 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2881 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
2882 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
2883 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
2884 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(
2885 transfer
->dev_handle
);
2886 WINUSB_SETUP_PACKET
*setup
= (WINUSB_SETUP_PACKET
*) transfer
->buffer
;
2888 HANDLE winusb_handle
;
2889 int current_interface
;
2892 CHECK_WINUSBX_AVAILABLE(sub_api
);
2894 transfer_priv
->pollable_fd
= INVALID_WINFD
;
2895 size
= transfer
->length
- LIBUSB_CONTROL_SETUP_SIZE
;
2897 if (size
> MAX_CTRL_BUFFER_LENGTH
)
2898 return LIBUSB_ERROR_INVALID_PARAM
;
2900 current_interface
= get_valid_interface(transfer
->dev_handle
, USB_API_WINUSBX
);
2901 if (current_interface
< 0) {
2902 if (auto_claim(transfer
, ¤t_interface
, USB_API_WINUSBX
) != LIBUSB_SUCCESS
) {
2903 return LIBUSB_ERROR_NOT_FOUND
;
2907 usbi_dbg("will use interface %d", current_interface
);
2908 winusb_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
2910 wfd
= usbi_create_fd(winusb_handle
, RW_READ
, NULL
, NULL
);
2911 // Always use the handle returned from usbi_create_fd (wfd.handle)
2913 return LIBUSB_ERROR_NO_MEM
;
2916 // Sending of set configuration control requests from WinUSB creates issues
2917 if ( ((setup
->request_type
& (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD
)
2918 && (setup
->request
== LIBUSB_REQUEST_SET_CONFIGURATION
) ) {
2919 if (setup
->value
!= priv
->active_config
) {
2920 usbi_warn(ctx
, "cannot set configuration other than the default one");
2922 return LIBUSB_ERROR_INVALID_PARAM
;
2924 wfd
.overlapped
->Internal
= STATUS_COMPLETED_SYNCHRONOUSLY
;
2925 wfd
.overlapped
->InternalHigh
= 0;
2927 if (!WinUSBX
[sub_api
].ControlTransfer(wfd
.handle
, *setup
, transfer
->buffer
+ LIBUSB_CONTROL_SETUP_SIZE
, size
, NULL
, wfd
.overlapped
)) {
2928 if(GetLastError() != ERROR_IO_PENDING
) {
2929 usbi_warn(ctx
, "ControlTransfer failed: %s", windows_error_str(0));
2931 return LIBUSB_ERROR_IO
;
2934 wfd
.overlapped
->Internal
= STATUS_COMPLETED_SYNCHRONOUSLY
;
2935 wfd
.overlapped
->InternalHigh
= (DWORD
)size
;
2939 // Use priv_transfer to store data needed for async polling
2940 transfer_priv
->pollable_fd
= wfd
;
2941 transfer_priv
->interface_number
= (uint8_t)current_interface
;
2943 return LIBUSB_SUCCESS
;
2946 static int winusbx_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
)
2948 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
2949 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
2950 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
2951 HANDLE winusb_handle
;
2953 CHECK_WINUSBX_AVAILABLE(sub_api
);
2955 if (altsetting
> 255) {
2956 return LIBUSB_ERROR_INVALID_PARAM
;
2959 winusb_handle
= handle_priv
->interface_handle
[iface
].api_handle
;
2960 if ((winusb_handle
== 0) || (winusb_handle
== INVALID_HANDLE_VALUE
)) {
2961 usbi_err(ctx
, "interface must be claimed first");
2962 return LIBUSB_ERROR_NOT_FOUND
;
2965 if (!WinUSBX
[sub_api
].SetCurrentAlternateSetting(winusb_handle
, (UCHAR
)altsetting
)) {
2966 usbi_err(ctx
, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
2967 return LIBUSB_ERROR_IO
;
2970 return LIBUSB_SUCCESS
;
2973 static int winusbx_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
)
2975 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
2976 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
2977 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
2978 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
2979 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
2980 HANDLE winusb_handle
;
2982 int current_interface
;
2985 CHECK_WINUSBX_AVAILABLE(sub_api
);
2987 transfer_priv
->pollable_fd
= INVALID_WINFD
;
2989 current_interface
= interface_by_endpoint(priv
, handle_priv
, transfer
->endpoint
);
2990 if (current_interface
< 0) {
2991 usbi_err(ctx
, "unable to match endpoint to an open interface - cancelling transfer");
2992 return LIBUSB_ERROR_NOT_FOUND
;
2995 usbi_dbg("matched endpoint %02X with interface %d", transfer
->endpoint
, current_interface
);
2997 winusb_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
2999 wfd
= usbi_create_fd(winusb_handle
, IS_XFERIN(transfer
) ? RW_READ
: RW_WRITE
, NULL
, NULL
);
3000 // Always use the handle returned from usbi_create_fd (wfd.handle)
3002 return LIBUSB_ERROR_NO_MEM
;
3005 if (IS_XFERIN(transfer
)) {
3006 usbi_dbg("reading %d bytes", transfer
->length
);
3007 ret
= WinUSBX
[sub_api
].ReadPipe(wfd
.handle
, transfer
->endpoint
, transfer
->buffer
, transfer
->length
, NULL
, wfd
.overlapped
);
3009 usbi_dbg("writing %d bytes", transfer
->length
);
3010 ret
= WinUSBX
[sub_api
].WritePipe(wfd
.handle
, transfer
->endpoint
, transfer
->buffer
, transfer
->length
, NULL
, wfd
.overlapped
);
3013 if(GetLastError() != ERROR_IO_PENDING
) {
3014 usbi_err(ctx
, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
3016 return LIBUSB_ERROR_IO
;
3019 wfd
.overlapped
->Internal
= STATUS_COMPLETED_SYNCHRONOUSLY
;
3020 wfd
.overlapped
->InternalHigh
= (DWORD
)transfer
->length
;
3023 transfer_priv
->pollable_fd
= wfd
;
3024 transfer_priv
->interface_number
= (uint8_t)current_interface
;
3026 return LIBUSB_SUCCESS
;
3029 static int winusbx_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
)
3031 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
3032 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
3033 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
3034 HANDLE winusb_handle
;
3035 int current_interface
;
3037 CHECK_WINUSBX_AVAILABLE(sub_api
);
3039 current_interface
= interface_by_endpoint(priv
, handle_priv
, endpoint
);
3040 if (current_interface
< 0) {
3041 usbi_err(ctx
, "unable to match endpoint to an open interface - cannot clear");
3042 return LIBUSB_ERROR_NOT_FOUND
;
3045 usbi_dbg("matched endpoint %02X with interface %d", endpoint
, current_interface
);
3046 winusb_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
3048 if (!WinUSBX
[sub_api
].ResetPipe(winusb_handle
, endpoint
)) {
3049 usbi_err(ctx
, "ResetPipe failed: %s", windows_error_str(0));
3050 return LIBUSB_ERROR_NO_DEVICE
;
3053 return LIBUSB_SUCCESS
;
3057 * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
3058 * through testing as well):
3059 * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
3060 * the control transfer using CancelIo"
3062 static int winusbx_abort_control(int sub_api
, struct usbi_transfer
*itransfer
)
3064 // Cancelling of the I/O is done in the parent
3065 return LIBUSB_SUCCESS
;
3068 static int winusbx_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
)
3070 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
3071 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
3072 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
3073 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
3074 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
3075 HANDLE winusb_handle
;
3076 int current_interface
;
3078 CHECK_WINUSBX_AVAILABLE(sub_api
);
3080 current_interface
= transfer_priv
->interface_number
;
3081 if ((current_interface
< 0) || (current_interface
>= USB_MAXINTERFACES
)) {
3082 usbi_err(ctx
, "program assertion failed: invalid interface_number");
3083 return LIBUSB_ERROR_NOT_FOUND
;
3085 usbi_dbg("will use interface %d", current_interface
);
3087 winusb_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
3089 if (!WinUSBX
[sub_api
].AbortPipe(winusb_handle
, transfer
->endpoint
)) {
3090 usbi_err(ctx
, "AbortPipe failed: %s", windows_error_str(0));
3091 return LIBUSB_ERROR_NO_DEVICE
;
3094 return LIBUSB_SUCCESS
;
3098 * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper
3099 * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx):
3100 * "WinUSB does not support host-initiated reset port and cycle port operations" and
3101 * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the
3102 * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is
3103 * cycle the pipes (and even then, the control pipe can not be reset using WinUSB)
3105 // TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
3106 static int winusbx_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
)
3108 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
3109 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
3110 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
3112 HANDLE winusb_handle
;
3115 CHECK_WINUSBX_AVAILABLE(sub_api
);
3117 // Reset any available pipe (except control)
3118 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
3119 winusb_handle
= handle_priv
->interface_handle
[i
].api_handle
;
3120 for (wfd
= handle_to_winfd(winusb_handle
); wfd
.fd
> 0;)
3122 // Cancel any pollable I/O
3123 usbi_remove_pollfd(ctx
, wfd
.fd
);
3125 wfd
= handle_to_winfd(winusb_handle
);
3128 if ( (winusb_handle
!= 0) && (winusb_handle
!= INVALID_HANDLE_VALUE
)) {
3129 for (j
=0; j
<priv
->usb_interface
[i
].nb_endpoints
; j
++) {
3130 usbi_dbg("resetting ep %02X", priv
->usb_interface
[i
].endpoint
[j
]);
3131 if (!WinUSBX
[sub_api
].AbortPipe(winusb_handle
, priv
->usb_interface
[i
].endpoint
[j
])) {
3132 usbi_err(ctx
, "AbortPipe (pipe address %02X) failed: %s",
3133 priv
->usb_interface
[i
].endpoint
[j
], windows_error_str(0));
3135 // FlushPipe seems to fail on OUT pipes
3136 if (IS_EPIN(priv
->usb_interface
[i
].endpoint
[j
])
3137 && (!WinUSBX
[sub_api
].FlushPipe(winusb_handle
, priv
->usb_interface
[i
].endpoint
[j
])) ) {
3138 usbi_err(ctx
, "FlushPipe (pipe address %02X) failed: %s",
3139 priv
->usb_interface
[i
].endpoint
[j
], windows_error_str(0));
3141 if (!WinUSBX
[sub_api
].ResetPipe(winusb_handle
, priv
->usb_interface
[i
].endpoint
[j
])) {
3142 usbi_err(ctx
, "ResetPipe (pipe address %02X) failed: %s",
3143 priv
->usb_interface
[i
].endpoint
[j
], windows_error_str(0));
3149 // libusbK & libusb0 have the ability to issue an actual device reset
3150 if (WinUSBX
[sub_api
].ResetDevice
!= NULL
) {
3151 winusb_handle
= handle_priv
->interface_handle
[0].api_handle
;
3152 if ( (winusb_handle
!= 0) && (winusb_handle
!= INVALID_HANDLE_VALUE
)) {
3153 WinUSBX
[sub_api
].ResetDevice(winusb_handle
);
3156 return LIBUSB_SUCCESS
;
3159 static int winusbx_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
)
3161 itransfer
->transferred
+= io_size
;
3162 return LIBUSB_TRANSFER_COMPLETED
;
3166 * Internal HID Support functions (from libusb-win32)
3167 * Note that functions that complete data transfer synchronously must return
3168 * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS
3170 static int _hid_get_hid_descriptor(struct hid_device_priv
* dev
, void *data
, size_t *size
);
3171 static int _hid_get_report_descriptor(struct hid_device_priv
* dev
, void *data
, size_t *size
);
3173 static int _hid_wcslen(WCHAR
*str
)
3176 while (str
[i
] && (str
[i
] != 0x409)) {
3182 static int _hid_get_device_descriptor(struct hid_device_priv
* dev
, void *data
, size_t *size
)
3184 struct libusb_device_descriptor d
;
3186 d
.bLength
= LIBUSB_DT_DEVICE_SIZE
;
3187 d
.bDescriptorType
= LIBUSB_DT_DEVICE
;
3188 d
.bcdUSB
= 0x0200; /* 2.00 */
3190 d
.bDeviceSubClass
= 0;
3191 d
.bDeviceProtocol
= 0;
3192 d
.bMaxPacketSize0
= 64; /* fix this! */
3193 d
.idVendor
= (uint16_t)dev
->vid
;
3194 d
.idProduct
= (uint16_t)dev
->pid
;
3195 d
.bcdDevice
= 0x0100;
3196 d
.iManufacturer
= dev
->string_index
[0];
3197 d
.iProduct
= dev
->string_index
[1];
3198 d
.iSerialNumber
= dev
->string_index
[2];
3199 d
.bNumConfigurations
= 1;
3201 if (*size
> LIBUSB_DT_DEVICE_SIZE
)
3202 *size
= LIBUSB_DT_DEVICE_SIZE
;
3203 memcpy(data
, &d
, *size
);
3204 return LIBUSB_COMPLETED
;
3207 static int _hid_get_config_descriptor(struct hid_device_priv
* dev
, void *data
, size_t *size
)
3209 char num_endpoints
= 0;
3210 size_t config_total_len
= 0;
3211 char tmp
[HID_MAX_CONFIG_DESC_SIZE
];
3212 struct libusb_config_descriptor
*cd
;
3213 struct libusb_interface_descriptor
*id
;
3214 struct libusb_hid_descriptor
*hd
;
3215 struct libusb_endpoint_descriptor
*ed
;
3218 if (dev
->input_report_size
)
3220 if (dev
->output_report_size
)
3223 config_total_len
= LIBUSB_DT_CONFIG_SIZE
+ LIBUSB_DT_INTERFACE_SIZE
3224 + LIBUSB_DT_HID_SIZE
+ num_endpoints
* LIBUSB_DT_ENDPOINT_SIZE
;
3227 cd
= (struct libusb_config_descriptor
*)tmp
;
3228 id
= (struct libusb_interface_descriptor
*)(tmp
+ LIBUSB_DT_CONFIG_SIZE
);
3229 hd
= (struct libusb_hid_descriptor
*)(tmp
+ LIBUSB_DT_CONFIG_SIZE
3230 + LIBUSB_DT_INTERFACE_SIZE
);
3231 ed
= (struct libusb_endpoint_descriptor
*)(tmp
+ LIBUSB_DT_CONFIG_SIZE
3232 + LIBUSB_DT_INTERFACE_SIZE
3233 + LIBUSB_DT_HID_SIZE
);
3235 cd
->bLength
= LIBUSB_DT_CONFIG_SIZE
;
3236 cd
->bDescriptorType
= LIBUSB_DT_CONFIG
;
3237 cd
->wTotalLength
= (uint16_t) config_total_len
;
3238 cd
->bNumInterfaces
= 1;
3239 cd
->bConfigurationValue
= 1;
3240 cd
->iConfiguration
= 0;
3241 cd
->bmAttributes
= 1 << 7; /* bus powered */
3244 id
->bLength
= LIBUSB_DT_INTERFACE_SIZE
;
3245 id
->bDescriptorType
= LIBUSB_DT_INTERFACE
;
3246 id
->bInterfaceNumber
= 0;
3247 id
->bAlternateSetting
= 0;
3248 id
->bNumEndpoints
= num_endpoints
;
3249 id
->bInterfaceClass
= 3;
3250 id
->bInterfaceSubClass
= 0;
3251 id
->bInterfaceProtocol
= 0;
3254 tmp_size
= LIBUSB_DT_HID_SIZE
;
3255 _hid_get_hid_descriptor(dev
, hd
, &tmp_size
);
3257 if (dev
->input_report_size
) {
3258 ed
->bLength
= LIBUSB_DT_ENDPOINT_SIZE
;
3259 ed
->bDescriptorType
= LIBUSB_DT_ENDPOINT
;
3260 ed
->bEndpointAddress
= HID_IN_EP
;
3261 ed
->bmAttributes
= 3;
3262 ed
->wMaxPacketSize
= dev
->input_report_size
- 1;
3264 ed
= (struct libusb_endpoint_descriptor
*)((char*)ed
+ LIBUSB_DT_ENDPOINT_SIZE
);
3267 if (dev
->output_report_size
) {
3268 ed
->bLength
= LIBUSB_DT_ENDPOINT_SIZE
;
3269 ed
->bDescriptorType
= LIBUSB_DT_ENDPOINT
;
3270 ed
->bEndpointAddress
= HID_OUT_EP
;
3271 ed
->bmAttributes
= 3;
3272 ed
->wMaxPacketSize
= dev
->output_report_size
- 1;
3276 if (*size
> config_total_len
)
3277 *size
= config_total_len
;
3278 memcpy(data
, tmp
, *size
);
3279 return LIBUSB_COMPLETED
;
3282 static int _hid_get_string_descriptor(struct hid_device_priv
* dev
, int _index
,
3283 void *data
, size_t *size
)
3286 size_t tmp_size
= 0;
3289 /* language ID, EN-US */
3290 char string_langid
[] = {
3295 if ((*size
< 2) || (*size
> 255)) {
3296 return LIBUSB_ERROR_OVERFLOW
;
3300 tmp
= string_langid
;
3301 tmp_size
= sizeof(string_langid
)+2;
3303 for (i
=0; i
<3; i
++) {
3304 if (_index
== (dev
->string_index
[i
])) {
3305 tmp
= dev
->string
[i
];
3306 tmp_size
= (_hid_wcslen(dev
->string
[i
])+1) * sizeof(WCHAR
);
3310 if (i
== 3) { // not found
3311 return LIBUSB_ERROR_INVALID_PARAM
;
3316 return LIBUSB_ERROR_INVALID_PARAM
;
3319 if (tmp_size
< *size
) {
3323 ((uint8_t*)data
)[0] = (uint8_t)*size
;
3324 ((uint8_t*)data
)[1] = LIBUSB_DT_STRING
;
3325 memcpy((uint8_t*)data
+2, tmp
, *size
-2);
3326 return LIBUSB_COMPLETED
;
3329 static int _hid_get_hid_descriptor(struct hid_device_priv
* dev
, void *data
, size_t *size
)
3331 struct libusb_hid_descriptor d
;
3332 uint8_t tmp
[MAX_HID_DESCRIPTOR_SIZE
];
3333 size_t report_len
= MAX_HID_DESCRIPTOR_SIZE
;
3335 _hid_get_report_descriptor(dev
, tmp
, &report_len
);
3337 d
.bLength
= LIBUSB_DT_HID_SIZE
;
3338 d
.bDescriptorType
= LIBUSB_DT_HID
;
3339 d
.bcdHID
= 0x0110; /* 1.10 */
3341 d
.bNumDescriptors
= 1;
3342 d
.bClassDescriptorType
= LIBUSB_DT_REPORT
;
3343 d
.wClassDescriptorLength
= (uint16_t)report_len
;
3345 if (*size
> LIBUSB_DT_HID_SIZE
)
3346 *size
= LIBUSB_DT_HID_SIZE
;
3347 memcpy(data
, &d
, *size
);
3348 return LIBUSB_COMPLETED
;
3351 static int _hid_get_report_descriptor(struct hid_device_priv
* dev
, void *data
, size_t *size
)
3353 uint8_t d
[MAX_HID_DESCRIPTOR_SIZE
];
3356 /* usage page (0xFFA0 == vendor defined) */
3357 d
[i
++] = 0x06; d
[i
++] = 0xA0; d
[i
++] = 0xFF;
3358 /* usage (vendor defined) */
3359 d
[i
++] = 0x09; d
[i
++] = 0x01;
3360 /* start collection (application) */
3361 d
[i
++] = 0xA1; d
[i
++] = 0x01;
3363 if (dev
->input_report_size
) {
3364 /* usage (vendor defined) */
3365 d
[i
++] = 0x09; d
[i
++] = 0x01;
3366 /* logical minimum (0) */
3367 d
[i
++] = 0x15; d
[i
++] = 0x00;
3368 /* logical maximum (255) */
3369 d
[i
++] = 0x25; d
[i
++] = 0xFF;
3370 /* report size (8 bits) */
3371 d
[i
++] = 0x75; d
[i
++] = 0x08;
3373 d
[i
++] = 0x95; d
[i
++] = (uint8_t)dev
->input_report_size
- 1;
3374 /* input (data, variable, absolute) */
3375 d
[i
++] = 0x81; d
[i
++] = 0x00;
3378 if (dev
->output_report_size
) {
3379 /* usage (vendor defined) */
3380 d
[i
++] = 0x09; d
[i
++] = 0x02;
3381 /* logical minimum (0) */
3382 d
[i
++] = 0x15; d
[i
++] = 0x00;
3383 /* logical maximum (255) */
3384 d
[i
++] = 0x25; d
[i
++] = 0xFF;
3385 /* report size (8 bits) */
3386 d
[i
++] = 0x75; d
[i
++] = 0x08;
3388 d
[i
++] = 0x95; d
[i
++] = (uint8_t)dev
->output_report_size
- 1;
3389 /* output (data, variable, absolute) */
3390 d
[i
++] = 0x91; d
[i
++] = 0x00;
3392 /* feature report */
3393 if (dev
->feature_report_size
) {
3394 /* usage (vendor defined) */
3395 d
[i
++] = 0x09; d
[i
++] = 0x03;
3396 /* logical minimum (0) */
3397 d
[i
++] = 0x15; d
[i
++] = 0x00;
3398 /* logical maximum (255) */
3399 d
[i
++] = 0x25; d
[i
++] = 0xFF;
3400 /* report size (8 bits) */
3401 d
[i
++] = 0x75; d
[i
++] = 0x08;
3403 d
[i
++] = 0x95; d
[i
++] = (uint8_t)dev
->feature_report_size
- 1;
3404 /* feature (data, variable, absolute) */
3405 d
[i
++] = 0xb2; d
[i
++] = 0x02; d
[i
++] = 0x01;
3408 /* end collection */
3413 memcpy(data
, d
, *size
);
3414 return LIBUSB_COMPLETED
;
3417 static int _hid_get_descriptor(struct hid_device_priv
* dev
, HANDLE hid_handle
, int recipient
,
3418 int type
, int _index
, void *data
, size_t *size
)
3421 case LIBUSB_DT_DEVICE
:
3422 usbi_dbg("LIBUSB_DT_DEVICE");
3423 return _hid_get_device_descriptor(dev
, data
, size
);
3424 case LIBUSB_DT_CONFIG
:
3425 usbi_dbg("LIBUSB_DT_CONFIG");
3427 return _hid_get_config_descriptor(dev
, data
, size
);
3428 return LIBUSB_ERROR_INVALID_PARAM
;
3429 case LIBUSB_DT_STRING
:
3430 usbi_dbg("LIBUSB_DT_STRING");
3431 return _hid_get_string_descriptor(dev
, _index
, data
, size
);
3433 usbi_dbg("LIBUSB_DT_HID");
3435 return _hid_get_hid_descriptor(dev
, data
, size
);
3436 return LIBUSB_ERROR_INVALID_PARAM
;
3437 case LIBUSB_DT_REPORT
:
3438 usbi_dbg("LIBUSB_DT_REPORT");
3440 return _hid_get_report_descriptor(dev
, data
, size
);
3441 return LIBUSB_ERROR_INVALID_PARAM
;
3442 case LIBUSB_DT_PHYSICAL
:
3443 usbi_dbg("LIBUSB_DT_PHYSICAL");
3444 if (HidD_GetPhysicalDescriptor(hid_handle
, data
, (ULONG
)*size
))
3445 return LIBUSB_COMPLETED
;
3446 return LIBUSB_ERROR_OTHER
;
3448 usbi_dbg("unsupported");
3449 return LIBUSB_ERROR_INVALID_PARAM
;
3452 static int _hid_get_report(struct hid_device_priv
* dev
, HANDLE hid_handle
, int id
, void *data
,
3453 struct windows_transfer_priv
*tp
, size_t *size
, OVERLAPPED
* overlapped
,
3457 DWORD ioctl_code
, read_size
, expected_size
= (DWORD
)*size
;
3458 int r
= LIBUSB_SUCCESS
;
3460 if (tp
->hid_buffer
!= NULL
) {
3461 usbi_dbg("program assertion failed: hid_buffer is not NULL");
3464 if ((*size
== 0) || (*size
> MAX_HID_REPORT_SIZE
)) {
3465 usbi_dbg("invalid size (%d)", *size
);
3466 return LIBUSB_ERROR_INVALID_PARAM
;
3469 switch (report_type
) {
3470 case HID_REPORT_TYPE_INPUT
:
3471 ioctl_code
= IOCTL_HID_GET_INPUT_REPORT
;
3473 case HID_REPORT_TYPE_FEATURE
:
3474 ioctl_code
= IOCTL_HID_GET_FEATURE
;
3477 usbi_dbg("unknown HID report type %d", report_type
);
3478 return LIBUSB_ERROR_INVALID_PARAM
;
3481 // Add a trailing byte to detect overflows
3482 buf
= (uint8_t*)calloc(expected_size
+1, 1);
3484 return LIBUSB_ERROR_NO_MEM
;
3486 buf
[0] = (uint8_t)id
; // Must be set always
3487 usbi_dbg("report ID: 0x%02X", buf
[0]);
3489 tp
->hid_expected_size
= expected_size
;
3490 read_size
= expected_size
;
3492 // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
3493 if (!DeviceIoControl(hid_handle
, ioctl_code
, buf
, expected_size
+1,
3494 buf
, expected_size
+1, &read_size
, overlapped
)) {
3495 if (GetLastError() != ERROR_IO_PENDING
) {
3496 usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
3498 return LIBUSB_ERROR_IO
;
3500 // Asynchronous wait
3501 tp
->hid_buffer
= buf
;
3502 tp
->hid_dest
= (uint8_t*)data
; // copy dest, as not necessarily the start of the transfer buffer
3503 return LIBUSB_SUCCESS
;
3506 // Transfer completed synchronously => copy and discard extra buffer
3507 if (read_size
== 0) {
3508 usbi_warn(NULL
, "program assertion failed - read completed synchronously, but no data was read");
3512 usbi_warn(NULL
, "mismatched report ID (data is %02X, parameter is %02X)", buf
[0], id
);
3514 if ((size_t)read_size
> expected_size
) {
3515 r
= LIBUSB_ERROR_OVERFLOW
;
3516 usbi_dbg("OVERFLOW!");
3518 r
= LIBUSB_COMPLETED
;
3521 *size
= MIN((size_t)read_size
, *size
);
3523 // Discard report ID
3524 memcpy(data
, buf
+1, *size
);
3526 memcpy(data
, buf
, *size
);
3533 static int _hid_set_report(struct hid_device_priv
* dev
, HANDLE hid_handle
, int id
, void *data
,
3534 struct windows_transfer_priv
*tp
, size_t *size
, OVERLAPPED
* overlapped
,
3537 uint8_t *buf
= NULL
;
3538 DWORD ioctl_code
, write_size
= (DWORD
)*size
;
3540 if (tp
->hid_buffer
!= NULL
) {
3541 usbi_dbg("program assertion failed: hid_buffer is not NULL");
3544 if ((*size
== 0) || (*size
> MAX_HID_REPORT_SIZE
)) {
3545 usbi_dbg("invalid size (%d)", *size
);
3546 return LIBUSB_ERROR_INVALID_PARAM
;
3549 switch (report_type
) {
3550 case HID_REPORT_TYPE_OUTPUT
:
3551 ioctl_code
= IOCTL_HID_SET_OUTPUT_REPORT
;
3553 case HID_REPORT_TYPE_FEATURE
:
3554 ioctl_code
= IOCTL_HID_SET_FEATURE
;
3557 usbi_dbg("unknown HID report type %d", report_type
);
3558 return LIBUSB_ERROR_INVALID_PARAM
;
3561 usbi_dbg("report ID: 0x%02X", id
);
3562 // When report IDs are not used (i.e. when id == 0), we must add
3563 // a null report ID. Otherwise, we just use original data buffer
3567 buf
= (uint8_t*) malloc(write_size
);
3569 return LIBUSB_ERROR_NO_MEM
;
3573 memcpy(buf
+ 1, data
, *size
);
3575 // This seems like a waste, but if we don't duplicate the
3576 // data, we'll get issues when freeing hid_buffer
3577 memcpy(buf
, data
, *size
);
3579 usbi_warn(NULL
, "mismatched report ID (data is %02X, parameter is %02X)", buf
[0], id
);
3583 // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
3584 if (!DeviceIoControl(hid_handle
, ioctl_code
, buf
, write_size
,
3585 buf
, write_size
, &write_size
, overlapped
)) {
3586 if (GetLastError() != ERROR_IO_PENDING
) {
3587 usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
3589 return LIBUSB_ERROR_IO
;
3591 tp
->hid_buffer
= buf
;
3592 tp
->hid_dest
= NULL
;
3593 return LIBUSB_SUCCESS
;
3596 // Transfer completed synchronously
3598 if (write_size
== 0) {
3599 usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
3602 return LIBUSB_COMPLETED
;
3605 static int _hid_class_request(struct hid_device_priv
* dev
, HANDLE hid_handle
, int request_type
,
3606 int request
, int value
, int _index
, void *data
, struct windows_transfer_priv
*tp
,
3607 size_t *size
, OVERLAPPED
* overlapped
)
3609 int report_type
= (value
>> 8) & 0xFF;
3610 int report_id
= value
& 0xFF;
3612 if ( (LIBUSB_REQ_RECIPIENT(request_type
) != LIBUSB_RECIPIENT_INTERFACE
)
3613 && (LIBUSB_REQ_RECIPIENT(request_type
) != LIBUSB_RECIPIENT_DEVICE
) )
3614 return LIBUSB_ERROR_INVALID_PARAM
;
3616 if (LIBUSB_REQ_OUT(request_type
) && request
== HID_REQ_SET_REPORT
)
3617 return _hid_set_report(dev
, hid_handle
, report_id
, data
, tp
, size
, overlapped
, report_type
);
3619 if (LIBUSB_REQ_IN(request_type
) && request
== HID_REQ_GET_REPORT
)
3620 return _hid_get_report(dev
, hid_handle
, report_id
, data
, tp
, size
, overlapped
, report_type
);
3622 return LIBUSB_ERROR_INVALID_PARAM
;
3629 static int hid_init(int sub_api
, struct libusb_context
*ctx
)
3631 DLL_LOAD(hid
.dll
, HidD_GetAttributes
, TRUE
);
3632 DLL_LOAD(hid
.dll
, HidD_GetHidGuid
, TRUE
);
3633 DLL_LOAD(hid
.dll
, HidD_GetPreparsedData
, TRUE
);
3634 DLL_LOAD(hid
.dll
, HidD_FreePreparsedData
, TRUE
);
3635 DLL_LOAD(hid
.dll
, HidD_GetManufacturerString
, TRUE
);
3636 DLL_LOAD(hid
.dll
, HidD_GetProductString
, TRUE
);
3637 DLL_LOAD(hid
.dll
, HidD_GetSerialNumberString
, TRUE
);
3638 DLL_LOAD(hid
.dll
, HidP_GetCaps
, TRUE
);
3639 DLL_LOAD(hid
.dll
, HidD_SetNumInputBuffers
, TRUE
);
3640 DLL_LOAD(hid
.dll
, HidD_SetFeature
, TRUE
);
3641 DLL_LOAD(hid
.dll
, HidD_GetFeature
, TRUE
);
3642 DLL_LOAD(hid
.dll
, HidD_GetPhysicalDescriptor
, TRUE
);
3643 DLL_LOAD(hid
.dll
, HidD_GetInputReport
, FALSE
);
3644 DLL_LOAD(hid
.dll
, HidD_SetOutputReport
, FALSE
);
3645 DLL_LOAD(hid
.dll
, HidD_FlushQueue
, TRUE
);
3646 DLL_LOAD(hid
.dll
, HidP_GetValueCaps
, TRUE
);
3648 api_hid_available
= true;
3649 return LIBUSB_SUCCESS
;
3652 static int hid_exit(int sub_api
)
3654 return LIBUSB_SUCCESS
;
3657 // NB: open and close must ensure that they only handle interface of
3658 // the right API type, as these functions can be called wholesale from
3659 // composite_open(), with interfaces belonging to different APIs
3660 static int hid_open(int sub_api
, struct libusb_device_handle
*dev_handle
)
3662 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
3663 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
3664 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
3666 HIDD_ATTRIBUTES hid_attributes
;
3667 PHIDP_PREPARSED_DATA preparsed_data
= NULL
;
3668 HIDP_CAPS capabilities
;
3669 HIDP_VALUE_CAPS
*value_caps
;
3671 HANDLE hid_handle
= INVALID_HANDLE_VALUE
;
3673 // report IDs handling
3675 const char* type
[3] = {"input", "output", "feature"};
3676 int nb_ids
[2]; // zero and nonzero report IDs
3678 CHECK_HID_AVAILABLE
;
3679 if (priv
->hid
== NULL
) {
3680 usbi_err(ctx
, "program assertion failed - private HID structure is unitialized");
3681 return LIBUSB_ERROR_NOT_FOUND
;
3684 for (i
= 0; i
< USB_MAXINTERFACES
; i
++) {
3685 if ( (priv
->usb_interface
[i
].path
!= NULL
)
3686 && (priv
->usb_interface
[i
].apib
->id
== USB_API_HID
) ) {
3687 hid_handle
= CreateFileA(priv
->usb_interface
[i
].path
, GENERIC_WRITE
| GENERIC_READ
, FILE_SHARE_WRITE
| FILE_SHARE_READ
,
3688 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
3690 * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
3691 * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
3692 * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not
3693 * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and
3694 * HidD_GetFeature (if the device supports Feature reports)."
3696 if (hid_handle
== INVALID_HANDLE_VALUE
) {
3697 usbi_warn(ctx
, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
3698 hid_handle
= CreateFileA(priv
->usb_interface
[i
].path
, 0, FILE_SHARE_WRITE
| FILE_SHARE_READ
,
3699 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
3700 if (hid_handle
== INVALID_HANDLE_VALUE
) {
3701 usbi_err(ctx
, "could not open device %s (interface %d): %s", priv
->path
, i
, windows_error_str(0));
3702 switch(GetLastError()) {
3703 case ERROR_FILE_NOT_FOUND
: // The device was disconnected
3704 return LIBUSB_ERROR_NO_DEVICE
;
3705 case ERROR_ACCESS_DENIED
:
3706 return LIBUSB_ERROR_ACCESS
;
3708 return LIBUSB_ERROR_IO
;
3711 priv
->usb_interface
[i
].restricted_functionality
= true;
3713 handle_priv
->interface_handle
[i
].api_handle
= hid_handle
;
3717 hid_attributes
.Size
= sizeof(hid_attributes
);
3719 if (!HidD_GetAttributes(hid_handle
, &hid_attributes
)) {
3720 usbi_err(ctx
, "could not gain access to HID top collection (HidD_GetAttributes)");
3724 priv
->hid
->vid
= hid_attributes
.VendorID
;
3725 priv
->hid
->pid
= hid_attributes
.ProductID
;
3727 // Set the maximum available input buffer size
3728 for (i
=32; HidD_SetNumInputBuffers(hid_handle
, i
); i
*=2);
3729 usbi_dbg("set maximum input buffer size to %d", i
/2);
3731 // Get the maximum input and output report size
3732 if (!HidD_GetPreparsedData(hid_handle
, &preparsed_data
) || !preparsed_data
) {
3733 usbi_err(ctx
, "could not read HID preparsed data (HidD_GetPreparsedData)");
3736 if (HidP_GetCaps(preparsed_data
, &capabilities
) != HIDP_STATUS_SUCCESS
) {
3737 usbi_err(ctx
, "could not parse HID capabilities (HidP_GetCaps)");
3741 // Find out if interrupt will need report IDs
3742 size
[0] = capabilities
.NumberInputValueCaps
;
3743 size
[1] = capabilities
.NumberOutputValueCaps
;
3744 size
[2] = capabilities
.NumberFeatureValueCaps
;
3745 for (j
=HidP_Input
; j
<=HidP_Feature
; j
++) {
3746 usbi_dbg("%d HID %s report value(s) found", size
[j
], type
[j
]);
3747 priv
->hid
->uses_report_ids
[j
] = false;
3749 value_caps
= (HIDP_VALUE_CAPS
*) calloc(size
[j
], sizeof(HIDP_VALUE_CAPS
));
3750 if ( (value_caps
!= NULL
)
3751 && (HidP_GetValueCaps((HIDP_REPORT_TYPE
)j
, value_caps
, &size
[j
], preparsed_data
) == HIDP_STATUS_SUCCESS
)
3752 && (size
[j
] >= 1) ) {
3755 for (i
=0; i
<(int)size
[j
]; i
++) {
3756 usbi_dbg(" Report ID: 0x%02X", value_caps
[i
].ReportID
);
3757 if (value_caps
[i
].ReportID
!= 0) {
3763 if (nb_ids
[1] != 0) {
3764 if (nb_ids
[0] != 0) {
3765 usbi_warn(ctx
, "program assertion failed: zero and nonzero report IDs used for %s",
3768 priv
->hid
->uses_report_ids
[j
] = true;
3771 usbi_warn(ctx
, " could not process %s report IDs", type
[j
]);
3773 safe_free(value_caps
);
3777 // Set the report sizes
3778 priv
->hid
->input_report_size
= capabilities
.InputReportByteLength
;
3779 priv
->hid
->output_report_size
= capabilities
.OutputReportByteLength
;
3780 priv
->hid
->feature_report_size
= capabilities
.FeatureReportByteLength
;
3782 // Fetch string descriptors
3783 priv
->hid
->string_index
[0] = priv
->dev_descriptor
.iManufacturer
;
3784 if (priv
->hid
->string_index
[0] != 0) {
3785 HidD_GetManufacturerString(hid_handle
, priv
->hid
->string
[0],
3786 sizeof(priv
->hid
->string
[0]));
3788 priv
->hid
->string
[0][0] = 0;
3790 priv
->hid
->string_index
[1] = priv
->dev_descriptor
.iProduct
;
3791 if (priv
->hid
->string_index
[1] != 0) {
3792 HidD_GetProductString(hid_handle
, priv
->hid
->string
[1],
3793 sizeof(priv
->hid
->string
[1]));
3795 priv
->hid
->string
[1][0] = 0;
3797 priv
->hid
->string_index
[2] = priv
->dev_descriptor
.iSerialNumber
;
3798 if (priv
->hid
->string_index
[2] != 0) {
3799 HidD_GetSerialNumberString(hid_handle
, priv
->hid
->string
[2],
3800 sizeof(priv
->hid
->string
[2]));
3802 priv
->hid
->string
[2][0] = 0;
3806 if (preparsed_data
) {
3807 HidD_FreePreparsedData(preparsed_data
);
3810 return LIBUSB_SUCCESS
;
3813 static void hid_close(int sub_api
, struct libusb_device_handle
*dev_handle
)
3815 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
3816 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
3820 if (!api_hid_available
)
3823 for (i
= 0; i
< USB_MAXINTERFACES
; i
++) {
3824 if (priv
->usb_interface
[i
].apib
->id
== USB_API_HID
) {
3825 file_handle
= handle_priv
->interface_handle
[i
].api_handle
;
3826 if ( (file_handle
!= 0) && (file_handle
!= INVALID_HANDLE_VALUE
)) {
3827 CloseHandle(file_handle
);
3833 static int hid_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
3835 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
3836 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
3838 CHECK_HID_AVAILABLE
;
3840 // NB: Disconnection detection is not possible in this function
3841 if (priv
->usb_interface
[iface
].path
== NULL
) {
3842 return LIBUSB_ERROR_NOT_FOUND
; // invalid iface
3845 // We use dev_handle as a flag for interface claimed
3846 if (handle_priv
->interface_handle
[iface
].dev_handle
== INTERFACE_CLAIMED
) {
3847 return LIBUSB_ERROR_BUSY
; // already claimed
3850 handle_priv
->interface_handle
[iface
].dev_handle
= INTERFACE_CLAIMED
;
3852 usbi_dbg("claimed interface %d", iface
);
3853 handle_priv
->active_interface
= iface
;
3855 return LIBUSB_SUCCESS
;
3858 static int hid_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
3860 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
3861 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
3863 CHECK_HID_AVAILABLE
;
3865 if (priv
->usb_interface
[iface
].path
== NULL
) {
3866 return LIBUSB_ERROR_NOT_FOUND
; // invalid iface
3869 if (handle_priv
->interface_handle
[iface
].dev_handle
!= INTERFACE_CLAIMED
) {
3870 return LIBUSB_ERROR_NOT_FOUND
; // invalid iface
3873 handle_priv
->interface_handle
[iface
].dev_handle
= INVALID_HANDLE_VALUE
;
3875 return LIBUSB_SUCCESS
;
3878 static int hid_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
)
3880 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
3882 CHECK_HID_AVAILABLE
;
3884 if (altsetting
> 255) {
3885 return LIBUSB_ERROR_INVALID_PARAM
;
3888 if (altsetting
!= 0) {
3889 usbi_err(ctx
, "set interface altsetting not supported for altsetting >0");
3890 return LIBUSB_ERROR_NOT_SUPPORTED
;
3893 return LIBUSB_SUCCESS
;
3896 static int hid_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
)
3898 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
3899 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
3900 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
3901 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
3902 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
3903 WINUSB_SETUP_PACKET
*setup
= (WINUSB_SETUP_PACKET
*) transfer
->buffer
;
3906 int current_interface
, config
;
3908 int r
= LIBUSB_ERROR_INVALID_PARAM
;
3910 CHECK_HID_AVAILABLE
;
3912 transfer_priv
->pollable_fd
= INVALID_WINFD
;
3913 safe_free(transfer_priv
->hid_buffer
);
3914 transfer_priv
->hid_dest
= NULL
;
3915 size
= transfer
->length
- LIBUSB_CONTROL_SETUP_SIZE
;
3917 if (size
> MAX_CTRL_BUFFER_LENGTH
) {
3918 return LIBUSB_ERROR_INVALID_PARAM
;
3921 current_interface
= get_valid_interface(transfer
->dev_handle
, USB_API_HID
);
3922 if (current_interface
< 0) {
3923 if (auto_claim(transfer
, ¤t_interface
, USB_API_HID
) != LIBUSB_SUCCESS
) {
3924 return LIBUSB_ERROR_NOT_FOUND
;
3928 usbi_dbg("will use interface %d", current_interface
);
3929 hid_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
3930 // Always use the handle returned from usbi_create_fd (wfd.handle)
3931 wfd
= usbi_create_fd(hid_handle
, RW_READ
, NULL
, NULL
);
3933 return LIBUSB_ERROR_NOT_FOUND
;
3936 switch(LIBUSB_REQ_TYPE(setup
->request_type
)) {
3937 case LIBUSB_REQUEST_TYPE_STANDARD
:
3938 switch(setup
->request
) {
3939 case LIBUSB_REQUEST_GET_DESCRIPTOR
:
3940 r
= _hid_get_descriptor(priv
->hid
, wfd
.handle
, LIBUSB_REQ_RECIPIENT(setup
->request_type
),
3941 (setup
->value
>> 8) & 0xFF, setup
->value
& 0xFF, transfer
->buffer
+ LIBUSB_CONTROL_SETUP_SIZE
, &size
);
3943 case LIBUSB_REQUEST_GET_CONFIGURATION
:
3944 r
= windows_get_configuration(transfer
->dev_handle
, &config
);
3945 if (r
== LIBUSB_SUCCESS
) {
3947 ((uint8_t*)transfer
->buffer
)[LIBUSB_CONTROL_SETUP_SIZE
] = (uint8_t)config
;
3948 r
= LIBUSB_COMPLETED
;
3951 case LIBUSB_REQUEST_SET_CONFIGURATION
:
3952 if (setup
->value
== priv
->active_config
) {
3953 r
= LIBUSB_COMPLETED
;
3955 usbi_warn(ctx
, "cannot set configuration other than the default one");
3956 r
= LIBUSB_ERROR_INVALID_PARAM
;
3959 case LIBUSB_REQUEST_GET_INTERFACE
:
3961 ((uint8_t*)transfer
->buffer
)[LIBUSB_CONTROL_SETUP_SIZE
] = 0;
3962 r
= LIBUSB_COMPLETED
;
3964 case LIBUSB_REQUEST_SET_INTERFACE
:
3965 r
= hid_set_interface_altsetting(0, transfer
->dev_handle
, setup
->index
, setup
->value
);
3966 if (r
== LIBUSB_SUCCESS
) {
3967 r
= LIBUSB_COMPLETED
;
3971 usbi_warn(ctx
, "unsupported HID control request");
3972 r
= LIBUSB_ERROR_INVALID_PARAM
;
3976 case LIBUSB_REQUEST_TYPE_CLASS
:
3977 r
=_hid_class_request(priv
->hid
, wfd
.handle
, setup
->request_type
, setup
->request
, setup
->value
,
3978 setup
->index
, transfer
->buffer
+ LIBUSB_CONTROL_SETUP_SIZE
, transfer_priv
,
3979 &size
, wfd
.overlapped
);
3982 usbi_warn(ctx
, "unsupported HID control request");
3983 r
= LIBUSB_ERROR_INVALID_PARAM
;
3987 if (r
== LIBUSB_COMPLETED
) {
3988 // Force request to be completed synchronously. Transferred size has been set by previous call
3989 wfd
.overlapped
->Internal
= STATUS_COMPLETED_SYNCHRONOUSLY
;
3990 // http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx
3991 // set InternalHigh to the number of bytes transferred
3992 wfd
.overlapped
->InternalHigh
= (DWORD
)size
;
3996 if (r
== LIBUSB_SUCCESS
) {
3997 // Use priv_transfer to store data needed for async polling
3998 transfer_priv
->pollable_fd
= wfd
;
3999 transfer_priv
->interface_number
= (uint8_t)current_interface
;
4007 static int hid_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
) {
4008 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4009 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
4010 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
4011 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
4012 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4015 bool direction_in
, ret
;
4016 int current_interface
, length
;
4018 int r
= LIBUSB_SUCCESS
;
4020 CHECK_HID_AVAILABLE
;
4022 transfer_priv
->pollable_fd
= INVALID_WINFD
;
4023 transfer_priv
->hid_dest
= NULL
;
4024 safe_free(transfer_priv
->hid_buffer
);
4026 current_interface
= interface_by_endpoint(priv
, handle_priv
, transfer
->endpoint
);
4027 if (current_interface
< 0) {
4028 usbi_err(ctx
, "unable to match endpoint to an open interface - cancelling transfer");
4029 return LIBUSB_ERROR_NOT_FOUND
;
4032 usbi_dbg("matched endpoint %02X with interface %d", transfer
->endpoint
, current_interface
);
4034 hid_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
4035 direction_in
= transfer
->endpoint
& LIBUSB_ENDPOINT_IN
;
4037 wfd
= usbi_create_fd(hid_handle
, direction_in
?RW_READ
:RW_WRITE
, NULL
, NULL
);
4038 // Always use the handle returned from usbi_create_fd (wfd.handle)
4040 return LIBUSB_ERROR_NO_MEM
;
4043 // If report IDs are not in use, an extra prefix byte must be added
4044 if ( ((direction_in
) && (!priv
->hid
->uses_report_ids
[0]))
4045 || ((!direction_in
) && (!priv
->hid
->uses_report_ids
[1])) ) {
4046 length
= transfer
->length
+1;
4048 length
= transfer
->length
;
4050 // Add a trailing byte to detect overflows on input
4051 transfer_priv
->hid_buffer
= (uint8_t*)calloc(length
+1, 1);
4052 if (transfer_priv
->hid_buffer
== NULL
) {
4053 return LIBUSB_ERROR_NO_MEM
;
4055 transfer_priv
->hid_expected_size
= length
;
4058 transfer_priv
->hid_dest
= transfer
->buffer
;
4059 usbi_dbg("reading %d bytes (report ID: 0x00)", length
);
4060 ret
= ReadFile(wfd
.handle
, transfer_priv
->hid_buffer
, length
+1, &size
, wfd
.overlapped
);
4062 if (!priv
->hid
->uses_report_ids
[1]) {
4063 memcpy(transfer_priv
->hid_buffer
+1, transfer
->buffer
, transfer
->length
);
4065 // We could actually do without the calloc and memcpy in this case
4066 memcpy(transfer_priv
->hid_buffer
, transfer
->buffer
, transfer
->length
);
4068 usbi_dbg("writing %d bytes (report ID: 0x%02X)", length
, transfer_priv
->hid_buffer
[0]);
4069 ret
= WriteFile(wfd
.handle
, transfer_priv
->hid_buffer
, length
, &size
, wfd
.overlapped
);
4072 if (GetLastError() != ERROR_IO_PENDING
) {
4073 usbi_err(ctx
, "HID transfer failed: %s", windows_error_str(0));
4075 safe_free(transfer_priv
->hid_buffer
);
4076 return LIBUSB_ERROR_IO
;
4079 // Only write operations that completed synchronously need to free up
4080 // hid_buffer. For reads, copy_transfer_data() handles that process.
4081 if (!direction_in
) {
4082 safe_free(transfer_priv
->hid_buffer
);
4085 usbi_err(ctx
, "program assertion failed - no data was transferred");
4088 if (size
> (size_t)length
) {
4089 usbi_err(ctx
, "OVERFLOW!");
4090 r
= LIBUSB_ERROR_OVERFLOW
;
4092 wfd
.overlapped
->Internal
= STATUS_COMPLETED_SYNCHRONOUSLY
;
4093 wfd
.overlapped
->InternalHigh
= size
;
4096 transfer_priv
->pollable_fd
= wfd
;
4097 transfer_priv
->interface_number
= (uint8_t)current_interface
;
4102 static int hid_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
)
4104 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4105 struct windows_transfer_priv
*transfer_priv
= (struct windows_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
4106 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
4108 int current_interface
;
4110 CHECK_HID_AVAILABLE
;
4112 current_interface
= transfer_priv
->interface_number
;
4113 hid_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
4114 CancelIo(hid_handle
);
4116 return LIBUSB_SUCCESS
;
4119 static int hid_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
)
4121 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
4123 int current_interface
;
4125 CHECK_HID_AVAILABLE
;
4127 // Flushing the queues on all interfaces is the best we can achieve
4128 for (current_interface
= 0; current_interface
< USB_MAXINTERFACES
; current_interface
++) {
4129 hid_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
4130 if ((hid_handle
!= 0) && (hid_handle
!= INVALID_HANDLE_VALUE
)) {
4131 HidD_FlushQueue(hid_handle
);
4134 return LIBUSB_SUCCESS
;
4137 static int hid_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
)
4139 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
4140 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
4141 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4143 int current_interface
;
4145 CHECK_HID_AVAILABLE
;
4147 current_interface
= interface_by_endpoint(priv
, handle_priv
, endpoint
);
4148 if (current_interface
< 0) {
4149 usbi_err(ctx
, "unable to match endpoint to an open interface - cannot clear");
4150 return LIBUSB_ERROR_NOT_FOUND
;
4153 usbi_dbg("matched endpoint %02X with interface %d", endpoint
, current_interface
);
4154 hid_handle
= handle_priv
->interface_handle
[current_interface
].api_handle
;
4156 // No endpoint selection with Microsoft's implementation, so we try to flush the
4157 // whole interface. Should be OK for most case scenarios
4158 if (!HidD_FlushQueue(hid_handle
)) {
4159 usbi_err(ctx
, "Flushing of HID queue failed: %s", windows_error_str(0));
4160 // Device was probably disconnected
4161 return LIBUSB_ERROR_NO_DEVICE
;
4164 return LIBUSB_SUCCESS
;
4167 // This extra function is only needed for HID
4168 static int hid_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
) {
4169 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4170 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
4171 struct windows_transfer_priv
*transfer_priv
= usbi_transfer_get_os_priv(itransfer
);
4172 int r
= LIBUSB_TRANSFER_COMPLETED
;
4173 uint32_t corrected_size
= io_size
;
4175 if (transfer_priv
->hid_buffer
!= NULL
) {
4176 // If we have a valid hid_buffer, it means the transfer was async
4177 if (transfer_priv
->hid_dest
!= NULL
) { // Data readout
4178 if (corrected_size
> 0) {
4179 // First, check for overflow
4180 if (corrected_size
> transfer_priv
->hid_expected_size
) {
4181 usbi_err(ctx
, "OVERFLOW!");
4182 corrected_size
= (uint32_t)transfer_priv
->hid_expected_size
;
4183 r
= LIBUSB_TRANSFER_OVERFLOW
;
4186 if (transfer_priv
->hid_buffer
[0] == 0) {
4187 // Discard the 1 byte report ID prefix
4189 memcpy(transfer_priv
->hid_dest
, transfer_priv
->hid_buffer
+1, corrected_size
);
4191 memcpy(transfer_priv
->hid_dest
, transfer_priv
->hid_buffer
, corrected_size
);
4194 transfer_priv
->hid_dest
= NULL
;
4196 // For write, we just need to free the hid buffer
4197 safe_free(transfer_priv
->hid_buffer
);
4199 itransfer
->transferred
+= corrected_size
;
4205 * Composite API functions
4207 static int composite_init(int sub_api
, struct libusb_context
*ctx
)
4209 return LIBUSB_SUCCESS
;
4212 static int composite_exit(int sub_api
)
4214 return LIBUSB_SUCCESS
;
4217 static int composite_open(int sub_api
, struct libusb_device_handle
*dev_handle
)
4219 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4220 int r
= LIBUSB_ERROR_NOT_FOUND
;
4222 // SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID
4223 bool available
[SUB_API_MAX
+1] = {0};
4225 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
4226 switch (priv
->usb_interface
[i
].apib
->id
) {
4227 case USB_API_WINUSBX
:
4228 if (priv
->usb_interface
[i
].sub_api
!= SUB_API_NOTSET
)
4229 available
[priv
->usb_interface
[i
].sub_api
] = true;
4232 available
[SUB_API_MAX
] = true;
4239 for (i
=0; i
<SUB_API_MAX
; i
++) { // WinUSB-like drivers
4241 r
= usb_api_backend
[USB_API_WINUSBX
].open(i
, dev_handle
);
4242 if (r
!= LIBUSB_SUCCESS
) {
4247 if (available
[SUB_API_MAX
]) { // HID driver
4248 r
= hid_open(SUB_API_NOTSET
, dev_handle
);
4253 static void composite_close(int sub_api
, struct libusb_device_handle
*dev_handle
)
4255 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4257 bool available
[SUB_API_MAX
];
4259 for (i
= 0; i
<SUB_API_MAX
; i
++) {
4260 available
[i
] = false;
4263 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
4264 if ( (priv
->usb_interface
[i
].apib
->id
== USB_API_WINUSBX
)
4265 && (priv
->usb_interface
[i
].sub_api
!= SUB_API_NOTSET
) ) {
4266 available
[priv
->usb_interface
[i
].sub_api
] = true;
4270 for (i
=0; i
<SUB_API_MAX
; i
++) {
4272 usb_api_backend
[USB_API_WINUSBX
].close(i
, dev_handle
);
4277 static int composite_claim_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
4279 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4280 return priv
->usb_interface
[iface
].apib
->
4281 claim_interface(priv
->usb_interface
[iface
].sub_api
, dev_handle
, iface
);
4284 static int composite_set_interface_altsetting(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
, int altsetting
)
4286 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4287 return priv
->usb_interface
[iface
].apib
->
4288 set_interface_altsetting(priv
->usb_interface
[iface
].sub_api
, dev_handle
, iface
, altsetting
);
4291 static int composite_release_interface(int sub_api
, struct libusb_device_handle
*dev_handle
, int iface
)
4293 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4294 return priv
->usb_interface
[iface
].apib
->
4295 release_interface(priv
->usb_interface
[iface
].sub_api
, dev_handle
, iface
);
4298 static int composite_submit_control_transfer(int sub_api
, struct usbi_transfer
*itransfer
)
4300 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4301 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
4302 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4305 // Interface shouldn't matter for control, but it does in practice, with Windows'
4306 // restrictions with regards to accessing HID keyboards and mice. Try a 2 pass approach
4307 for (pass
= 0; pass
< 2; pass
++) {
4308 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
4309 if (priv
->usb_interface
[i
].path
!= NULL
) {
4310 if ((pass
== 0) && (priv
->usb_interface
[i
].restricted_functionality
)) {
4311 usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", i
);
4314 usbi_dbg("using interface %d", i
);
4315 return priv
->usb_interface
[i
].apib
->submit_control_transfer(priv
->usb_interface
[i
].sub_api
, itransfer
);
4320 usbi_err(ctx
, "no libusbx supported interfaces to complete request");
4321 return LIBUSB_ERROR_NOT_FOUND
;
4324 static int composite_submit_bulk_transfer(int sub_api
, struct usbi_transfer
*itransfer
) {
4325 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4326 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
4327 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
4328 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4329 int current_interface
;
4331 current_interface
= interface_by_endpoint(priv
, handle_priv
, transfer
->endpoint
);
4332 if (current_interface
< 0) {
4333 usbi_err(ctx
, "unable to match endpoint to an open interface - cancelling transfer");
4334 return LIBUSB_ERROR_NOT_FOUND
;
4337 return priv
->usb_interface
[current_interface
].apib
->
4338 submit_bulk_transfer(priv
->usb_interface
[current_interface
].sub_api
, itransfer
);}
4340 static int composite_submit_iso_transfer(int sub_api
, struct usbi_transfer
*itransfer
) {
4341 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4342 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
4343 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(transfer
->dev_handle
);
4344 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4345 int current_interface
;
4347 current_interface
= interface_by_endpoint(priv
, handle_priv
, transfer
->endpoint
);
4348 if (current_interface
< 0) {
4349 usbi_err(ctx
, "unable to match endpoint to an open interface - cancelling transfer");
4350 return LIBUSB_ERROR_NOT_FOUND
;
4353 return priv
->usb_interface
[current_interface
].apib
->
4354 submit_iso_transfer(priv
->usb_interface
[current_interface
].sub_api
, itransfer
);}
4356 static int composite_clear_halt(int sub_api
, struct libusb_device_handle
*dev_handle
, unsigned char endpoint
)
4358 struct libusb_context
*ctx
= DEVICE_CTX(dev_handle
->dev
);
4359 struct windows_device_handle_priv
*handle_priv
= _device_handle_priv(dev_handle
);
4360 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4361 int current_interface
;
4363 current_interface
= interface_by_endpoint(priv
, handle_priv
, endpoint
);
4364 if (current_interface
< 0) {
4365 usbi_err(ctx
, "unable to match endpoint to an open interface - cannot clear");
4366 return LIBUSB_ERROR_NOT_FOUND
;
4369 return priv
->usb_interface
[current_interface
].apib
->
4370 clear_halt(priv
->usb_interface
[current_interface
].sub_api
, dev_handle
, endpoint
);}
4372 static int composite_abort_control(int sub_api
, struct usbi_transfer
*itransfer
)
4374 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4375 struct windows_transfer_priv
*transfer_priv
= usbi_transfer_get_os_priv(itransfer
);
4376 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4378 return priv
->usb_interface
[transfer_priv
->interface_number
].apib
->
4379 abort_control(priv
->usb_interface
[transfer_priv
->interface_number
].sub_api
, itransfer
);}
4381 static int composite_abort_transfers(int sub_api
, struct usbi_transfer
*itransfer
)
4383 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4384 struct windows_transfer_priv
*transfer_priv
= usbi_transfer_get_os_priv(itransfer
);
4385 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4387 return priv
->usb_interface
[transfer_priv
->interface_number
].apib
->
4388 abort_transfers(priv
->usb_interface
[transfer_priv
->interface_number
].sub_api
, itransfer
);}
4390 static int composite_reset_device(int sub_api
, struct libusb_device_handle
*dev_handle
)
4392 struct windows_device_priv
*priv
= _device_priv(dev_handle
->dev
);
4395 bool available
[SUB_API_MAX
];
4396 for (i
= 0; i
<SUB_API_MAX
; i
++) {
4397 available
[i
] = false;
4399 for (i
=0; i
<USB_MAXINTERFACES
; i
++) {
4400 if ( (priv
->usb_interface
[i
].apib
->id
== USB_API_WINUSBX
)
4401 && (priv
->usb_interface
[i
].sub_api
!= SUB_API_NOTSET
) ) {
4402 available
[priv
->usb_interface
[i
].sub_api
] = true;
4405 for (i
=0; i
<SUB_API_MAX
; i
++) {
4407 r
= usb_api_backend
[USB_API_WINUSBX
].reset_device(i
, dev_handle
);
4408 if (r
!= LIBUSB_SUCCESS
) {
4413 return LIBUSB_SUCCESS
;
4416 static int composite_copy_transfer_data(int sub_api
, struct usbi_transfer
*itransfer
, uint32_t io_size
)
4418 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
4419 struct windows_transfer_priv
*transfer_priv
= usbi_transfer_get_os_priv(itransfer
);
4420 struct windows_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
4422 return priv
->usb_interface
[transfer_priv
->interface_number
].apib
->
4423 copy_transfer_data(priv
->usb_interface
[transfer_priv
->interface_number
].sub_api
, itransfer
, io_size
);