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
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
31 #include "windows_common.h"
33 #define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
35 #define STATUS_SUCCESS ((ULONG_PTR)0UL)
38 enum windows_version windows_version = WINDOWS_UNDEFINED;
40 // Global variables for init/exit
41 static unsigned int init_count;
42 static bool usbdk_available;
45 * Converts a windows error to human readable string
46 * uses retval as errorcode, or, if 0, use GetLastError()
48 #if defined(ENABLE_LOGGING)
49 const char *windows_error_str(DWORD error_code)
51 static char err_string[256];
57 error_code = GetLastError();
59 len = sprintf(err_string, "[%lu] ", ULONG_CAST(error_code));
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) {
66 error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
69 error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
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);
79 DWORD format_error = GetLastError();
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));
85 snprintf(err_string, sizeof(err_string), "Unknown error code %lu",
86 ULONG_CAST(error_code));
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';
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.
103 HMODULE load_system_library(struct libusb_context *ctx, const char *name)
105 char library_path[MAX_PATH];
106 char *filename_start;
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");
115 filename_start = library_path + length;
116 // Append '\' + name + ".dll" + NUL
117 length += 1 + strlen(name) + 4 + 1;
118 if (length >= (UINT)sizeof(library_path)) {
119 usbi_err(ctx, "program assertion failed - library path buffer overflow");
123 sprintf(filename_start, "\\%s.dll", name);
124 return LoadLibraryA(library_path);
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) */
131 #define HTAB_SIZE 1021UL // *MUST* be a prime number!!
133 typedef struct htab_entry {
138 static htab_entry *htab_table;
139 static usbi_mutex_t htab_mutex;
140 static unsigned long htab_filled;
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. */
146 static bool htab_create(struct libusb_context *ctx)
148 if (htab_table != NULL) {
149 usbi_err(ctx, "program assertion failed - hash table already allocated");
154 usbi_mutex_init(&htab_mutex);
156 usbi_dbg("using %lu entries hash table", HTAB_SIZE);
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");
169 /* After using the hash table it has to be destroyed. */
170 static void htab_destroy(void)
174 if (htab_table == NULL)
177 for (i = 0; i < HTAB_SIZE; i++)
178 free(htab_table[i].str);
180 safe_free(htab_table);
182 usbi_mutex_destroy(&htab_mutex);
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. */
193 unsigned long htab_hash(const char *str)
195 unsigned long hval, hval2;
197 unsigned long r = 5381UL;
199 const char *sz = str;
204 // Compute main hash value (algorithm suggested by Nokia)
205 while ((c = *sz++) != 0)
206 r = ((r << 5) + r) + c;
210 // compute table hash: simply take the modulus
211 hval = r % HTAB_SIZE;
215 // Try the first index
218 // Mutually exclusive access (R/W lock would be better)
219 usbi_mutex_lock(&htab_mutex);
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
225 usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
227 // Second hash function, as suggested in [Knuth]
228 hval2 = 1UL + hval % (HTAB_SIZE - 2);
231 // Because size is prime this guarantees to step through all available indexes
233 idx = HTAB_SIZE + idx - hval2;
237 // If we visited all entries leave the loop unsuccessfully
241 // If entry is found use it.
242 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
244 } while (htab_table[idx].used);
247 // Not found => New entry
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);
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");
263 htab_table[idx].used = hval;
267 usbi_mutex_unlock(&htab_mutex);
272 enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
274 if (USBD_SUCCESS(status))
275 return LIBUSB_TRANSFER_COMPLETED;
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;
287 usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
288 return LIBUSB_TRANSFER_ERROR;
293 * Make a transfer complete synchronously
295 void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size)
297 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
298 OVERLAPPED *overlapped = &transfer_priv->overlapped;
300 usbi_dbg("transfer %p, length %lu", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), size);
302 overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
303 overlapped->InternalHigh = (ULONG_PTR)size;
305 usbi_signal_transfer_completion(itransfer);
308 /* Windows version detection */
309 static BOOL is_x64(void)
313 // Detect if we're running a 32 or 64 bit system
314 if (sizeof(uintptr_t) < 8) {
315 IsWow64Process(GetCurrentProcess(), &ret);
323 static enum windows_version get_windows_version(void)
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;
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;
341 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
342 return WINDOWS_UNDEFINED;
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
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))
356 if (vi.dwMajorVersion < major) {
357 vi.dwMajorVersion = major;
358 vi.dwMinorVersion = 0;
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))
369 vi.dwMinorVersion = minor;
377 if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
378 return WINDOWS_UNDEFINED;
380 ws = (vi.wProductType <= VER_NT_WORKSTATION);
381 version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
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;
394 return WINDOWS_UNDEFINED;
395 winver = WINDOWS_11_OR_LATER;
399 arch = is_x64() ? "64-bit" : "32-bit";
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);
406 usbi_dbg("Windows %s %s", w, arch);
411 static unsigned __stdcall windows_iocp_thread(void *arg)
413 struct libusb_context *ctx = arg;
414 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
415 HANDLE iocp = priv->completion_port;
417 ULONG_PTR completion_key;
418 OVERLAPPED *overlapped;
419 struct windows_transfer_priv *transfer_priv;
420 struct usbi_transfer *itransfer;
422 usbi_dbg("I/O completion thread started");
426 if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
427 usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
431 if (overlapped == NULL) {
433 if (completion_key != (ULONG_PTR)ctx)
434 usbi_err(ctx, "program assertion failed - overlapped is NULL");
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);
445 usbi_dbg("I/O completion thread exiting");
450 static int windows_init(struct libusb_context *ctx)
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'
455 bool winusb_backend_init = false;
458 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
459 mutex = CreateMutexA(NULL, FALSE, mutex_name);
461 usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
462 return LIBUSB_ERROR_NO_MEM;
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));
470 return LIBUSB_ERROR_NO_MEM;
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;
481 } else if (windows_version < WINDOWS_VISTA) {
482 usbi_err(ctx, "Windows version is too old");
483 r = LIBUSB_ERROR_NOT_SUPPORTED;
487 if (!htab_create(ctx)) {
488 r = LIBUSB_ERROR_NO_MEM;
492 r = winusb_backend.init(ctx);
493 if (r != LIBUSB_SUCCESS)
495 winusb_backend_init = true;
497 r = usbdk_backend.init(ctx);
498 if (r == LIBUSB_SUCCESS) {
499 usbi_dbg("UsbDk backend is available");
500 usbdk_available = true;
502 usbi_info(ctx, "UsbDk backend is not available");
503 // Do not report this as an error
507 // By default, new contexts will use the WinUSB backend
508 priv->backend = &winusb_backend;
510 r = LIBUSB_ERROR_NO_MEM;
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));
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);
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;
535 if (winusb_backend_init)
536 winusb_backend.exit(ctx);
546 static void windows_exit(struct libusb_context *ctx)
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'
552 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
553 mutex = CreateMutexA(NULL, FALSE, mutex_name);
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));
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));
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));
572 CloseHandle(priv->completion_port_thread);
573 CloseHandle(priv->completion_port);
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;
581 winusb_backend.exit(ctx);
589 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
591 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
595 switch ((int)option) {
596 case LIBUSB_OPTION_USE_USBDK:
597 if (usbdk_available) {
598 usbi_dbg("switching context %p to use UsbDk backend", ctx);
599 priv->backend = &usbdk_backend;
601 usbi_err(ctx, "UsbDk backend not available");
602 return LIBUSB_ERROR_NOT_FOUND;
604 return LIBUSB_SUCCESS;
606 return LIBUSB_ERROR_NOT_SUPPORTED;
610 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
612 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
613 return priv->backend->get_device_list(ctx, discdevs);
616 static int windows_open(struct libusb_device_handle *dev_handle)
618 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
619 return priv->backend->open(dev_handle);
622 static void windows_close(struct libusb_device_handle *dev_handle)
624 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
625 priv->backend->close(dev_handle);
628 static int windows_get_active_config_descriptor(struct libusb_device *dev,
629 void *buffer, size_t len)
631 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
632 return priv->backend->get_active_config_descriptor(dev, buffer, len);
635 static int windows_get_config_descriptor(struct libusb_device *dev,
636 uint8_t config_index, void *buffer, size_t len)
638 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
639 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
642 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
643 uint8_t bConfigurationValue, void **buffer)
645 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
646 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
649 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
651 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
652 return priv->backend->get_configuration(dev_handle, config);
655 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
657 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
660 return priv->backend->set_configuration(dev_handle, (uint8_t)config);
663 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
665 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
666 return priv->backend->claim_interface(dev_handle, interface_number);
669 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
671 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
672 return priv->backend->release_interface(dev_handle, interface_number);
675 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
676 uint8_t interface_number, uint8_t altsetting)
678 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
679 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
682 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
684 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
685 return priv->backend->clear_halt(dev_handle, endpoint);
688 static int windows_reset_device(struct libusb_device_handle *dev_handle)
690 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
691 return priv->backend->reset_device(dev_handle);
694 static void windows_destroy_device(struct libusb_device *dev)
696 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
697 priv->backend->destroy_device(dev);
700 static int windows_submit_transfer(struct usbi_transfer *itransfer)
702 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
703 struct libusb_context *ctx = TRANSFER_CTX(transfer);
704 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
705 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
708 switch (transfer->type) {
709 case LIBUSB_TRANSFER_TYPE_CONTROL:
710 case LIBUSB_TRANSFER_TYPE_BULK:
711 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
712 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
714 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
715 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
716 return LIBUSB_ERROR_NOT_SUPPORTED;
718 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
719 return LIBUSB_ERROR_INVALID_PARAM;
722 if (transfer_priv->handle != NULL) {
723 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
724 transfer_priv->handle = NULL;
727 r = priv->backend->submit_transfer(itransfer);
728 if (r != LIBUSB_SUCCESS) {
729 // Always call the backend's clear_transfer_priv() function on failure
730 priv->backend->clear_transfer_priv(itransfer);
731 transfer_priv->handle = NULL;
735 // The backend should set the HANDLE used for each submitted transfer
736 // by calling set_transfer_priv_handle()
737 if (transfer_priv->handle == NULL)
738 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
743 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
745 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
746 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
748 // Try CancelIoEx() on the transfer
749 // If that fails, fall back to the backend's cancel_transfer()
750 // function if it is available
751 if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
752 return LIBUSB_SUCCESS;
753 else if (GetLastError() == ERROR_NOT_FOUND)
754 return LIBUSB_ERROR_NOT_FOUND;
756 if (priv->backend->cancel_transfer)
757 return priv->backend->cancel_transfer(itransfer);
759 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
760 return LIBUSB_ERROR_NOT_SUPPORTED;
763 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
765 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
766 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
767 const struct windows_backend *backend = priv->backend;
768 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
769 enum libusb_transfer_status status, istatus;
770 DWORD result, bytes_transferred;
772 if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
775 result = GetLastError();
777 usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
778 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
782 status = backend->copy_transfer_data(itransfer, bytes_transferred);
784 case ERROR_GEN_FAILURE:
785 usbi_dbg("detected endpoint stall");
786 status = LIBUSB_TRANSFER_STALL;
788 case ERROR_SEM_TIMEOUT:
789 usbi_dbg("detected semaphore timeout");
790 status = LIBUSB_TRANSFER_TIMED_OUT;
792 case ERROR_OPERATION_ABORTED:
793 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
794 if (istatus != LIBUSB_TRANSFER_COMPLETED)
795 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
797 usbi_dbg("detected operation aborted");
798 status = LIBUSB_TRANSFER_CANCELLED;
800 case ERROR_FILE_NOT_FOUND:
801 case ERROR_DEVICE_NOT_CONNECTED:
802 case ERROR_NO_SUCH_DEVICE:
803 usbi_dbg("detected device removed");
804 status = LIBUSB_TRANSFER_NO_DEVICE;
807 usbi_err(ctx, "detected I/O error %lu: %s",
808 ULONG_CAST(result), windows_error_str(result));
809 status = LIBUSB_TRANSFER_ERROR;
813 transfer_priv->handle = NULL;
815 // Backend-specific cleanup
816 backend->clear_transfer_priv(itransfer);
818 if (status == LIBUSB_TRANSFER_CANCELLED)
819 return usbi_handle_transfer_cancellation(itransfer);
821 return usbi_handle_transfer_completion(itransfer, status);
824 void usbi_get_monotonic_time(struct timespec *tp)
826 static LONG hires_counter_init;
827 static uint64_t hires_ticks_to_ps;
828 static uint64_t hires_frequency;
829 LARGE_INTEGER hires_counter;
831 if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
832 LARGE_INTEGER li_frequency;
834 // Microsoft says that the QueryPerformanceFrequency() and
835 // QueryPerformanceCounter() functions always succeed on XP and later
836 QueryPerformanceFrequency(&li_frequency);
838 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
839 // to picoseconds to compute the tv_nsecs part
840 hires_frequency = li_frequency.QuadPart;
841 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
844 QueryPerformanceCounter(&hires_counter);
845 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
846 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
849 // NB: MSVC6 does not support named initializers.
850 const struct usbi_os_backend usbi_backend = {
852 USBI_CAP_HAS_HID_ACCESS,
856 windows_get_device_list,
857 NULL, /* hotplug_poll */
858 NULL, /* wrap_sys_device */
861 windows_get_active_config_descriptor,
862 windows_get_config_descriptor,
863 windows_get_config_descriptor_by_value,
864 windows_get_configuration,
865 windows_set_configuration,
866 windows_claim_interface,
867 windows_release_interface,
868 windows_set_interface_altsetting,
870 windows_reset_device,
871 NULL, /* alloc_streams */
872 NULL, /* free_streams */
873 NULL, /* dev_mem_alloc */
874 NULL, /* dev_mem_free */
875 NULL, /* kernel_driver_active */
876 NULL, /* detach_kernel_driver */
877 NULL, /* attach_kernel_driver */
878 windows_destroy_device,
879 windows_submit_transfer,
880 windows_cancel_transfer,
881 NULL, /* clear_transfer_priv */
882 NULL, /* handle_events */
883 windows_handle_transfer_completion,
884 sizeof(struct windows_context_priv),
885 sizeof(union windows_device_priv),
886 sizeof(union windows_device_handle_priv),
887 sizeof(struct windows_transfer_priv),