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
30 #include "windows_common.h"
32 #define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
34 #define STATUS_SUCCESS ((ULONG_PTR)0UL)
37 enum windows_version windows_version = WINDOWS_UNDEFINED;
39 // Global variables for init/exit
40 static unsigned int init_count;
41 static bool usbdk_available;
44 * Converts a windows error to human readable string
45 * uses retval as errorcode, or, if 0, use GetLastError()
47 #if defined(ENABLE_LOGGING)
48 const char *windows_error_str(DWORD error_code)
50 static char err_string[256];
56 error_code = GetLastError();
58 len = sprintf(err_string, "[%lu] ", ULONG_CAST(error_code));
60 // Translate codes returned by SetupAPI. The ones we are dealing with are either
61 // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
62 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
63 switch (error_code & 0xE0000000) {
65 error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
68 error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
74 size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
75 NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
76 &err_string[len], sizeof(err_string) - len, NULL);
78 DWORD format_error = GetLastError();
80 snprintf(err_string, sizeof(err_string),
81 "Windows error code %lu (FormatMessage error code %lu)",
82 ULONG_CAST(error_code), ULONG_CAST(format_error));
84 snprintf(err_string, sizeof(err_string), "Unknown error code %lu",
85 ULONG_CAST(error_code));
87 // Remove CRLF from end of message, if present
88 size_t pos = len + size - 2;
89 if (err_string[pos] == '\r')
90 err_string[pos] = '\0';
98 * Dynamically loads a DLL from the Windows system directory. Unlike the
99 * LoadLibraryA() function, this function will not search through any
100 * directories to try and find the library.
102 HMODULE load_system_library(struct libusb_context *ctx, const char *name)
104 char library_path[MAX_PATH];
105 char *filename_start;
108 length = GetSystemDirectoryA(library_path, sizeof(library_path));
109 if ((length == 0) || (length >= (UINT)sizeof(library_path))) {
110 usbi_err(ctx, "program assertion failed - could not get system directory");
114 filename_start = library_path + length;
115 // Append '\' + name + ".dll" + NUL
116 length += 1 + (UINT)strlen(name) + 4 + 1;
117 if (length >= (UINT)sizeof(library_path)) {
118 usbi_err(ctx, "program assertion failed - library path buffer overflow");
122 sprintf(filename_start, "\\%s.dll", name);
123 return LoadLibraryA(library_path);
126 /* Hash table functions - modified From glibc 2.3.2:
127 [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
128 [Knuth] The Art of Computer Programming, part 3 (6.4) */
130 #define HTAB_SIZE 1021UL // *MUST* be a prime number!!
132 typedef struct htab_entry {
137 static htab_entry *htab_table;
138 static usbi_mutex_t htab_mutex;
139 static unsigned long htab_filled;
141 /* Before using the hash table we must allocate memory for it.
142 We allocate one element more as the found prime number says.
143 This is done for more effective indexing as explained in the
144 comment for the hash function. */
145 static bool htab_create(struct libusb_context *ctx)
147 if (htab_table != NULL) {
148 usbi_err(ctx, "program assertion failed - hash table already allocated");
153 usbi_mutex_init(&htab_mutex);
155 usbi_dbg("using %lu entries hash table", HTAB_SIZE);
158 // allocate memory and zero out.
159 htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry));
160 if (htab_table == NULL) {
161 usbi_err(ctx, "could not allocate space for hash table");
168 /* After using the hash table it has to be destroyed. */
169 static void htab_destroy(void)
173 if (htab_table == NULL)
176 for (i = 0; i < HTAB_SIZE; i++)
177 free(htab_table[i].str);
179 safe_free(htab_table);
181 usbi_mutex_destroy(&htab_mutex);
184 /* This is the search function. It uses double hashing with open addressing.
185 We use a trick to speed up the lookup. The table is created with one
186 more element available. This enables us to use the index zero special.
187 This index will never be used because we store the first hash index in
188 the field used where zero means not used. Every other value means used.
189 The used field can be used as a first fast comparison for equality of
190 the stored and the parameter value. This helps to prevent unnecessary
191 expensive calls of strcmp. */
192 unsigned long htab_hash(const char *str)
194 unsigned long hval, hval2;
196 unsigned long r = 5381UL;
198 const char *sz = str;
203 // Compute main hash value (algorithm suggested by Nokia)
204 while ((c = *sz++) != 0)
205 r = ((r << 5) + r) + c;
209 // compute table hash: simply take the modulus
210 hval = r % HTAB_SIZE;
214 // Try the first index
217 // Mutually exclusive access (R/W lock would be better)
218 usbi_mutex_lock(&htab_mutex);
220 if (htab_table[idx].used) {
221 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
222 goto out_unlock; // existing hash
224 usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
226 // Second hash function, as suggested in [Knuth]
227 hval2 = 1UL + hval % (HTAB_SIZE - 2);
230 // Because size is prime this guarantees to step through all available indexes
232 idx = HTAB_SIZE + idx - hval2;
236 // If we visited all entries leave the loop unsuccessfully
240 // If entry is found use it.
241 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
243 } while (htab_table[idx].used);
246 // Not found => New entry
248 // If the table is full return an error
249 if (htab_filled >= HTAB_SIZE) {
250 usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
255 htab_table[idx].str = _strdup(str);
256 if (htab_table[idx].str == NULL) {
257 usbi_err(NULL, "could not duplicate string for hash table");
262 htab_table[idx].used = hval;
266 usbi_mutex_unlock(&htab_mutex);
271 enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
273 if (USBD_SUCCESS(status))
274 return LIBUSB_TRANSFER_COMPLETED;
277 case USBD_STATUS_TIMEOUT:
278 return LIBUSB_TRANSFER_TIMED_OUT;
279 case USBD_STATUS_CANCELED:
280 return LIBUSB_TRANSFER_CANCELLED;
281 case USBD_STATUS_ENDPOINT_HALTED:
282 return LIBUSB_TRANSFER_STALL;
283 case USBD_STATUS_DEVICE_GONE:
284 return LIBUSB_TRANSFER_NO_DEVICE;
286 usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
287 return LIBUSB_TRANSFER_ERROR;
292 * Make a transfer complete synchronously
294 void windows_force_sync_completion(struct usbi_transfer *itransfer, ULONG size)
296 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
297 OVERLAPPED *overlapped = &transfer_priv->overlapped;
299 usbi_dbg("transfer %p, length %lu", USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(size));
301 overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
302 overlapped->InternalHigh = (ULONG_PTR)size;
304 usbi_signal_transfer_completion(itransfer);
307 /* Windows version detection */
308 static BOOL is_x64(void)
312 // Detect if we're running a 32 or 64 bit system
313 if (sizeof(uintptr_t) < 8) {
314 IsWow64Process(GetCurrentProcess(), &ret);
322 static enum windows_version get_windows_version(void)
324 enum windows_version winver;
325 OSVERSIONINFOEXA vi, vi2;
326 unsigned major, minor, version;
327 ULONGLONG major_equal, minor_equal;
328 const char *w, *arch;
331 memset(&vi, 0, sizeof(vi));
332 vi.dwOSVersionInfoSize = sizeof(vi);
333 if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
334 memset(&vi, 0, sizeof(vi));
335 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
336 if (!GetVersionExA((OSVERSIONINFOA *)&vi))
337 return WINDOWS_UNDEFINED;
340 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
341 return WINDOWS_UNDEFINED;
343 if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
344 // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
345 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
347 major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
348 for (major = vi.dwMajorVersion; major <= 9; major++) {
349 memset(&vi2, 0, sizeof(vi2));
350 vi2.dwOSVersionInfoSize = sizeof(vi2);
351 vi2.dwMajorVersion = major;
352 if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
355 if (vi.dwMajorVersion < major) {
356 vi.dwMajorVersion = major;
357 vi.dwMinorVersion = 0;
360 minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
361 for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
362 memset(&vi2, 0, sizeof(vi2));
363 vi2.dwOSVersionInfoSize = sizeof(vi2);
364 vi2.dwMinorVersion = minor;
365 if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
368 vi.dwMinorVersion = minor;
376 if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
377 return WINDOWS_UNDEFINED;
379 ws = (vi.wProductType <= VER_NT_WORKSTATION);
380 version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
382 case 0x50: winver = WINDOWS_2000; w = "2000"; break;
383 case 0x51: winver = WINDOWS_XP; w = "XP"; break;
384 case 0x52: winver = WINDOWS_2003; w = "2003"; break;
385 case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break;
386 case 0x61: winver = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break;
387 case 0x62: winver = WINDOWS_8; w = (ws ? "8" : "2012"); break;
388 case 0x63: winver = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break;
389 case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
390 case 0xA0: winver = WINDOWS_10; w = (ws ? "10" : "2016"); break;
393 return WINDOWS_UNDEFINED;
394 winver = WINDOWS_11_OR_LATER;
398 arch = is_x64() ? "64-bit" : "32-bit";
400 if (vi.wServicePackMinor)
401 usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
402 else if (vi.wServicePackMajor)
403 usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
405 usbi_dbg("Windows %s %s", w, arch);
410 static unsigned __stdcall windows_iocp_thread(void *arg)
412 struct libusb_context *ctx = arg;
413 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
414 HANDLE iocp = priv->completion_port;
416 ULONG_PTR completion_key;
417 OVERLAPPED *overlapped;
418 struct libusb_device_handle *dev_handle;
419 struct windows_device_handle_priv *handle_priv;
420 struct windows_transfer_priv *transfer_priv;
421 struct usbi_transfer *itransfer;
424 usbi_dbg("I/O completion thread started");
428 if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
429 usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
433 if (overlapped == NULL) {
435 if (completion_key != (ULONG_PTR)ctx)
436 usbi_err(ctx, "program assertion failed - overlapped is NULL");
440 // Find the transfer associated with the OVERLAPPED that just completed.
441 // If we cannot find a match, the I/O operation originated from outside of libusb
442 // (e.g. within libusbK) and we need to ignore it.
443 dev_handle = (struct libusb_device_handle *)completion_key;
444 handle_priv = usbi_get_device_handle_priv(dev_handle);
446 usbi_mutex_lock(&dev_handle->lock);
447 list_for_each_entry(transfer_priv, &handle_priv->active_transfers, list, struct windows_transfer_priv) {
448 if (overlapped == &transfer_priv->overlapped) {
449 // This OVERLAPPED belongs to us, remove the transfer from the device handle's list
450 list_del(&transfer_priv->list);
455 usbi_mutex_unlock(&dev_handle->lock);
458 usbi_dbg("ignoring overlapped %p for handle %p (device %u.%u)",
459 overlapped, dev_handle, dev_handle->dev->bus_number, dev_handle->dev->device_address);
463 itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
464 usbi_dbg("transfer %p completed, length %lu",
465 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes));
466 usbi_signal_transfer_completion(itransfer);
469 usbi_dbg("I/O completion thread exiting");
474 static int windows_init(struct libusb_context *ctx)
476 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
477 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
479 bool winusb_backend_init = false;
482 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
483 mutex = CreateMutexA(NULL, FALSE, mutex_name);
485 usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
486 return LIBUSB_ERROR_NO_MEM;
489 // A successful wait gives this thread ownership of the mutex
490 // => any concurrent wait stalls until the mutex is released
491 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
492 usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
494 return LIBUSB_ERROR_NO_MEM;
497 // NB: concurrent usage supposes that init calls are equally balanced with
498 // exit calls. If init is called more than exit, we will not exit properly
499 if (++init_count == 1) { // First init?
500 windows_version = get_windows_version();
501 if (windows_version == WINDOWS_UNDEFINED) {
502 usbi_err(ctx, "failed to detect Windows version");
503 r = LIBUSB_ERROR_NOT_SUPPORTED;
505 } else if (windows_version < WINDOWS_VISTA) {
506 usbi_err(ctx, "Windows version is too old");
507 r = LIBUSB_ERROR_NOT_SUPPORTED;
511 if (!htab_create(ctx)) {
512 r = LIBUSB_ERROR_NO_MEM;
516 r = winusb_backend.init(ctx);
517 if (r != LIBUSB_SUCCESS)
519 winusb_backend_init = true;
521 r = usbdk_backend.init(ctx);
522 if (r == LIBUSB_SUCCESS) {
523 usbi_dbg("UsbDk backend is available");
524 usbdk_available = true;
526 usbi_info(ctx, "UsbDk backend is not available");
527 // Do not report this as an error
531 // By default, new contexts will use the WinUSB backend
532 priv->backend = &winusb_backend;
534 r = LIBUSB_ERROR_NO_MEM;
536 // Use an I/O completion port to manage all transfers for this context
537 priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
538 if (priv->completion_port == NULL) {
539 usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
543 // And a dedicated thread to wait for I/O completions
544 priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
545 if (priv->completion_port_thread == NULL) {
546 usbi_err(ctx, "failed to create I/O completion port thread");
547 CloseHandle(priv->completion_port);
553 init_exit: // Holds semaphore here
554 if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
555 if (usbdk_available) {
556 usbdk_backend.exit(ctx);
557 usbdk_available = false;
559 if (winusb_backend_init)
560 winusb_backend.exit(ctx);
570 static void windows_exit(struct libusb_context *ctx)
572 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
573 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
576 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
577 mutex = CreateMutexA(NULL, FALSE, mutex_name);
581 // A successful wait gives this thread ownership of the mutex
582 // => any concurrent wait stalls until the mutex is released
583 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
584 usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
589 // A NULL completion status will indicate to the thread that it is time to exit
590 if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
591 usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
593 if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
594 usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
596 CloseHandle(priv->completion_port_thread);
597 CloseHandle(priv->completion_port);
599 // Only works if exits and inits are balanced exactly
600 if (--init_count == 0) { // Last exit
601 if (usbdk_available) {
602 usbdk_backend.exit(ctx);
603 usbdk_available = false;
605 winusb_backend.exit(ctx);
613 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
615 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
619 if (option == LIBUSB_OPTION_USE_USBDK) {
620 if (!usbdk_available) {
621 usbi_err(ctx, "UsbDk backend not available");
622 return LIBUSB_ERROR_NOT_FOUND;
624 usbi_dbg("switching context %p to use UsbDk backend", ctx);
625 priv->backend = &usbdk_backend;
626 return LIBUSB_SUCCESS;
629 return LIBUSB_ERROR_NOT_SUPPORTED;
632 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
634 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
635 return priv->backend->get_device_list(ctx, discdevs);
638 static int windows_open(struct libusb_device_handle *dev_handle)
640 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
641 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
643 list_init(&handle_priv->active_transfers);
644 return priv->backend->open(dev_handle);
647 static void windows_close(struct libusb_device_handle *dev_handle)
649 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
650 priv->backend->close(dev_handle);
653 static int windows_get_active_config_descriptor(struct libusb_device *dev,
654 void *buffer, size_t len)
656 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
657 return priv->backend->get_active_config_descriptor(dev, buffer, len);
660 static int windows_get_config_descriptor(struct libusb_device *dev,
661 uint8_t config_index, void *buffer, size_t len)
663 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
664 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
667 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
668 uint8_t bConfigurationValue, void **buffer)
670 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
671 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
674 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
676 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
677 return priv->backend->get_configuration(dev_handle, config);
680 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
682 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
685 return priv->backend->set_configuration(dev_handle, (uint8_t)config);
688 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
690 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
691 return priv->backend->claim_interface(dev_handle, interface_number);
694 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
696 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
697 return priv->backend->release_interface(dev_handle, interface_number);
700 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
701 uint8_t interface_number, uint8_t altsetting)
703 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
704 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
707 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
709 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
710 return priv->backend->clear_halt(dev_handle, endpoint);
713 static int windows_reset_device(struct libusb_device_handle *dev_handle)
715 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
716 return priv->backend->reset_device(dev_handle);
719 static void windows_destroy_device(struct libusb_device *dev)
721 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
722 priv->backend->destroy_device(dev);
725 static int windows_submit_transfer(struct usbi_transfer *itransfer)
727 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
728 struct libusb_device_handle *dev_handle = transfer->dev_handle;
729 struct libusb_context *ctx = HANDLE_CTX(dev_handle);
730 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
731 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
732 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
735 switch (transfer->type) {
736 case LIBUSB_TRANSFER_TYPE_CONTROL:
737 case LIBUSB_TRANSFER_TYPE_BULK:
738 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
739 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
741 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
742 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
743 return LIBUSB_ERROR_NOT_SUPPORTED;
745 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
746 return LIBUSB_ERROR_INVALID_PARAM;
749 if (transfer_priv->handle != NULL) {
750 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
751 transfer_priv->handle = NULL;
754 // Add transfer to the device handle's list
755 usbi_mutex_lock(&dev_handle->lock);
756 list_add_tail(&transfer_priv->list, &handle_priv->active_transfers);
757 usbi_mutex_unlock(&dev_handle->lock);
759 r = priv->backend->submit_transfer(itransfer);
760 if (r != LIBUSB_SUCCESS) {
761 // Remove the unsuccessful transfer from the device handle's list
762 usbi_mutex_lock(&dev_handle->lock);
763 list_del(&transfer_priv->list);
764 usbi_mutex_unlock(&dev_handle->lock);
766 // Always call the backend's clear_transfer_priv() function on failure
767 priv->backend->clear_transfer_priv(itransfer);
768 transfer_priv->handle = NULL;
772 // The backend should set the HANDLE used for each submitted transfer
773 // by calling set_transfer_priv_handle()
774 if (transfer_priv->handle == NULL)
775 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
780 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
782 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
783 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
785 // Try CancelIoEx() on the transfer
786 // If that fails, fall back to the backend's cancel_transfer()
787 // function if it is available
788 if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
789 return LIBUSB_SUCCESS;
790 else if (GetLastError() == ERROR_NOT_FOUND)
791 return LIBUSB_ERROR_NOT_FOUND;
793 if (priv->backend->cancel_transfer)
794 return priv->backend->cancel_transfer(itransfer);
796 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
797 return LIBUSB_ERROR_NOT_SUPPORTED;
800 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
802 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
803 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
804 const struct windows_backend *backend = priv->backend;
805 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
806 enum libusb_transfer_status status, istatus;
807 DWORD result, bytes_transferred;
809 if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
812 result = GetLastError();
814 usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
815 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
819 status = backend->copy_transfer_data(itransfer, bytes_transferred);
821 case ERROR_GEN_FAILURE:
822 usbi_dbg("detected endpoint stall");
823 status = LIBUSB_TRANSFER_STALL;
825 case ERROR_SEM_TIMEOUT:
826 usbi_dbg("detected semaphore timeout");
827 status = LIBUSB_TRANSFER_TIMED_OUT;
829 case ERROR_OPERATION_ABORTED:
830 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
831 if (istatus != LIBUSB_TRANSFER_COMPLETED)
832 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
834 usbi_dbg("detected operation aborted");
835 status = LIBUSB_TRANSFER_CANCELLED;
837 case ERROR_FILE_NOT_FOUND:
838 case ERROR_DEVICE_NOT_CONNECTED:
839 case ERROR_NO_SUCH_DEVICE:
840 usbi_dbg("detected device removed");
841 status = LIBUSB_TRANSFER_NO_DEVICE;
844 usbi_err(ctx, "detected I/O error %lu: %s",
845 ULONG_CAST(result), windows_error_str(result));
846 status = LIBUSB_TRANSFER_ERROR;
850 transfer_priv->handle = NULL;
852 // Backend-specific cleanup
853 backend->clear_transfer_priv(itransfer);
855 if (status == LIBUSB_TRANSFER_CANCELLED)
856 return usbi_handle_transfer_cancellation(itransfer);
858 return usbi_handle_transfer_completion(itransfer, status);
861 void usbi_get_monotonic_time(struct timespec *tp)
863 static LONG hires_counter_init;
864 static uint64_t hires_ticks_to_ps;
865 static uint64_t hires_frequency;
866 LARGE_INTEGER hires_counter;
868 if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
869 LARGE_INTEGER li_frequency;
871 // Microsoft says that the QueryPerformanceFrequency() and
872 // QueryPerformanceCounter() functions always succeed on XP and later
873 QueryPerformanceFrequency(&li_frequency);
875 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
876 // to picoseconds to compute the tv_nsecs part
877 hires_frequency = li_frequency.QuadPart;
878 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
881 QueryPerformanceCounter(&hires_counter);
882 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
883 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
886 // NB: MSVC6 does not support named initializers.
887 const struct usbi_os_backend usbi_backend = {
889 USBI_CAP_HAS_HID_ACCESS,
893 windows_get_device_list,
894 NULL, /* hotplug_poll */
895 NULL, /* wrap_sys_device */
898 windows_get_active_config_descriptor,
899 windows_get_config_descriptor,
900 windows_get_config_descriptor_by_value,
901 windows_get_configuration,
902 windows_set_configuration,
903 windows_claim_interface,
904 windows_release_interface,
905 windows_set_interface_altsetting,
907 windows_reset_device,
908 NULL, /* alloc_streams */
909 NULL, /* free_streams */
910 NULL, /* dev_mem_alloc */
911 NULL, /* dev_mem_free */
912 NULL, /* kernel_driver_active */
913 NULL, /* detach_kernel_driver */
914 NULL, /* attach_kernel_driver */
915 windows_destroy_device,
916 windows_submit_transfer,
917 windows_cancel_transfer,
918 NULL, /* clear_transfer_priv */
919 NULL, /* handle_events */
920 windows_handle_transfer_completion,
921 sizeof(struct windows_context_priv),
922 sizeof(union windows_device_priv),
923 sizeof(struct windows_device_handle_priv),
924 sizeof(struct windows_transfer_priv),