1 /*
2 * windows backend for libusb 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
9 *
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.
14 *
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.
19 *
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
23 */
24
25 #include <config.h>
26
27 #include <process.h>
28 #include <stdio.h>
29
30 #include "libusbi.h"
31 #include "windows_common.h"
32
33 #define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
34
35 #define STATUS_SUCCESS ((ULONG_PTR)0UL)
36
37 // Public
38 enum windows_version windows_version = WINDOWS_UNDEFINED;
39
40 // Global variables for init/exit
41 static unsigned int init_count;
42 static bool usbdk_available;
43
44 /*
45 * Converts a windows error to human readable string
46 * uses retval as errorcode, or, if 0, use GetLastError()
47 */
48 #if defined(ENABLE_LOGGING)
windows_error_str(DWORD error_code)49 const char *windows_error_str(DWORD error_code)
50 {
51 static char err_string[256];
52
53 DWORD size;
54 int len;
55
56 if (error_code == 0)
57 error_code = GetLastError();
58
59 len = sprintf(err_string, "[%lu] ", ULONG_CAST(error_code));
60
61 // Translate codes returned by SetupAPI. The ones we are dealing with are either
62 // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
63 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
64 switch (error_code & 0xE0000000) {
65 case 0:
66 error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
67 break;
68 case 0xE0000000:
69 error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
70 break;
71 default:
72 break;
73 }
74
75 size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
76 NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
77 &err_string[len], sizeof(err_string) - len, NULL);
78 if (size == 0) {
79 DWORD format_error = GetLastError();
80 if (format_error)
81 snprintf(err_string, sizeof(err_string),
82 "Windows error code %lu (FormatMessage error code %lu)",
83 ULONG_CAST(error_code), ULONG_CAST(format_error));
84 else
85 snprintf(err_string, sizeof(err_string), "Unknown error code %lu",
86 ULONG_CAST(error_code));
87 } else {
88 // Remove CRLF from end of message, if present
89 size_t pos = len + size - 2;
90 if (err_string[pos] == '\r')
91 err_string[pos] = '\0';
92 }
93
94 return err_string;
95 }
96 #endif
97
98 /*
99 * Dynamically loads a DLL from the Windows system directory. Unlike the
100 * LoadLibraryA() function, this function will not search through any
101 * directories to try and find the library.
102 */
load_system_library(struct libusb_context * ctx,const char * name)103 HMODULE load_system_library(struct libusb_context *ctx, const char *name)
104 {
105 char library_path[MAX_PATH];
106 char *filename_start;
107 UINT length;
108
109 length = GetSystemDirectoryA(library_path, sizeof(library_path));
110 if ((length == 0) || (length >= (UINT)sizeof(library_path))) {
111 usbi_err(ctx, "program assertion failed - could not get system directory");
112 return NULL;
113 }
114
115 filename_start = library_path + length;
116 // Append '\' + name + ".dll" + NUL
117 length += 1 + (UINT)strlen(name) + 4 + 1;
118 if (length >= (UINT)sizeof(library_path)) {
119 usbi_err(ctx, "program assertion failed - library path buffer overflow");
120 return NULL;
121 }
122
123 sprintf(filename_start, "\\%s.dll", name);
124 return LoadLibraryA(library_path);
125 }
126
127 /* Hash table functions - modified From glibc 2.3.2:
128 [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
129 [Knuth] The Art of Computer Programming, part 3 (6.4) */
130
131 #define HTAB_SIZE 1021UL // *MUST* be a prime number!!
132
133 typedef struct htab_entry {
134 unsigned long used;
135 char *str;
136 } htab_entry;
137
138 static htab_entry *htab_table;
139 static usbi_mutex_t htab_mutex;
140 static unsigned long htab_filled;
141
142 /* Before using the hash table we must allocate memory for it.
143 We allocate one element more as the found prime number says.
144 This is done for more effective indexing as explained in the
145 comment for the hash function. */
htab_create(struct libusb_context * ctx)146 static bool htab_create(struct libusb_context *ctx)
147 {
148 if (htab_table != NULL) {
149 usbi_err(ctx, "program assertion failed - hash table already allocated");
150 return true;
151 }
152
153 // Create a mutex
154 usbi_mutex_init(&htab_mutex);
155
156 usbi_dbg("using %lu entries hash table", HTAB_SIZE);
157 htab_filled = 0;
158
159 // allocate memory and zero out.
160 htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry));
161 if (htab_table == NULL) {
162 usbi_err(ctx, "could not allocate space for hash table");
163 return false;
164 }
165
166 return true;
167 }
168
169 /* After using the hash table it has to be destroyed. */
htab_destroy(void)170 static void htab_destroy(void)
171 {
172 unsigned long i;
173
174 if (htab_table == NULL)
175 return;
176
177 for (i = 0; i < HTAB_SIZE; i++)
178 free(htab_table[i].str);
179
180 safe_free(htab_table);
181
182 usbi_mutex_destroy(&htab_mutex);
183 }
184
185 /* This is the search function. It uses double hashing with open addressing.
186 We use a trick to speed up the lookup. The table is created with one
187 more element available. This enables us to use the index zero special.
188 This index will never be used because we store the first hash index in
189 the field used where zero means not used. Every other value means used.
190 The used field can be used as a first fast comparison for equality of
191 the stored and the parameter value. This helps to prevent unnecessary
192 expensive calls of strcmp. */
htab_hash(const char * str)193 unsigned long htab_hash(const char *str)
194 {
195 unsigned long hval, hval2;
196 unsigned long idx;
197 unsigned long r = 5381UL;
198 int c;
199 const char *sz = str;
200
201 if (str == NULL)
202 return 0;
203
204 // Compute main hash value (algorithm suggested by Nokia)
205 while ((c = *sz++) != 0)
206 r = ((r << 5) + r) + c;
207 if (r == 0)
208 ++r;
209
210 // compute table hash: simply take the modulus
211 hval = r % HTAB_SIZE;
212 if (hval == 0)
213 ++hval;
214
215 // Try the first index
216 idx = hval;
217
218 // Mutually exclusive access (R/W lock would be better)
219 usbi_mutex_lock(&htab_mutex);
220
221 if (htab_table[idx].used) {
222 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
223 goto out_unlock; // existing hash
224
225 usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
226
227 // Second hash function, as suggested in [Knuth]
228 hval2 = 1UL + hval % (HTAB_SIZE - 2);
229
230 do {
231 // Because size is prime this guarantees to step through all available indexes
232 if (idx <= hval2)
233 idx = HTAB_SIZE + idx - hval2;
234 else
235 idx -= hval2;
236
237 // If we visited all entries leave the loop unsuccessfully
238 if (idx == hval)
239 break;
240
241 // If entry is found use it.
242 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
243 goto out_unlock;
244 } while (htab_table[idx].used);
245 }
246
247 // Not found => New entry
248
249 // If the table is full return an error
250 if (htab_filled >= HTAB_SIZE) {
251 usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
252 idx = 0UL;
253 goto out_unlock;
254 }
255
256 htab_table[idx].str = _strdup(str);
257 if (htab_table[idx].str == NULL) {
258 usbi_err(NULL, "could not duplicate string for hash table");
259 idx = 0UL;
260 goto out_unlock;
261 }
262
263 htab_table[idx].used = hval;
264 ++htab_filled;
265
266 out_unlock:
267 usbi_mutex_unlock(&htab_mutex);
268
269 return idx;
270 }
271
usbd_status_to_libusb_transfer_status(USBD_STATUS status)272 enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
273 {
274 if (USBD_SUCCESS(status))
275 return LIBUSB_TRANSFER_COMPLETED;
276
277 switch (status) {
278 case USBD_STATUS_TIMEOUT:
279 return LIBUSB_TRANSFER_TIMED_OUT;
280 case USBD_STATUS_CANCELED:
281 return LIBUSB_TRANSFER_CANCELLED;
282 case USBD_STATUS_ENDPOINT_HALTED:
283 return LIBUSB_TRANSFER_STALL;
284 case USBD_STATUS_DEVICE_GONE:
285 return LIBUSB_TRANSFER_NO_DEVICE;
286 default:
287 usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
288 return LIBUSB_TRANSFER_ERROR;
289 }
290 }
291
292 /*
293 * Make a transfer complete synchronously
294 */
windows_force_sync_completion(struct usbi_transfer * itransfer,ULONG size)295 void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size)
296 {
297 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
298 OVERLAPPED *overlapped = &transfer_priv->overlapped;
299
300 usbi_dbg("transfer %p, length %lu", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(size));
301
302 overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
303 overlapped->InternalHigh = (ULONG_PTR)size;
304
305 usbi_signal_transfer_completion(itransfer);
306 }
307
308 /* Windows version detection */
is_x64(void)309 static BOOL is_x64(void)
310 {
311 BOOL ret = FALSE;
312
313 // Detect if we're running a 32 or 64 bit system
314 if (sizeof(uintptr_t) < 8) {
315 IsWow64Process(GetCurrentProcess(), &ret);
316 } else {
317 ret = TRUE;
318 }
319
320 return ret;
321 }
322
get_windows_version(void)323 static enum windows_version get_windows_version(void)
324 {
325 enum windows_version winver;
326 OSVERSIONINFOEXA vi, vi2;
327 unsigned major, minor, version;
328 ULONGLONG major_equal, minor_equal;
329 const char *w, *arch;
330 bool ws;
331
332 memset(&vi, 0, sizeof(vi));
333 vi.dwOSVersionInfoSize = sizeof(vi);
334 if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
335 memset(&vi, 0, sizeof(vi));
336 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
337 if (!GetVersionExA((OSVERSIONINFOA *)&vi))
338 return WINDOWS_UNDEFINED;
339 }
340
341 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
342 return WINDOWS_UNDEFINED;
343
344 if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
345 // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
346 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
347
348 major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
349 for (major = vi.dwMajorVersion; major <= 9; major++) {
350 memset(&vi2, 0, sizeof(vi2));
351 vi2.dwOSVersionInfoSize = sizeof(vi2);
352 vi2.dwMajorVersion = major;
353 if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
354 continue;
355
356 if (vi.dwMajorVersion < major) {
357 vi.dwMajorVersion = major;
358 vi.dwMinorVersion = 0;
359 }
360
361 minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
362 for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
363 memset(&vi2, 0, sizeof(vi2));
364 vi2.dwOSVersionInfoSize = sizeof(vi2);
365 vi2.dwMinorVersion = minor;
366 if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
367 continue;
368
369 vi.dwMinorVersion = minor;
370 break;
371 }
372
373 break;
374 }
375 }
376
377 if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
378 return WINDOWS_UNDEFINED;
379
380 ws = (vi.wProductType <= VER_NT_WORKSTATION);
381 version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
382 switch (version) {
383 case 0x50: winver = WINDOWS_2000; w = "2000"; break;
384 case 0x51: winver = WINDOWS_XP; w = "XP"; break;
385 case 0x52: winver = WINDOWS_2003; w = "2003"; break;
386 case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break;
387 case 0x61: winver = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break;
388 case 0x62: winver = WINDOWS_8; w = (ws ? "8" : "2012"); break;
389 case 0x63: winver = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break;
390 case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
391 case 0xA0: winver = WINDOWS_10; w = (ws ? "10" : "2016"); break;
392 default:
393 if (version < 0x50)
394 return WINDOWS_UNDEFINED;
395 winver = WINDOWS_11_OR_LATER;
396 w = "11 or later";
397 }
398
399 arch = is_x64() ? "64-bit" : "32-bit";
400
401 if (vi.wServicePackMinor)
402 usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
403 else if (vi.wServicePackMajor)
404 usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
405 else
406 usbi_dbg("Windows %s %s", w, arch);
407
408 return winver;
409 }
410
windows_iocp_thread(void * arg)411 static unsigned __stdcall windows_iocp_thread(void *arg)
412 {
413 struct libusb_context *ctx = arg;
414 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
415 HANDLE iocp = priv->completion_port;
416 DWORD num_bytes;
417 ULONG_PTR completion_key;
418 OVERLAPPED *overlapped;
419 struct windows_transfer_priv *transfer_priv;
420 struct usbi_transfer *itransfer;
421
422 usbi_dbg("I/O completion thread started");
423
424 while (true) {
425 overlapped = NULL;
426 if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
427 usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
428 break;
429 }
430
431 if (overlapped == NULL) {
432 // Signal to quit
433 if (completion_key != (ULONG_PTR)ctx)
434 usbi_err(ctx, "program assertion failed - overlapped is NULL");
435 break;
436 }
437
438 transfer_priv = container_of(overlapped, struct windows_transfer_priv, overlapped);
439 itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
440 usbi_dbg("transfer %p completed, length %lu",
441 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes));
442 usbi_signal_transfer_completion(itransfer);
443 }
444
445 usbi_dbg("I/O completion thread exiting");
446
447 return 0;
448 }
449
windows_init(struct libusb_context * ctx)450 static int windows_init(struct libusb_context *ctx)
451 {
452 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
453 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
454 HANDLE mutex;
455 bool winusb_backend_init = false;
456 int r;
457
458 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
459 mutex = CreateMutexA(NULL, FALSE, mutex_name);
460 if (mutex == NULL) {
461 usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
462 return LIBUSB_ERROR_NO_MEM;
463 }
464
465 // A successful wait gives this thread ownership of the mutex
466 // => any concurrent wait stalls until the mutex is released
467 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
468 usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
469 CloseHandle(mutex);
470 return LIBUSB_ERROR_NO_MEM;
471 }
472
473 // NB: concurrent usage supposes that init calls are equally balanced with
474 // exit calls. If init is called more than exit, we will not exit properly
475 if (++init_count == 1) { // First init?
476 windows_version = get_windows_version();
477 if (windows_version == WINDOWS_UNDEFINED) {
478 usbi_err(ctx, "failed to detect Windows version");
479 r = LIBUSB_ERROR_NOT_SUPPORTED;
480 goto init_exit;
481 } else if (windows_version < WINDOWS_VISTA) {
482 usbi_err(ctx, "Windows version is too old");
483 r = LIBUSB_ERROR_NOT_SUPPORTED;
484 goto init_exit;
485 }
486
487 if (!htab_create(ctx)) {
488 r = LIBUSB_ERROR_NO_MEM;
489 goto init_exit;
490 }
491
492 r = winusb_backend.init(ctx);
493 if (r != LIBUSB_SUCCESS)
494 goto init_exit;
495 winusb_backend_init = true;
496
497 r = usbdk_backend.init(ctx);
498 if (r == LIBUSB_SUCCESS) {
499 usbi_dbg("UsbDk backend is available");
500 usbdk_available = true;
501 } else {
502 usbi_info(ctx, "UsbDk backend is not available");
503 // Do not report this as an error
504 }
505 }
506
507 // By default, new contexts will use the WinUSB backend
508 priv->backend = &winusb_backend;
509
510 r = LIBUSB_ERROR_NO_MEM;
511
512 // Use an I/O completion port to manage all transfers for this context
513 priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
514 if (priv->completion_port == NULL) {
515 usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
516 goto init_exit;
517 }
518
519 // And a dedicated thread to wait for I/O completions
520 priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
521 if (priv->completion_port_thread == NULL) {
522 usbi_err(ctx, "failed to create I/O completion port thread");
523 CloseHandle(priv->completion_port);
524 goto init_exit;
525 }
526
527 r = LIBUSB_SUCCESS;
528
529 init_exit: // Holds semaphore here
530 if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
531 if (usbdk_available) {
532 usbdk_backend.exit(ctx);
533 usbdk_available = false;
534 }
535 if (winusb_backend_init)
536 winusb_backend.exit(ctx);
537 htab_destroy();
538 --init_count;
539 }
540
541 ReleaseMutex(mutex);
542 CloseHandle(mutex);
543 return r;
544 }
545
windows_exit(struct libusb_context * ctx)546 static void windows_exit(struct libusb_context *ctx)
547 {
548 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
549 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
550 HANDLE mutex;
551
552 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
553 mutex = CreateMutexA(NULL, FALSE, mutex_name);
554 if (mutex == NULL)
555 return;
556
557 // A successful wait gives this thread ownership of the mutex
558 // => any concurrent wait stalls until the mutex is released
559 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
560 usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
561 CloseHandle(mutex);
562 return;
563 }
564
565 // A NULL completion status will indicate to the thread that it is time to exit
566 if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
567 usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
568
569 if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
570 usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
571
572 CloseHandle(priv->completion_port_thread);
573 CloseHandle(priv->completion_port);
574
575 // Only works if exits and inits are balanced exactly
576 if (--init_count == 0) { // Last exit
577 if (usbdk_available) {
578 usbdk_backend.exit(ctx);
579 usbdk_available = false;
580 }
581 winusb_backend.exit(ctx);
582 htab_destroy();
583 }
584
585 ReleaseMutex(mutex);
586 CloseHandle(mutex);
587 }
588
windows_set_option(struct libusb_context * ctx,enum libusb_option option,va_list ap)589 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
590 {
591 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
592
593 UNUSED(ap);
594
595 if (option == LIBUSB_OPTION_USE_USBDK) {
596 if (!usbdk_available) {
597 usbi_err(ctx, "UsbDk backend not available");
598 return LIBUSB_ERROR_NOT_FOUND;
599 }
600 usbi_dbg("switching context %p to use UsbDk backend", ctx);
601 priv->backend = &usbdk_backend;
602 return LIBUSB_SUCCESS;
603 }
604
605 return LIBUSB_ERROR_NOT_SUPPORTED;
606 }
607
windows_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)608 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
609 {
610 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
611 return priv->backend->get_device_list(ctx, discdevs);
612 }
613
windows_open(struct libusb_device_handle * dev_handle)614 static int windows_open(struct libusb_device_handle *dev_handle)
615 {
616 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
617 return priv->backend->open(dev_handle);
618 }
619
windows_close(struct libusb_device_handle * dev_handle)620 static void windows_close(struct libusb_device_handle *dev_handle)
621 {
622 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
623 priv->backend->close(dev_handle);
624 }
625
windows_get_active_config_descriptor(struct libusb_device * dev,void * buffer,size_t len)626 static int windows_get_active_config_descriptor(struct libusb_device *dev,
627 void *buffer, size_t len)
628 {
629 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
630 return priv->backend->get_active_config_descriptor(dev, buffer, len);
631 }
632
windows_get_config_descriptor(struct libusb_device * dev,uint8_t config_index,void * buffer,size_t len)633 static int windows_get_config_descriptor(struct libusb_device *dev,
634 uint8_t config_index, void *buffer, size_t len)
635 {
636 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
637 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
638 }
639
windows_get_config_descriptor_by_value(struct libusb_device * dev,uint8_t bConfigurationValue,void ** buffer)640 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
641 uint8_t bConfigurationValue, void **buffer)
642 {
643 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
644 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
645 }
646
windows_get_configuration(struct libusb_device_handle * dev_handle,uint8_t * config)647 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
648 {
649 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
650 return priv->backend->get_configuration(dev_handle, config);
651 }
652
windows_set_configuration(struct libusb_device_handle * dev_handle,int config)653 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
654 {
655 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
656 if (config == -1)
657 config = 0;
658 return priv->backend->set_configuration(dev_handle, (uint8_t)config);
659 }
660
windows_claim_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)661 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
662 {
663 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
664 return priv->backend->claim_interface(dev_handle, interface_number);
665 }
666
windows_release_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)667 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
668 {
669 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
670 return priv->backend->release_interface(dev_handle, interface_number);
671 }
672
windows_set_interface_altsetting(struct libusb_device_handle * dev_handle,uint8_t interface_number,uint8_t altsetting)673 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
674 uint8_t interface_number, uint8_t altsetting)
675 {
676 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
677 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
678 }
679
windows_clear_halt(struct libusb_device_handle * dev_handle,unsigned char endpoint)680 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
681 {
682 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
683 return priv->backend->clear_halt(dev_handle, endpoint);
684 }
685
windows_reset_device(struct libusb_device_handle * dev_handle)686 static int windows_reset_device(struct libusb_device_handle *dev_handle)
687 {
688 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
689 return priv->backend->reset_device(dev_handle);
690 }
691
windows_destroy_device(struct libusb_device * dev)692 static void windows_destroy_device(struct libusb_device *dev)
693 {
694 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
695 priv->backend->destroy_device(dev);
696 }
697
windows_submit_transfer(struct usbi_transfer * itransfer)698 static int windows_submit_transfer(struct usbi_transfer *itransfer)
699 {
700 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
701 struct libusb_context *ctx = TRANSFER_CTX(transfer);
702 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
703 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
704 int r;
705
706 switch (transfer->type) {
707 case LIBUSB_TRANSFER_TYPE_CONTROL:
708 case LIBUSB_TRANSFER_TYPE_BULK:
709 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
710 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
711 break;
712 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
713 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
714 return LIBUSB_ERROR_NOT_SUPPORTED;
715 default:
716 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
717 return LIBUSB_ERROR_INVALID_PARAM;
718 }
719
720 if (transfer_priv->handle != NULL) {
721 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
722 transfer_priv->handle = NULL;
723 }
724
725 r = priv->backend->submit_transfer(itransfer);
726 if (r != LIBUSB_SUCCESS) {
727 // Always call the backend's clear_transfer_priv() function on failure
728 priv->backend->clear_transfer_priv(itransfer);
729 transfer_priv->handle = NULL;
730 return r;
731 }
732
733 // The backend should set the HANDLE used for each submitted transfer
734 // by calling set_transfer_priv_handle()
735 if (transfer_priv->handle == NULL)
736 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
737
738 return r;
739 }
740
windows_cancel_transfer(struct usbi_transfer * itransfer)741 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
742 {
743 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
744 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
745
746 // Try CancelIoEx() on the transfer
747 // If that fails, fall back to the backend's cancel_transfer()
748 // function if it is available
749 if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
750 return LIBUSB_SUCCESS;
751 else if (GetLastError() == ERROR_NOT_FOUND)
752 return LIBUSB_ERROR_NOT_FOUND;
753
754 if (priv->backend->cancel_transfer)
755 return priv->backend->cancel_transfer(itransfer);
756
757 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
758 return LIBUSB_ERROR_NOT_SUPPORTED;
759 }
760
windows_handle_transfer_completion(struct usbi_transfer * itransfer)761 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
762 {
763 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
764 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
765 const struct windows_backend *backend = priv->backend;
766 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
767 enum libusb_transfer_status status, istatus;
768 DWORD result, bytes_transferred;
769
770 if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
771 result = NO_ERROR;
772 else
773 result = GetLastError();
774
775 usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
776 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
777
778 switch (result) {
779 case NO_ERROR:
780 status = backend->copy_transfer_data(itransfer, bytes_transferred);
781 break;
782 case ERROR_GEN_FAILURE:
783 usbi_dbg("detected endpoint stall");
784 status = LIBUSB_TRANSFER_STALL;
785 break;
786 case ERROR_SEM_TIMEOUT:
787 usbi_dbg("detected semaphore timeout");
788 status = LIBUSB_TRANSFER_TIMED_OUT;
789 break;
790 case ERROR_OPERATION_ABORTED:
791 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
792 if (istatus != LIBUSB_TRANSFER_COMPLETED)
793 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
794
795 usbi_dbg("detected operation aborted");
796 status = LIBUSB_TRANSFER_CANCELLED;
797 break;
798 case ERROR_FILE_NOT_FOUND:
799 case ERROR_DEVICE_NOT_CONNECTED:
800 case ERROR_NO_SUCH_DEVICE:
801 usbi_dbg("detected device removed");
802 status = LIBUSB_TRANSFER_NO_DEVICE;
803 break;
804 default:
805 usbi_err(ctx, "detected I/O error %lu: %s",
806 ULONG_CAST(result), windows_error_str(result));
807 status = LIBUSB_TRANSFER_ERROR;
808 break;
809 }
810
811 transfer_priv->handle = NULL;
812
813 // Backend-specific cleanup
814 backend->clear_transfer_priv(itransfer);
815
816 if (status == LIBUSB_TRANSFER_CANCELLED)
817 return usbi_handle_transfer_cancellation(itransfer);
818 else
819 return usbi_handle_transfer_completion(itransfer, status);
820 }
821
usbi_get_monotonic_time(struct timespec * tp)822 void usbi_get_monotonic_time(struct timespec *tp)
823 {
824 static LONG hires_counter_init;
825 static uint64_t hires_ticks_to_ps;
826 static uint64_t hires_frequency;
827 LARGE_INTEGER hires_counter;
828
829 if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
830 LARGE_INTEGER li_frequency;
831
832 // Microsoft says that the QueryPerformanceFrequency() and
833 // QueryPerformanceCounter() functions always succeed on XP and later
834 QueryPerformanceFrequency(&li_frequency);
835
836 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
837 // to picoseconds to compute the tv_nsecs part
838 hires_frequency = li_frequency.QuadPart;
839 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
840 }
841
842 QueryPerformanceCounter(&hires_counter);
843 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
844 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
845 }
846
847 // NB: MSVC6 does not support named initializers.
848 const struct usbi_os_backend usbi_backend = {
849 "Windows",
850 USBI_CAP_HAS_HID_ACCESS,
851 windows_init,
852 windows_exit,
853 windows_set_option,
854 windows_get_device_list,
855 NULL, /* hotplug_poll */
856 NULL, /* wrap_sys_device */
857 windows_open,
858 windows_close,
859 windows_get_active_config_descriptor,
860 windows_get_config_descriptor,
861 windows_get_config_descriptor_by_value,
862 windows_get_configuration,
863 windows_set_configuration,
864 windows_claim_interface,
865 windows_release_interface,
866 windows_set_interface_altsetting,
867 windows_clear_halt,
868 windows_reset_device,
869 NULL, /* alloc_streams */
870 NULL, /* free_streams */
871 NULL, /* dev_mem_alloc */
872 NULL, /* dev_mem_free */
873 NULL, /* kernel_driver_active */
874 NULL, /* detach_kernel_driver */
875 NULL, /* attach_kernel_driver */
876 windows_destroy_device,
877 windows_submit_transfer,
878 windows_cancel_transfer,
879 NULL, /* clear_transfer_priv */
880 NULL, /* handle_events */
881 windows_handle_transfer_completion,
882 sizeof(struct windows_context_priv),
883 sizeof(union windows_device_priv),
884 sizeof(union windows_device_handle_priv),
885 sizeof(struct windows_transfer_priv),
886 };
887