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 libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
297 struct windows_context_priv *priv = usbi_get_context_priv(TRANSFER_CTX(transfer));
298 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
299 OVERLAPPED *overlapped = &transfer_priv->overlapped;
301 usbi_dbg("transfer %p, length %lu", transfer, ULONG_CAST(size));
303 overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
304 overlapped->InternalHigh = (ULONG_PTR)size;
306 if (!PostQueuedCompletionStatus(priv->completion_port, (DWORD)size, (ULONG_PTR)transfer->dev_handle, overlapped))
307 usbi_err(TRANSFER_CTX(transfer), "failed to post I/O completion: %s", windows_error_str(0));
310 /* Windows version detection */
311 static BOOL is_x64(void)
315 // Detect if we're running a 32 or 64 bit system
316 if (sizeof(uintptr_t) < 8) {
317 IsWow64Process(GetCurrentProcess(), &ret);
325 static enum windows_version get_windows_version(void)
327 enum windows_version winver;
328 OSVERSIONINFOEXA vi, vi2;
329 unsigned major, minor, version;
330 ULONGLONG major_equal, minor_equal;
331 const char *w, *arch;
334 memset(&vi, 0, sizeof(vi));
335 vi.dwOSVersionInfoSize = sizeof(vi);
336 if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
337 memset(&vi, 0, sizeof(vi));
338 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
339 if (!GetVersionExA((OSVERSIONINFOA *)&vi))
340 return WINDOWS_UNDEFINED;
343 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
344 return WINDOWS_UNDEFINED;
346 if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
347 // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
348 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
350 major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
351 for (major = vi.dwMajorVersion; major <= 9; major++) {
352 memset(&vi2, 0, sizeof(vi2));
353 vi2.dwOSVersionInfoSize = sizeof(vi2);
354 vi2.dwMajorVersion = major;
355 if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
358 if (vi.dwMajorVersion < major) {
359 vi.dwMajorVersion = major;
360 vi.dwMinorVersion = 0;
363 minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
364 for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
365 memset(&vi2, 0, sizeof(vi2));
366 vi2.dwOSVersionInfoSize = sizeof(vi2);
367 vi2.dwMinorVersion = minor;
368 if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
371 vi.dwMinorVersion = minor;
379 if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
380 return WINDOWS_UNDEFINED;
382 ws = (vi.wProductType <= VER_NT_WORKSTATION);
383 version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
385 case 0x50: winver = WINDOWS_2000; w = "2000"; break;
386 case 0x51: winver = WINDOWS_XP; w = "XP"; break;
387 case 0x52: winver = WINDOWS_2003; w = "2003"; break;
388 case 0x60: winver = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break;
389 case 0x61: winver = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break;
390 case 0x62: winver = WINDOWS_8; w = (ws ? "8" : "2012"); break;
391 case 0x63: winver = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break;
392 case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
393 case 0xA0: winver = WINDOWS_10; w = (ws ? "10" : "2016"); break;
396 return WINDOWS_UNDEFINED;
397 winver = WINDOWS_11_OR_LATER;
401 arch = is_x64() ? "64-bit" : "32-bit";
403 if (vi.wServicePackMinor)
404 usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
405 else if (vi.wServicePackMajor)
406 usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
408 usbi_dbg("Windows %s %s", w, arch);
413 static unsigned __stdcall windows_iocp_thread(void *arg)
415 struct libusb_context *ctx = arg;
416 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
417 HANDLE iocp = priv->completion_port;
419 ULONG_PTR completion_key;
420 OVERLAPPED *overlapped;
421 struct libusb_device_handle *dev_handle;
422 struct windows_device_handle_priv *handle_priv;
423 struct windows_transfer_priv *transfer_priv;
424 struct usbi_transfer *itransfer;
427 usbi_dbg("I/O completion thread started");
431 if (!GetQueuedCompletionStatus(iocp, &num_bytes, &completion_key, &overlapped, INFINITE) && (overlapped == NULL)) {
432 usbi_err(ctx, "GetQueuedCompletionStatus failed: %s", windows_error_str(0));
436 if (overlapped == NULL) {
438 if (completion_key != (ULONG_PTR)ctx)
439 usbi_err(ctx, "program assertion failed - overlapped is NULL");
443 // Find the transfer associated with the OVERLAPPED that just completed.
444 // If we cannot find a match, the I/O operation originated from outside of libusb
445 // (e.g. within libusbK) and we need to ignore it.
446 dev_handle = (struct libusb_device_handle *)completion_key;
447 handle_priv = usbi_get_device_handle_priv(dev_handle);
449 usbi_mutex_lock(&dev_handle->lock);
450 list_for_each_entry(transfer_priv, &handle_priv->active_transfers, list, struct windows_transfer_priv) {
451 if (overlapped == &transfer_priv->overlapped) {
452 // This OVERLAPPED belongs to us, remove the transfer from the device handle's list
453 list_del(&transfer_priv->list);
458 usbi_mutex_unlock(&dev_handle->lock);
461 usbi_dbg("ignoring overlapped %p for handle %p (device %u.%u)",
462 overlapped, dev_handle, dev_handle->dev->bus_number, dev_handle->dev->device_address);
466 itransfer = (struct usbi_transfer *)((unsigned char *)transfer_priv + PTR_ALIGN(sizeof(*transfer_priv)));
467 usbi_dbg("transfer %p completed, length %lu",
468 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(num_bytes));
469 usbi_signal_transfer_completion(itransfer);
472 usbi_dbg("I/O completion thread exiting");
477 static int windows_init(struct libusb_context *ctx)
479 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
480 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
482 bool winusb_backend_init = false;
485 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
486 mutex = CreateMutexA(NULL, FALSE, mutex_name);
488 usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
489 return LIBUSB_ERROR_NO_MEM;
492 // A successful wait gives this thread ownership of the mutex
493 // => any concurrent wait stalls until the mutex is released
494 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
495 usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
497 return LIBUSB_ERROR_NO_MEM;
500 // NB: concurrent usage supposes that init calls are equally balanced with
501 // exit calls. If init is called more than exit, we will not exit properly
502 if (++init_count == 1) { // First init?
503 windows_version = get_windows_version();
504 if (windows_version == WINDOWS_UNDEFINED) {
505 usbi_err(ctx, "failed to detect Windows version");
506 r = LIBUSB_ERROR_NOT_SUPPORTED;
508 } else if (windows_version < WINDOWS_VISTA) {
509 usbi_err(ctx, "Windows version is too old");
510 r = LIBUSB_ERROR_NOT_SUPPORTED;
514 if (!htab_create(ctx)) {
515 r = LIBUSB_ERROR_NO_MEM;
519 r = winusb_backend.init(ctx);
520 if (r != LIBUSB_SUCCESS)
522 winusb_backend_init = true;
524 r = usbdk_backend.init(ctx);
525 if (r == LIBUSB_SUCCESS) {
526 usbi_dbg("UsbDk backend is available");
527 usbdk_available = true;
529 usbi_info(ctx, "UsbDk backend is not available");
530 // Do not report this as an error
534 // By default, new contexts will use the WinUSB backend
535 priv->backend = &winusb_backend;
537 r = LIBUSB_ERROR_NO_MEM;
539 // Use an I/O completion port to manage all transfers for this context
540 priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
541 if (priv->completion_port == NULL) {
542 usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
546 // And a dedicated thread to wait for I/O completions
547 priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
548 if (priv->completion_port_thread == NULL) {
549 usbi_err(ctx, "failed to create I/O completion port thread");
550 CloseHandle(priv->completion_port);
556 init_exit: // Holds semaphore here
557 if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
558 if (usbdk_available) {
559 usbdk_backend.exit(ctx);
560 usbdk_available = false;
562 if (winusb_backend_init)
563 winusb_backend.exit(ctx);
573 static void windows_exit(struct libusb_context *ctx)
575 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
576 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
579 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
580 mutex = CreateMutexA(NULL, FALSE, mutex_name);
584 // A successful wait gives this thread ownership of the mutex
585 // => any concurrent wait stalls until the mutex is released
586 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
587 usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
592 // A NULL completion status will indicate to the thread that it is time to exit
593 if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
594 usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
596 if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
597 usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
599 CloseHandle(priv->completion_port_thread);
600 CloseHandle(priv->completion_port);
602 // Only works if exits and inits are balanced exactly
603 if (--init_count == 0) { // Last exit
604 if (usbdk_available) {
605 usbdk_backend.exit(ctx);
606 usbdk_available = false;
608 winusb_backend.exit(ctx);
616 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
618 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
622 if (option == LIBUSB_OPTION_USE_USBDK) {
623 if (!usbdk_available) {
624 usbi_err(ctx, "UsbDk backend not available");
625 return LIBUSB_ERROR_NOT_FOUND;
627 usbi_dbg("switching context %p to use UsbDk backend", ctx);
628 priv->backend = &usbdk_backend;
629 return LIBUSB_SUCCESS;
632 return LIBUSB_ERROR_NOT_SUPPORTED;
635 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
637 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
638 return priv->backend->get_device_list(ctx, discdevs);
641 static int windows_open(struct libusb_device_handle *dev_handle)
643 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
644 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
646 list_init(&handle_priv->active_transfers);
647 return priv->backend->open(dev_handle);
650 static void windows_close(struct libusb_device_handle *dev_handle)
652 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
653 priv->backend->close(dev_handle);
656 static int windows_get_active_config_descriptor(struct libusb_device *dev,
657 void *buffer, size_t len)
659 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
660 return priv->backend->get_active_config_descriptor(dev, buffer, len);
663 static int windows_get_config_descriptor(struct libusb_device *dev,
664 uint8_t config_index, void *buffer, size_t len)
666 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
667 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
670 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
671 uint8_t bConfigurationValue, void **buffer)
673 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
674 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
677 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
679 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
680 return priv->backend->get_configuration(dev_handle, config);
683 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
685 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
688 return priv->backend->set_configuration(dev_handle, (uint8_t)config);
691 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
693 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
694 return priv->backend->claim_interface(dev_handle, interface_number);
697 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
699 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
700 return priv->backend->release_interface(dev_handle, interface_number);
703 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
704 uint8_t interface_number, uint8_t altsetting)
706 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
707 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
710 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
712 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
713 return priv->backend->clear_halt(dev_handle, endpoint);
716 static int windows_reset_device(struct libusb_device_handle *dev_handle)
718 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
719 return priv->backend->reset_device(dev_handle);
722 static void windows_destroy_device(struct libusb_device *dev)
724 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
725 priv->backend->destroy_device(dev);
728 static int windows_submit_transfer(struct usbi_transfer *itransfer)
730 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
731 struct libusb_device_handle *dev_handle = transfer->dev_handle;
732 struct libusb_context *ctx = HANDLE_CTX(dev_handle);
733 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
734 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
735 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
738 switch (transfer->type) {
739 case LIBUSB_TRANSFER_TYPE_CONTROL:
740 case LIBUSB_TRANSFER_TYPE_BULK:
741 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
742 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
744 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
745 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
746 return LIBUSB_ERROR_NOT_SUPPORTED;
748 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
749 return LIBUSB_ERROR_INVALID_PARAM;
752 if (transfer_priv->handle != NULL) {
753 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
754 transfer_priv->handle = NULL;
757 // Add transfer to the device handle's list
758 usbi_mutex_lock(&dev_handle->lock);
759 list_add_tail(&transfer_priv->list, &handle_priv->active_transfers);
760 usbi_mutex_unlock(&dev_handle->lock);
762 r = priv->backend->submit_transfer(itransfer);
763 if (r != LIBUSB_SUCCESS) {
764 // Remove the unsuccessful transfer from the device handle's list
765 usbi_mutex_lock(&dev_handle->lock);
766 list_del(&transfer_priv->list);
767 usbi_mutex_unlock(&dev_handle->lock);
769 // Always call the backend's clear_transfer_priv() function on failure
770 priv->backend->clear_transfer_priv(itransfer);
771 transfer_priv->handle = NULL;
775 // The backend should set the HANDLE used for each submitted transfer
776 // by calling set_transfer_priv_handle()
777 if (transfer_priv->handle == NULL)
778 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
783 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
785 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
786 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
788 // Try CancelIoEx() on the transfer
789 // If that fails, fall back to the backend's cancel_transfer()
790 // function if it is available
791 if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
792 return LIBUSB_SUCCESS;
793 else if (GetLastError() == ERROR_NOT_FOUND)
794 return LIBUSB_ERROR_NOT_FOUND;
796 if (priv->backend->cancel_transfer)
797 return priv->backend->cancel_transfer(itransfer);
799 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
800 return LIBUSB_ERROR_NOT_SUPPORTED;
803 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
805 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
806 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
807 const struct windows_backend *backend = priv->backend;
808 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
809 enum libusb_transfer_status status, istatus;
810 DWORD result, bytes_transferred;
812 if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
815 result = GetLastError();
817 usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
818 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
822 status = backend->copy_transfer_data(itransfer, bytes_transferred);
824 case ERROR_GEN_FAILURE:
825 usbi_dbg("detected endpoint stall");
826 status = LIBUSB_TRANSFER_STALL;
828 case ERROR_SEM_TIMEOUT:
829 usbi_dbg("detected semaphore timeout");
830 status = LIBUSB_TRANSFER_TIMED_OUT;
832 case ERROR_OPERATION_ABORTED:
833 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
834 if (istatus != LIBUSB_TRANSFER_COMPLETED)
835 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
837 usbi_dbg("detected operation aborted");
838 status = LIBUSB_TRANSFER_CANCELLED;
840 case ERROR_FILE_NOT_FOUND:
841 case ERROR_DEVICE_NOT_CONNECTED:
842 case ERROR_NO_SUCH_DEVICE:
843 usbi_dbg("detected device removed");
844 status = LIBUSB_TRANSFER_NO_DEVICE;
847 usbi_err(ctx, "detected I/O error %lu: %s",
848 ULONG_CAST(result), windows_error_str(result));
849 status = LIBUSB_TRANSFER_ERROR;
853 transfer_priv->handle = NULL;
855 // Backend-specific cleanup
856 backend->clear_transfer_priv(itransfer);
858 if (status == LIBUSB_TRANSFER_CANCELLED)
859 return usbi_handle_transfer_cancellation(itransfer);
861 return usbi_handle_transfer_completion(itransfer, status);
864 void usbi_get_monotonic_time(struct timespec *tp)
866 static LONG hires_counter_init;
867 static uint64_t hires_ticks_to_ps;
868 static uint64_t hires_frequency;
869 LARGE_INTEGER hires_counter;
871 if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
872 LARGE_INTEGER li_frequency;
874 // Microsoft says that the QueryPerformanceFrequency() and
875 // QueryPerformanceCounter() functions always succeed on XP and later
876 QueryPerformanceFrequency(&li_frequency);
878 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
879 // to picoseconds to compute the tv_nsecs part
880 hires_frequency = li_frequency.QuadPart;
881 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
884 QueryPerformanceCounter(&hires_counter);
885 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
886 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
889 // NB: MSVC6 does not support named initializers.
890 const struct usbi_os_backend usbi_backend = {
892 USBI_CAP_HAS_HID_ACCESS,
896 windows_get_device_list,
897 NULL, /* hotplug_poll */
898 NULL, /* wrap_sys_device */
901 windows_get_active_config_descriptor,
902 windows_get_config_descriptor,
903 windows_get_config_descriptor_by_value,
904 windows_get_configuration,
905 windows_set_configuration,
906 windows_claim_interface,
907 windows_release_interface,
908 windows_set_interface_altsetting,
910 windows_reset_device,
911 NULL, /* alloc_streams */
912 NULL, /* free_streams */
913 NULL, /* dev_mem_alloc */
914 NULL, /* dev_mem_free */
915 NULL, /* kernel_driver_active */
916 NULL, /* detach_kernel_driver */
917 NULL, /* attach_kernel_driver */
918 windows_destroy_device,
919 windows_submit_transfer,
920 windows_cancel_transfer,
921 NULL, /* clear_transfer_priv */
922 NULL, /* handle_events */
923 windows_handle_transfer_completion,
924 sizeof(struct windows_context_priv),
925 sizeof(union windows_device_priv),
926 sizeof(struct windows_device_handle_priv),
927 sizeof(struct windows_transfer_priv),