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 libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
298 struct windows_context_priv *priv = usbi_get_context_priv(TRANSFER_CTX(transfer));
299 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
300 OVERLAPPED *overlapped = &transfer_priv->overlapped;
301
302 usbi_dbg("transfer %p, length %lu", transfer, ULONG_CAST(size));
303
304 overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
305 overlapped->InternalHigh = (ULONG_PTR)size;
306
307 if (!PostQueuedCompletionStatus(priv->completion_port, (DWORD)size, (ULONG_PTR)transfer->dev_handle, overlapped))
308 usbi_err(TRANSFER_CTX(transfer), "failed to post I/O completion: %s", windows_error_str(0));
309 }
310
311 /* Windows version detection */
is_x64(void)312 static BOOL is_x64(void)
313 {
314 BOOL ret = FALSE;
315
316 // Detect if we're running a 32 or 64 bit system
317 if (sizeof(uintptr_t) < 8) {
318 IsWow64Process(GetCurrentProcess(), &ret);
319 } else {
320 ret = TRUE;
321 }
322
323 return ret;
324 }
325
get_windows_version(void)326 static enum windows_version get_windows_version(void)
327 {
328 enum windows_version winver;
329 OSVERSIONINFOEXA vi, vi2;
330 unsigned major, minor, version;
331 ULONGLONG major_equal, minor_equal;
332 const char *w, *arch;
333 bool ws;
334
335 memset(&vi, 0, sizeof(vi));
336 vi.dwOSVersionInfoSize = sizeof(vi);
337 if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
338 memset(&vi, 0, sizeof(vi));
339 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
340 if (!GetVersionExA((OSVERSIONINFOA *)&vi))
341 return WINDOWS_UNDEFINED;
342 }
343
344 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
345 return WINDOWS_UNDEFINED;
346
347 if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
348 // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
349 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
350
351 major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
352 for (major = vi.dwMajorVersion; major <= 9; major++) {
353 memset(&vi2, 0, sizeof(vi2));
354 vi2.dwOSVersionInfoSize = sizeof(vi2);
355 vi2.dwMajorVersion = major;
356 if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
357 continue;
358
359 if (vi.dwMajorVersion < major) {
360 vi.dwMajorVersion = major;
361 vi.dwMinorVersion = 0;
362 }
363
364 minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
365 for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
366 memset(&vi2, 0, sizeof(vi2));
367 vi2.dwOSVersionInfoSize = sizeof(vi2);
368 vi2.dwMinorVersion = minor;
369 if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
370 continue;
371
372 vi.dwMinorVersion = minor;
373 break;
374 }
375
376 break;
377 }
378 }
379
380 if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
381 return WINDOWS_UNDEFINED;
382
383 ws = (vi.wProductType <= VER_NT_WORKSTATION);
384 version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
385 switch (version) {
386 case 0x50: winver = WINDOWS_2000; w = "2000"; break;
387 case 0x51: winver = WINDOWS_XP; w = "XP"; break;
388 case 0x52: winver = WINDOWS_2003; w = "2003"; break;
389 case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break;
390 case 0x61: winver = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break;
391 case 0x62: winver = WINDOWS_8; w = (ws ? "8" : "2012"); break;
392 case 0x63: winver = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break;
393 case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
394 case 0xA0: winver = WINDOWS_10; w = (ws ? "10" : "2016"); break;
395 default:
396 if (version < 0x50)
397 return WINDOWS_UNDEFINED;
398 winver = WINDOWS_11_OR_LATER;
399 w = "11 or later";
400 }
401
402 arch = is_x64() ? "64-bit" : "32-bit";
403
404 if (vi.wServicePackMinor)
405 usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
406 else if (vi.wServicePackMajor)
407 usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
408 else
409 usbi_dbg("Windows %s %s", w, arch);
410
411 return winver;
412 }
413
windows_iocp_thread(void * arg)414 static unsigned __stdcall windows_iocp_thread(void *arg)
415 {
416 struct libusb_context *ctx = arg;
417 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
418 HANDLE iocp = priv->completion_port;
419 DWORD num_bytes;
420 ULONG_PTR completion_key;
421 OVERLAPPED *overlapped;
422 struct libusb_device_handle *dev_handle;
423 struct windows_device_handle_priv *handle_priv;
424 struct windows_transfer_priv *transfer_priv;
425 struct usbi_transfer *itransfer;
426 bool found;
427
428 usbi_dbg("I/O completion thread started");
429
430 while (true) {
431 overlapped = NULL;
432 if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
433 usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
434 break;
435 }
436
437 if (overlapped == NULL) {
438 // Signal to quit
439 if (completion_key != (ULONG_PTR)ctx)
440 usbi_err(ctx, "program assertion failed - overlapped is NULL");
441 break;
442 }
443
444 // Find the transfer associated with the OVERLAPPED that just completed.
445 // If we cannot find a match, the I/O operation originated from outside of libusb
446 // (e.g. within libusbK) and we need to ignore it.
447 dev_handle = (struct libusb_device_handle *)completion_key;
448 handle_priv = usbi_get_device_handle_priv(dev_handle);
449 found = false;
450 usbi_mutex_lock(&dev_handle->lock);
451 list_for_each_entry(transfer_priv, &handle_priv->active_transfers, list, struct windows_transfer_priv) {
452 if (overlapped == &transfer_priv->overlapped) {
453 // This OVERLAPPED belongs to us, remove the transfer from the device handle's list
454 list_del(&transfer_priv->list);
455 found = true;
456 break;
457 }
458 }
459 usbi_mutex_unlock(&dev_handle->lock);
460
461 if (!found) {
462 usbi_dbg("ignoring overlapped %p for handle %p (device %u.%u)",
463 overlapped, dev_handle, dev_handle->dev->bus_number, dev_handle->dev->device_address);
464 continue;
465 }
466
467 itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
468 usbi_dbg("transfer %p completed, length %lu",
469 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes));
470 usbi_signal_transfer_completion(itransfer);
471 }
472
473 usbi_dbg("I/O completion thread exiting");
474
475 return 0;
476 }
477
windows_init(struct libusb_context * ctx)478 static int windows_init(struct libusb_context *ctx)
479 {
480 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
481 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
482 HANDLE mutex;
483 bool winusb_backend_init = false;
484 int r;
485
486 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
487 mutex = CreateMutexA(NULL, FALSE, mutex_name);
488 if (mutex == NULL) {
489 usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
490 return LIBUSB_ERROR_NO_MEM;
491 }
492
493 // A successful wait gives this thread ownership of the mutex
494 // => any concurrent wait stalls until the mutex is released
495 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
496 usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
497 CloseHandle(mutex);
498 return LIBUSB_ERROR_NO_MEM;
499 }
500
501 // NB: concurrent usage supposes that init calls are equally balanced with
502 // exit calls. If init is called more than exit, we will not exit properly
503 if (++init_count == 1) { // First init?
504 windows_version = get_windows_version();
505 if (windows_version == WINDOWS_UNDEFINED) {
506 usbi_err(ctx, "failed to detect Windows version");
507 r = LIBUSB_ERROR_NOT_SUPPORTED;
508 goto init_exit;
509 } else if (windows_version < WINDOWS_VISTA) {
510 usbi_err(ctx, "Windows version is too old");
511 r = LIBUSB_ERROR_NOT_SUPPORTED;
512 goto init_exit;
513 }
514
515 if (!htab_create(ctx)) {
516 r = LIBUSB_ERROR_NO_MEM;
517 goto init_exit;
518 }
519
520 r = winusb_backend.init(ctx);
521 if (r != LIBUSB_SUCCESS)
522 goto init_exit;
523 winusb_backend_init = true;
524
525 r = usbdk_backend.init(ctx);
526 if (r == LIBUSB_SUCCESS) {
527 usbi_dbg("UsbDk backend is available");
528 usbdk_available = true;
529 } else {
530 usbi_info(ctx, "UsbDk backend is not available");
531 // Do not report this as an error
532 }
533 }
534
535 // By default, new contexts will use the WinUSB backend
536 priv->backend = &winusb_backend;
537
538 r = LIBUSB_ERROR_NO_MEM;
539
540 // Use an I/O completion port to manage all transfers for this context
541 priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
542 if (priv->completion_port == NULL) {
543 usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
544 goto init_exit;
545 }
546
547 // And a dedicated thread to wait for I/O completions
548 priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
549 if (priv->completion_port_thread == NULL) {
550 usbi_err(ctx, "failed to create I/O completion port thread");
551 CloseHandle(priv->completion_port);
552 goto init_exit;
553 }
554
555 r = LIBUSB_SUCCESS;
556
557 init_exit: // Holds semaphore here
558 if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
559 if (usbdk_available) {
560 usbdk_backend.exit(ctx);
561 usbdk_available = false;
562 }
563 if (winusb_backend_init)
564 winusb_backend.exit(ctx);
565 htab_destroy();
566 --init_count;
567 }
568
569 ReleaseMutex(mutex);
570 CloseHandle(mutex);
571 return r;
572 }
573
windows_exit(struct libusb_context * ctx)574 static void windows_exit(struct libusb_context *ctx)
575 {
576 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
577 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
578 HANDLE mutex;
579
580 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
581 mutex = CreateMutexA(NULL, FALSE, mutex_name);
582 if (mutex == NULL)
583 return;
584
585 // A successful wait gives this thread ownership of the mutex
586 // => any concurrent wait stalls until the mutex is released
587 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
588 usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
589 CloseHandle(mutex);
590 return;
591 }
592
593 // A NULL completion status will indicate to the thread that it is time to exit
594 if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
595 usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
596
597 if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
598 usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
599
600 CloseHandle(priv->completion_port_thread);
601 CloseHandle(priv->completion_port);
602
603 // Only works if exits and inits are balanced exactly
604 if (--init_count == 0) { // Last exit
605 if (usbdk_available) {
606 usbdk_backend.exit(ctx);
607 usbdk_available = false;
608 }
609 winusb_backend.exit(ctx);
610 htab_destroy();
611 }
612
613 ReleaseMutex(mutex);
614 CloseHandle(mutex);
615 }
616
windows_set_option(struct libusb_context * ctx,enum libusb_option option,va_list ap)617 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
618 {
619 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
620
621 UNUSED(ap);
622
623 if (option == LIBUSB_OPTION_USE_USBDK) {
624 if (!usbdk_available) {
625 usbi_err(ctx, "UsbDk backend not available");
626 return LIBUSB_ERROR_NOT_FOUND;
627 }
628 usbi_dbg("switching context %p to use UsbDk backend", ctx);
629 priv->backend = &usbdk_backend;
630 return LIBUSB_SUCCESS;
631 }
632
633 return LIBUSB_ERROR_NOT_SUPPORTED;
634 }
635
windows_get_device_list(struct libusb_context * ctx,struct discovered_devs ** discdevs)636 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
637 {
638 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
639 return priv->backend->get_device_list(ctx, discdevs);
640 }
641
windows_open(struct libusb_device_handle * dev_handle)642 static int windows_open(struct libusb_device_handle *dev_handle)
643 {
644 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
645 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
646
647 list_init(&handle_priv->active_transfers);
648 return priv->backend->open(dev_handle);
649 }
650
windows_close(struct libusb_device_handle * dev_handle)651 static void windows_close(struct libusb_device_handle *dev_handle)
652 {
653 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
654 priv->backend->close(dev_handle);
655 }
656
windows_get_active_config_descriptor(struct libusb_device * dev,void * buffer,size_t len)657 static int windows_get_active_config_descriptor(struct libusb_device *dev,
658 void *buffer, size_t len)
659 {
660 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
661 return priv->backend->get_active_config_descriptor(dev, buffer, len);
662 }
663
windows_get_config_descriptor(struct libusb_device * dev,uint8_t config_index,void * buffer,size_t len)664 static int windows_get_config_descriptor(struct libusb_device *dev,
665 uint8_t config_index, void *buffer, size_t len)
666 {
667 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
668 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
669 }
670
windows_get_config_descriptor_by_value(struct libusb_device * dev,uint8_t bConfigurationValue,void ** buffer)671 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
672 uint8_t bConfigurationValue, void **buffer)
673 {
674 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
675 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
676 }
677
windows_get_configuration(struct libusb_device_handle * dev_handle,uint8_t * config)678 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
679 {
680 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
681 return priv->backend->get_configuration(dev_handle, config);
682 }
683
windows_set_configuration(struct libusb_device_handle * dev_handle,int config)684 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
685 {
686 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
687 if (config == -1)
688 config = 0;
689 return priv->backend->set_configuration(dev_handle, (uint8_t)config);
690 }
691
windows_claim_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)692 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
693 {
694 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
695 return priv->backend->claim_interface(dev_handle, interface_number);
696 }
697
windows_release_interface(struct libusb_device_handle * dev_handle,uint8_t interface_number)698 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
699 {
700 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
701 return priv->backend->release_interface(dev_handle, interface_number);
702 }
703
windows_set_interface_altsetting(struct libusb_device_handle * dev_handle,uint8_t interface_number,uint8_t altsetting)704 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
705 uint8_t interface_number, uint8_t altsetting)
706 {
707 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
708 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
709 }
710
windows_clear_halt(struct libusb_device_handle * dev_handle,unsigned char endpoint)711 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
712 {
713 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
714 return priv->backend->clear_halt(dev_handle, endpoint);
715 }
716
windows_reset_device(struct libusb_device_handle * dev_handle)717 static int windows_reset_device(struct libusb_device_handle *dev_handle)
718 {
719 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
720 return priv->backend->reset_device(dev_handle);
721 }
722
windows_destroy_device(struct libusb_device * dev)723 static void windows_destroy_device(struct libusb_device *dev)
724 {
725 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
726 priv->backend->destroy_device(dev);
727 }
728
windows_submit_transfer(struct usbi_transfer * itransfer)729 static int windows_submit_transfer(struct usbi_transfer *itransfer)
730 {
731 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
732 struct libusb_device_handle *dev_handle = transfer->dev_handle;
733 struct libusb_context *ctx = HANDLE_CTX(dev_handle);
734 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
735 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
736 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
737 int r;
738
739 switch (transfer->type) {
740 case LIBUSB_TRANSFER_TYPE_CONTROL:
741 case LIBUSB_TRANSFER_TYPE_BULK:
742 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
743 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
744 break;
745 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
746 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
747 return LIBUSB_ERROR_NOT_SUPPORTED;
748 default:
749 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
750 return LIBUSB_ERROR_INVALID_PARAM;
751 }
752
753 if (transfer_priv->handle != NULL) {
754 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
755 transfer_priv->handle = NULL;
756 }
757
758 // Add transfer to the device handle's list
759 usbi_mutex_lock(&dev_handle->lock);
760 list_add_tail(&transfer_priv->list, &handle_priv->active_transfers);
761 usbi_mutex_unlock(&dev_handle->lock);
762
763 r = priv->backend->submit_transfer(itransfer);
764 if (r != LIBUSB_SUCCESS) {
765 // Remove the unsuccessful transfer from the device handle's list
766 usbi_mutex_lock(&dev_handle->lock);
767 list_del(&transfer_priv->list);
768 usbi_mutex_unlock(&dev_handle->lock);
769
770 // Always call the backend's clear_transfer_priv() function on failure
771 priv->backend->clear_transfer_priv(itransfer);
772 transfer_priv->handle = NULL;
773 return r;
774 }
775
776 // The backend should set the HANDLE used for each submitted transfer
777 // by calling set_transfer_priv_handle()
778 if (transfer_priv->handle == NULL)
779 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
780
781 return r;
782 }
783
windows_cancel_transfer(struct usbi_transfer * itransfer)784 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
785 {
786 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
787 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
788
789 // Try CancelIoEx() on the transfer
790 // If that fails, fall back to the backend's cancel_transfer()
791 // function if it is available
792 if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
793 return LIBUSB_SUCCESS;
794 else if (GetLastError() == ERROR_NOT_FOUND)
795 return LIBUSB_ERROR_NOT_FOUND;
796
797 if (priv->backend->cancel_transfer)
798 return priv->backend->cancel_transfer(itransfer);
799
800 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
801 return LIBUSB_ERROR_NOT_SUPPORTED;
802 }
803
windows_handle_transfer_completion(struct usbi_transfer * itransfer)804 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
805 {
806 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
807 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
808 const struct windows_backend *backend = priv->backend;
809 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
810 enum libusb_transfer_status status, istatus;
811 DWORD result, bytes_transferred;
812
813 if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
814 result = NO_ERROR;
815 else
816 result = GetLastError();
817
818 usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
819 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
820
821 switch (result) {
822 case NO_ERROR:
823 status = backend->copy_transfer_data(itransfer, bytes_transferred);
824 break;
825 case ERROR_GEN_FAILURE:
826 usbi_dbg("detected endpoint stall");
827 status = LIBUSB_TRANSFER_STALL;
828 break;
829 case ERROR_SEM_TIMEOUT:
830 usbi_dbg("detected semaphore timeout");
831 status = LIBUSB_TRANSFER_TIMED_OUT;
832 break;
833 case ERROR_OPERATION_ABORTED:
834 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
835 if (istatus != LIBUSB_TRANSFER_COMPLETED)
836 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
837
838 usbi_dbg("detected operation aborted");
839 status = LIBUSB_TRANSFER_CANCELLED;
840 break;
841 case ERROR_FILE_NOT_FOUND:
842 case ERROR_DEVICE_NOT_CONNECTED:
843 case ERROR_NO_SUCH_DEVICE:
844 usbi_dbg("detected device removed");
845 status = LIBUSB_TRANSFER_NO_DEVICE;
846 break;
847 default:
848 usbi_err(ctx, "detected I/O error %lu: %s",
849 ULONG_CAST(result), windows_error_str(result));
850 status = LIBUSB_TRANSFER_ERROR;
851 break;
852 }
853
854 transfer_priv->handle = NULL;
855
856 // Backend-specific cleanup
857 backend->clear_transfer_priv(itransfer);
858
859 if (status == LIBUSB_TRANSFER_CANCELLED)
860 return usbi_handle_transfer_cancellation(itransfer);
861 else
862 return usbi_handle_transfer_completion(itransfer, status);
863 }
864
usbi_get_monotonic_time(struct timespec * tp)865 void usbi_get_monotonic_time(struct timespec *tp)
866 {
867 static LONG hires_counter_init;
868 static uint64_t hires_ticks_to_ps;
869 static uint64_t hires_frequency;
870 LARGE_INTEGER hires_counter;
871
872 if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
873 LARGE_INTEGER li_frequency;
874
875 // Microsoft says that the QueryPerformanceFrequency() and
876 // QueryPerformanceCounter() functions always succeed on XP and later
877 QueryPerformanceFrequency(&li_frequency);
878
879 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
880 // to picoseconds to compute the tv_nsecs part
881 hires_frequency = li_frequency.QuadPart;
882 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
883 }
884
885 QueryPerformanceCounter(&hires_counter);
886 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
887 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
888 }
889
890 // NB: MSVC6 does not support named initializers.
891 const struct usbi_os_backend usbi_backend = {
892 "Windows",
893 USBI_CAP_HAS_HID_ACCESS,
894 windows_init,
895 windows_exit,
896 windows_set_option,
897 windows_get_device_list,
898 NULL, /* hotplug_poll */
899 NULL, /* wrap_sys_device */
900 windows_open,
901 windows_close,
902 windows_get_active_config_descriptor,
903 windows_get_config_descriptor,
904 windows_get_config_descriptor_by_value,
905 windows_get_configuration,
906 windows_set_configuration,
907 windows_claim_interface,
908 windows_release_interface,
909 windows_set_interface_altsetting,
910 windows_clear_halt,
911 windows_reset_device,
912 NULL, /* alloc_streams */
913 NULL, /* free_streams */
914 NULL, /* dev_mem_alloc */
915 NULL, /* dev_mem_free */
916 NULL, /* kernel_driver_active */
917 NULL, /* detach_kernel_driver */
918 NULL, /* attach_kernel_driver */
919 windows_destroy_device,
920 windows_submit_transfer,
921 windows_cancel_transfer,
922 NULL, /* clear_transfer_priv */
923 NULL, /* handle_events */
924 windows_handle_transfer_completion,
925 sizeof(struct windows_context_priv),
926 sizeof(union windows_device_priv),
927 sizeof(struct windows_device_handle_priv),
928 sizeof(struct windows_transfer_priv),
929 };
930