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 bool winusb_backend_init = false;
483 // NB: concurrent usage supposes that init calls are equally balanced with
484 // exit calls. If init is called more than exit, we will not exit properly
485 if (++init_count == 1) { // First init?
486 windows_version = get_windows_version();
487 if (windows_version == WINDOWS_UNDEFINED) {
488 usbi_err(ctx, "failed to detect Windows version");
489 r = LIBUSB_ERROR_NOT_SUPPORTED;
491 } else if (windows_version < WINDOWS_VISTA) {
492 usbi_err(ctx, "Windows version is too old");
493 r = LIBUSB_ERROR_NOT_SUPPORTED;
497 if (!htab_create(ctx)) {
498 r = LIBUSB_ERROR_NO_MEM;
502 r = winusb_backend.init(ctx);
503 if (r != LIBUSB_SUCCESS)
505 winusb_backend_init = true;
507 r = usbdk_backend.init(ctx);
508 if (r == LIBUSB_SUCCESS) {
509 usbi_dbg("UsbDk backend is available");
510 usbdk_available = true;
512 usbi_info(ctx, "UsbDk backend is not available");
513 // Do not report this as an error
517 // By default, new contexts will use the WinUSB backend
518 priv->backend = &winusb_backend;
520 r = LIBUSB_ERROR_NO_MEM;
522 // Use an I/O completion port to manage all transfers for this context
523 priv->completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
524 if (priv->completion_port == NULL) {
525 usbi_err(ctx, "failed to create I/O completion port: %s", windows_error_str(0));
529 // And a dedicated thread to wait for I/O completions
530 priv->completion_port_thread = (HANDLE)_beginthreadex(NULL, 0, windows_iocp_thread, ctx, 0, NULL);
531 if (priv->completion_port_thread == NULL) {
532 usbi_err(ctx, "failed to create I/O completion port thread");
533 CloseHandle(priv->completion_port);
539 init_exit: // Holds semaphore here
540 if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
541 if (usbdk_available) {
542 usbdk_backend.exit(ctx);
543 usbdk_available = false;
545 if (winusb_backend_init)
546 winusb_backend.exit(ctx);
554 static void windows_exit(struct libusb_context *ctx)
556 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
558 // A NULL completion status will indicate to the thread that it is time to exit
559 if (!PostQueuedCompletionStatus(priv->completion_port, 0, (ULONG_PTR)ctx, NULL))
560 usbi_err(ctx, "failed to post I/O completion: %s", windows_error_str(0));
562 if (WaitForSingleObject(priv->completion_port_thread, INFINITE) == WAIT_FAILED)
563 usbi_err(ctx, "failed to wait for I/O completion port thread: %s", windows_error_str(0));
565 CloseHandle(priv->completion_port_thread);
566 CloseHandle(priv->completion_port);
568 // Only works if exits and inits are balanced exactly
569 if (--init_count == 0) { // Last exit
570 if (usbdk_available) {
571 usbdk_backend.exit(ctx);
572 usbdk_available = false;
574 winusb_backend.exit(ctx);
579 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
581 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
585 if (option == LIBUSB_OPTION_USE_USBDK) {
586 if (!usbdk_available) {
587 usbi_err(ctx, "UsbDk backend not available");
588 return LIBUSB_ERROR_NOT_FOUND;
590 usbi_dbg("switching context %p to use UsbDk backend", ctx);
591 priv->backend = &usbdk_backend;
592 return LIBUSB_SUCCESS;
595 return LIBUSB_ERROR_NOT_SUPPORTED;
598 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
600 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
601 return priv->backend->get_device_list(ctx, discdevs);
604 static int windows_open(struct libusb_device_handle *dev_handle)
606 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
607 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
609 list_init(&handle_priv->active_transfers);
610 return priv->backend->open(dev_handle);
613 static void windows_close(struct libusb_device_handle *dev_handle)
615 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
616 priv->backend->close(dev_handle);
619 static int windows_get_active_config_descriptor(struct libusb_device *dev,
620 void *buffer, size_t len)
622 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
623 return priv->backend->get_active_config_descriptor(dev, buffer, len);
626 static int windows_get_config_descriptor(struct libusb_device *dev,
627 uint8_t config_index, void *buffer, size_t len)
629 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
630 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
633 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
634 uint8_t bConfigurationValue, void **buffer)
636 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
637 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
640 static int windows_get_configuration(struct libusb_device_handle *dev_handle, uint8_t *config)
642 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
643 return priv->backend->get_configuration(dev_handle, config);
646 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
648 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
651 return priv->backend->set_configuration(dev_handle, (uint8_t)config);
654 static int windows_claim_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
656 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
657 return priv->backend->claim_interface(dev_handle, interface_number);
660 static int windows_release_interface(struct libusb_device_handle *dev_handle, uint8_t interface_number)
662 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
663 return priv->backend->release_interface(dev_handle, interface_number);
666 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
667 uint8_t interface_number, uint8_t altsetting)
669 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
670 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
673 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
675 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
676 return priv->backend->clear_halt(dev_handle, endpoint);
679 static int windows_reset_device(struct libusb_device_handle *dev_handle)
681 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
682 return priv->backend->reset_device(dev_handle);
685 static void windows_destroy_device(struct libusb_device *dev)
687 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
688 priv->backend->destroy_device(dev);
691 static int windows_submit_transfer(struct usbi_transfer *itransfer)
693 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
694 struct libusb_device_handle *dev_handle = transfer->dev_handle;
695 struct libusb_context *ctx = HANDLE_CTX(dev_handle);
696 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
697 struct windows_device_handle_priv *handle_priv = usbi_get_device_handle_priv(dev_handle);
698 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
701 switch (transfer->type) {
702 case LIBUSB_TRANSFER_TYPE_CONTROL:
703 case LIBUSB_TRANSFER_TYPE_BULK:
704 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
705 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
707 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
708 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
709 return LIBUSB_ERROR_NOT_SUPPORTED;
711 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
712 return LIBUSB_ERROR_INVALID_PARAM;
715 if (transfer_priv->handle != NULL) {
716 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
717 transfer_priv->handle = NULL;
720 // Add transfer to the device handle's list
721 usbi_mutex_lock(&dev_handle->lock);
722 list_add_tail(&transfer_priv->list, &handle_priv->active_transfers);
723 usbi_mutex_unlock(&dev_handle->lock);
725 r = priv->backend->submit_transfer(itransfer);
726 if (r != LIBUSB_SUCCESS) {
727 // Remove the unsuccessful transfer from the device handle's list
728 usbi_mutex_lock(&dev_handle->lock);
729 list_del(&transfer_priv->list);
730 usbi_mutex_unlock(&dev_handle->lock);
732 // Always call the backend's clear_transfer_priv() function on failure
733 priv->backend->clear_transfer_priv(itransfer);
734 transfer_priv->handle = NULL;
738 // The backend should set the HANDLE used for each submitted transfer
739 // by calling set_transfer_priv_handle()
740 if (transfer_priv->handle == NULL)
741 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
746 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
748 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
749 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
751 // Try CancelIoEx() on the transfer
752 // If that fails, fall back to the backend's cancel_transfer()
753 // function if it is available
754 if (CancelIoEx(transfer_priv->handle, &transfer_priv->overlapped))
755 return LIBUSB_SUCCESS;
756 else if (GetLastError() == ERROR_NOT_FOUND)
757 return LIBUSB_ERROR_NOT_FOUND;
759 if (priv->backend->cancel_transfer)
760 return priv->backend->cancel_transfer(itransfer);
762 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
763 return LIBUSB_ERROR_NOT_SUPPORTED;
766 static int windows_handle_transfer_completion(struct usbi_transfer *itransfer)
768 struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
769 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
770 const struct windows_backend *backend = priv->backend;
771 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
772 enum libusb_transfer_status status, istatus;
773 DWORD result, bytes_transferred;
775 if (GetOverlappedResult(transfer_priv->handle, &transfer_priv->overlapped, &bytes_transferred, FALSE))
778 result = GetLastError();
780 usbi_dbg("handling transfer %p completion with errcode %lu, length %lu",
781 USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer), ULONG_CAST(result), ULONG_CAST(bytes_transferred));
785 status = backend->copy_transfer_data(itransfer, bytes_transferred);
787 case ERROR_GEN_FAILURE:
788 usbi_dbg("detected endpoint stall");
789 status = LIBUSB_TRANSFER_STALL;
791 case ERROR_SEM_TIMEOUT:
792 usbi_dbg("detected semaphore timeout");
793 status = LIBUSB_TRANSFER_TIMED_OUT;
795 case ERROR_OPERATION_ABORTED:
796 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
797 if (istatus != LIBUSB_TRANSFER_COMPLETED)
798 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
800 usbi_dbg("detected operation aborted");
801 status = LIBUSB_TRANSFER_CANCELLED;
803 case ERROR_FILE_NOT_FOUND:
804 case ERROR_DEVICE_NOT_CONNECTED:
805 case ERROR_NO_SUCH_DEVICE:
806 usbi_dbg("detected device removed");
807 status = LIBUSB_TRANSFER_NO_DEVICE;
810 usbi_err(ctx, "detected I/O error %lu: %s",
811 ULONG_CAST(result), windows_error_str(result));
812 status = LIBUSB_TRANSFER_ERROR;
816 transfer_priv->handle = NULL;
818 // Backend-specific cleanup
819 backend->clear_transfer_priv(itransfer);
821 if (status == LIBUSB_TRANSFER_CANCELLED)
822 return usbi_handle_transfer_cancellation(itransfer);
824 return usbi_handle_transfer_completion(itransfer, status);
827 void usbi_get_monotonic_time(struct timespec *tp)
829 static LONG hires_counter_init;
830 static uint64_t hires_ticks_to_ps;
831 static uint64_t hires_frequency;
832 LARGE_INTEGER hires_counter;
834 if (InterlockedExchange(&hires_counter_init, 1L) == 0L) {
835 LARGE_INTEGER li_frequency;
837 // Microsoft says that the QueryPerformanceFrequency() and
838 // QueryPerformanceCounter() functions always succeed on XP and later
839 QueryPerformanceFrequency(&li_frequency);
841 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
842 // to picoseconds to compute the tv_nsecs part
843 hires_frequency = li_frequency.QuadPart;
844 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
847 QueryPerformanceCounter(&hires_counter);
848 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
849 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
852 // NB: MSVC6 does not support named initializers.
853 const struct usbi_os_backend usbi_backend = {
855 USBI_CAP_HAS_HID_ACCESS,
859 windows_get_device_list,
860 NULL, /* hotplug_poll */
861 NULL, /* wrap_sys_device */
864 windows_get_active_config_descriptor,
865 windows_get_config_descriptor,
866 windows_get_config_descriptor_by_value,
867 windows_get_configuration,
868 windows_set_configuration,
869 windows_claim_interface,
870 windows_release_interface,
871 windows_set_interface_altsetting,
873 windows_reset_device,
874 NULL, /* alloc_streams */
875 NULL, /* free_streams */
876 NULL, /* dev_mem_alloc */
877 NULL, /* dev_mem_free */
878 NULL, /* kernel_driver_active */
879 NULL, /* detach_kernel_driver */
880 NULL, /* attach_kernel_driver */
881 windows_destroy_device,
882 windows_submit_transfer,
883 windows_cancel_transfer,
884 NULL, /* clear_transfer_priv */
885 NULL, /* handle_events */
886 windows_handle_transfer_completion,
887 sizeof(struct windows_context_priv),
888 sizeof(union windows_device_priv),
889 sizeof(struct windows_device_handle_priv),
890 sizeof(struct windows_transfer_priv),