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
33 #include "windows_common.h"
35 #define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
37 #define STATUS_SUCCESS ((ULONG_PTR)0UL)
40 enum windows_version windows_version = WINDOWS_UNDEFINED;
42 // Global variables for init/exit
43 static unsigned int init_count;
44 static bool usbdk_available;
46 #if !defined(HAVE_CLOCK_GETTIME)
47 // Global variables for clock_gettime mechanism
48 static uint64_t hires_ticks_to_ps;
49 static uint64_t hires_frequency;
53 * Converts a windows error to human readable string
54 * uses retval as errorcode, or, if 0, use GetLastError()
56 #if defined(ENABLE_LOGGING)
57 const char *windows_error_str(DWORD error_code)
59 static char err_string[256];
65 error_code = GetLastError();
67 len = sprintf(err_string, "[%lu] ", ULONG_CAST(error_code));
69 // Translate codes returned by SetupAPI. The ones we are dealing with are either
70 // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
71 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
72 switch (error_code & 0xE0000000) {
74 error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
77 error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
83 size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
84 NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
85 &err_string[len], sizeof(err_string) - len, NULL);
87 DWORD format_error = GetLastError();
89 snprintf(err_string, sizeof(err_string),
90 "Windows error code %lu (FormatMessage error code %lu)",
91 ULONG_CAST(error_code), ULONG_CAST(format_error));
93 snprintf(err_string, sizeof(err_string), "Unknown error code %lu",
94 ULONG_CAST(error_code));
96 // Remove CRLF from end of message, if present
97 size_t pos = len + size - 2;
98 if (err_string[pos] == '\r')
99 err_string[pos] = '\0';
106 /* Hash table functions - modified From glibc 2.3.2:
107 [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
108 [Knuth] The Art of Computer Programming, part 3 (6.4) */
110 #define HTAB_SIZE 1021UL // *MUST* be a prime number!!
112 typedef struct htab_entry {
117 static htab_entry *htab_table;
118 static usbi_mutex_t htab_mutex;
119 static unsigned long htab_filled;
121 /* Before using the hash table we must allocate memory for it.
122 We allocate one element more as the found prime number says.
123 This is done for more effective indexing as explained in the
124 comment for the hash function. */
125 static bool htab_create(struct libusb_context *ctx)
127 if (htab_table != NULL) {
128 usbi_err(ctx, "program assertion falied - hash table already allocated");
133 usbi_mutex_init(&htab_mutex);
135 usbi_dbg("using %lu entries hash table", HTAB_SIZE);
138 // allocate memory and zero out.
139 htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry));
140 if (htab_table == NULL) {
141 usbi_err(ctx, "could not allocate space for hash table");
148 /* After using the hash table it has to be destroyed. */
149 static void htab_destroy(void)
153 if (htab_table == NULL)
156 for (i = 0; i < HTAB_SIZE; i++)
157 free(htab_table[i].str);
159 safe_free(htab_table);
161 usbi_mutex_destroy(&htab_mutex);
164 /* This is the search function. It uses double hashing with open addressing.
165 We use a trick to speed up the lookup. The table is created with one
166 more element available. This enables us to use the index zero special.
167 This index will never be used because we store the first hash index in
168 the field used where zero means not used. Every other value means used.
169 The used field can be used as a first fast comparison for equality of
170 the stored and the parameter value. This helps to prevent unnecessary
171 expensive calls of strcmp. */
172 unsigned long htab_hash(const char *str)
174 unsigned long hval, hval2;
176 unsigned long r = 5381UL;
178 const char *sz = str;
183 // Compute main hash value (algorithm suggested by Nokia)
184 while ((c = *sz++) != 0)
185 r = ((r << 5) + r) + c;
189 // compute table hash: simply take the modulus
190 hval = r % HTAB_SIZE;
194 // Try the first index
197 // Mutually exclusive access (R/W lock would be better)
198 usbi_mutex_lock(&htab_mutex);
200 if (htab_table[idx].used) {
201 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
202 goto out_unlock; // existing hash
204 usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
206 // Second hash function, as suggested in [Knuth]
207 hval2 = 1UL + hval % (HTAB_SIZE - 2);
210 // Because size is prime this guarantees to step through all available indexes
212 idx = HTAB_SIZE + idx - hval2;
216 // If we visited all entries leave the loop unsuccessfully
220 // If entry is found use it.
221 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
223 } while (htab_table[idx].used);
226 // Not found => New entry
228 // If the table is full return an error
229 if (htab_filled >= HTAB_SIZE) {
230 usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
235 htab_table[idx].str = _strdup(str);
236 if (htab_table[idx].str == NULL) {
237 usbi_err(NULL, "could not duplicate string for hash table");
242 htab_table[idx].used = hval;
246 usbi_mutex_unlock(&htab_mutex);
251 enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
253 if (USBD_SUCCESS(status))
254 return LIBUSB_TRANSFER_COMPLETED;
257 case USBD_STATUS_TIMEOUT:
258 return LIBUSB_TRANSFER_TIMED_OUT;
259 case USBD_STATUS_CANCELED:
260 return LIBUSB_TRANSFER_CANCELLED;
261 case USBD_STATUS_ENDPOINT_HALTED:
262 return LIBUSB_TRANSFER_STALL;
263 case USBD_STATUS_DEVICE_GONE:
264 return LIBUSB_TRANSFER_NO_DEVICE;
266 usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
267 return LIBUSB_TRANSFER_ERROR;
272 * Make a transfer complete synchronously
274 void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size)
276 overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
277 overlapped->InternalHigh = (ULONG_PTR)size;
278 SetEvent(overlapped->hEvent);
281 static void windows_init_clock(void)
283 #if !defined(HAVE_CLOCK_GETTIME)
284 LARGE_INTEGER li_frequency;
286 // Microsoft says that the QueryPerformanceFrequency() and
287 // QueryPerformanceCounter() functions always succeed on XP and later
288 QueryPerformanceFrequency(&li_frequency);
290 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
291 // to picoseconds to compute the tv_nsecs part in clock_gettime
292 hires_frequency = li_frequency.QuadPart;
293 hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
294 usbi_dbg("hires timer frequency: %"PRIu64" Hz", hires_frequency);
298 /* Windows version detection */
299 static BOOL is_x64(void)
303 // Detect if we're running a 32 or 64 bit system
304 if (sizeof(uintptr_t) < 8) {
305 IsWow64Process(GetCurrentProcess(), &ret);
313 static void get_windows_version(void)
315 OSVERSIONINFOEXA vi, vi2;
316 const char *arch, *w = NULL;
317 unsigned major, minor, version;
318 ULONGLONG major_equal, minor_equal;
321 windows_version = WINDOWS_UNDEFINED;
323 memset(&vi, 0, sizeof(vi));
324 vi.dwOSVersionInfoSize = sizeof(vi);
325 if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
326 memset(&vi, 0, sizeof(vi));
327 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
328 if (!GetVersionExA((OSVERSIONINFOA *)&vi))
332 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
335 if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
336 // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
337 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
339 major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
340 for (major = vi.dwMajorVersion; major <= 9; major++) {
341 memset(&vi2, 0, sizeof(vi2));
342 vi2.dwOSVersionInfoSize = sizeof(vi2);
343 vi2.dwMajorVersion = major;
344 if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
347 if (vi.dwMajorVersion < major) {
348 vi.dwMajorVersion = major;
349 vi.dwMinorVersion = 0;
352 minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
353 for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
354 memset(&vi2, 0, sizeof(vi2));
355 vi2.dwOSVersionInfoSize = sizeof(vi2);
356 vi2.dwMinorVersion = minor;
357 if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
360 vi.dwMinorVersion = minor;
368 if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
371 ws = (vi.wProductType <= VER_NT_WORKSTATION);
372 version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
374 case 0x50: windows_version = WINDOWS_2000; w = "2000"; break;
375 case 0x51: windows_version = WINDOWS_XP; w = "XP"; break;
376 case 0x52: windows_version = WINDOWS_2003; w = "2003"; break;
377 case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break;
378 case 0x61: windows_version = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break;
379 case 0x62: windows_version = WINDOWS_8; w = (ws ? "8" : "2012"); break;
380 case 0x63: windows_version = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break;
381 case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
382 case 0xA0: windows_version = WINDOWS_10; w = (ws ? "10" : "2016"); break;
384 if (version < 0x50) {
387 windows_version = WINDOWS_11_OR_LATER;
392 arch = is_x64() ? "64-bit" : "32-bit";
394 if (vi.wServicePackMinor)
395 usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
396 else if (vi.wServicePackMajor)
397 usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
399 usbi_dbg("Windows %s %s", w, arch);
402 static void windows_transfer_callback(const struct windows_backend *backend,
403 struct usbi_transfer *itransfer, DWORD error, DWORD bytes_transferred)
405 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
406 enum libusb_transfer_status status, istatus;
408 usbi_dbg("handling I/O completion with errcode %lu, length %lu",
409 ULONG_CAST(error), ULONG_CAST(bytes_transferred));
413 status = backend->copy_transfer_data(itransfer, bytes_transferred);
415 case ERROR_GEN_FAILURE:
416 usbi_dbg("detected endpoint stall");
417 status = LIBUSB_TRANSFER_STALL;
419 case ERROR_SEM_TIMEOUT:
420 usbi_dbg("detected semaphore timeout");
421 status = LIBUSB_TRANSFER_TIMED_OUT;
423 case ERROR_OPERATION_ABORTED:
424 istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
425 if (istatus != LIBUSB_TRANSFER_COMPLETED)
426 usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
428 usbi_dbg("detected operation aborted");
429 status = LIBUSB_TRANSFER_CANCELLED;
431 case ERROR_FILE_NOT_FOUND:
432 case ERROR_DEVICE_NOT_CONNECTED:
433 usbi_dbg("detected device removed");
434 status = LIBUSB_TRANSFER_NO_DEVICE;
437 usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %lu: %s",
438 ULONG_CAST(error), windows_error_str(error));
439 status = LIBUSB_TRANSFER_ERROR;
444 usbi_close(transfer_priv->pollable_fd.fd);
445 transfer_priv->pollable_fd = INVALID_WINFD;
446 transfer_priv->handle = NULL;
448 // Backend-specific cleanup
449 backend->clear_transfer_priv(itransfer);
451 if (status == LIBUSB_TRANSFER_CANCELLED)
452 usbi_handle_transfer_cancellation(itransfer);
454 usbi_handle_transfer_completion(itransfer, status);
457 static int windows_init(struct libusb_context *ctx)
459 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
460 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
462 int r = LIBUSB_ERROR_OTHER;
463 bool winusb_backend_init = false;
465 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
466 mutex = CreateMutexA(NULL, FALSE, mutex_name);
468 usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
469 return LIBUSB_ERROR_NO_MEM;
472 // A successful wait gives this thread ownership of the mutex
473 // => any concurent wait stalls until the mutex is released
474 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
475 usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
477 return LIBUSB_ERROR_NO_MEM;
480 // NB: concurrent usage supposes that init calls are equally balanced with
481 // exit calls. If init is called more than exit, we will not exit properly
482 if (++init_count == 1) { // First init?
483 get_windows_version();
485 if (windows_version == WINDOWS_UNDEFINED) {
486 usbi_err(ctx, "failed to detect Windows version");
487 r = LIBUSB_ERROR_NOT_SUPPORTED;
491 windows_init_clock();
493 if (!htab_create(ctx))
496 r = winusb_backend.init(ctx);
497 if (r != LIBUSB_SUCCESS)
499 winusb_backend_init = true;
501 r = usbdk_backend.init(ctx);
502 if (r == LIBUSB_SUCCESS) {
503 usbi_dbg("UsbDk backend is available");
504 usbdk_available = true;
506 usbi_info(ctx, "UsbDk backend is not available");
507 // Do not report this as an error
512 // By default, new contexts will use the WinUSB backend
513 priv->backend = &winusb_backend;
517 init_exit: // Holds semaphore here
518 if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
519 if (winusb_backend_init)
520 winusb_backend.exit(ctx);
530 static void windows_exit(struct libusb_context *ctx)
532 char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
535 sprintf(mutex_name, "libusb_init%08lX", ULONG_CAST(GetCurrentProcessId() & 0xFFFFFFFFU));
536 mutex = CreateMutexA(NULL, FALSE, mutex_name);
540 // A successful wait gives this thread ownership of the mutex
541 // => any concurent wait stalls until the mutex is released
542 if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
543 usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
548 // Only works if exits and inits are balanced exactly
549 if (--init_count == 0) { // Last exit
550 if (usbdk_available) {
551 usbdk_backend.exit(ctx);
552 usbdk_available = false;
554 winusb_backend.exit(ctx);
562 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
564 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
569 case LIBUSB_OPTION_USE_USBDK:
570 if (usbdk_available) {
571 usbi_dbg("switching context %p to use UsbDk backend", ctx);
572 priv->backend = &usbdk_backend;
574 usbi_err(ctx, "UsbDk backend not available");
575 return LIBUSB_ERROR_NOT_FOUND;
577 return LIBUSB_SUCCESS;
579 return LIBUSB_ERROR_NOT_SUPPORTED;
583 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
585 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
586 return priv->backend->get_device_list(ctx, discdevs);
589 static int windows_open(struct libusb_device_handle *dev_handle)
591 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
592 return priv->backend->open(dev_handle);
595 static void windows_close(struct libusb_device_handle *dev_handle)
597 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
598 priv->backend->close(dev_handle);
601 static int windows_get_device_descriptor(struct libusb_device *dev,
602 unsigned char *buffer, int *host_endian)
604 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
606 return priv->backend->get_device_descriptor(dev, buffer);
609 static int windows_get_active_config_descriptor(struct libusb_device *dev,
610 unsigned char *buffer, size_t len, int *host_endian)
612 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
614 return priv->backend->get_active_config_descriptor(dev, buffer, len);
617 static int windows_get_config_descriptor(struct libusb_device *dev,
618 uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
620 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
622 return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
625 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
626 uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian)
628 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
630 return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
633 static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
635 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
636 return priv->backend->get_configuration(dev_handle, config);
639 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
641 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
642 return priv->backend->set_configuration(dev_handle, config);
645 static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
647 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
648 return priv->backend->claim_interface(dev_handle, interface_number);
651 static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
653 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
654 return priv->backend->release_interface(dev_handle, interface_number);
657 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
658 int interface_number, int altsetting)
660 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
661 return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
664 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
666 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
667 return priv->backend->clear_halt(dev_handle, endpoint);
670 static int windows_reset_device(struct libusb_device_handle *dev_handle)
672 struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
673 return priv->backend->reset_device(dev_handle);
676 static void windows_destroy_device(struct libusb_device *dev)
678 struct windows_context_priv *priv = usbi_get_context_priv(DEVICE_CTX(dev));
679 priv->backend->destroy_device(dev);
682 static int windows_submit_transfer(struct usbi_transfer *itransfer)
684 struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
685 struct libusb_context *ctx = TRANSFER_CTX(transfer);
686 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
687 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
691 switch (transfer->type) {
692 case LIBUSB_TRANSFER_TYPE_CONTROL:
693 events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
695 case LIBUSB_TRANSFER_TYPE_BULK:
696 case LIBUSB_TRANSFER_TYPE_INTERRUPT:
697 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
698 events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
700 case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
701 usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
702 return LIBUSB_ERROR_NOT_SUPPORTED;
704 usbi_err(ctx, "unknown endpoint type %d", transfer->type);
705 return LIBUSB_ERROR_INVALID_PARAM;
708 // Because a Windows OVERLAPPED is used for poll emulation,
709 // a pollable fd is created and stored with each transfer
710 transfer_priv->pollable_fd = usbi_create_fd();
711 if (transfer_priv->pollable_fd.fd < 0) {
712 usbi_err(ctx, "failed to create pollable fd");
713 return LIBUSB_ERROR_NO_MEM;
716 if (transfer_priv->handle != NULL) {
717 usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
718 transfer_priv->handle = NULL;
721 r = priv->backend->submit_transfer(itransfer);
722 if (r != LIBUSB_SUCCESS) {
723 // Always call the backend's clear_transfer_priv() function on failure
724 priv->backend->clear_transfer_priv(itransfer);
725 // Release the pollable fd since it won't be used
726 usbi_close(transfer_priv->pollable_fd.fd);
727 transfer_priv->pollable_fd = INVALID_WINFD;
728 transfer_priv->handle = NULL;
732 // The backend should set the HANDLE used for each submitted transfer
733 // by calling set_transfer_priv_handle()
734 if (transfer_priv->handle == NULL)
735 usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
737 // We don't want to start monitoring the pollable fd before the transfer
738 // has been submitted, so start monitoring it now. Note that if the
739 // usbi_add_pollfd() function fails, the user will never get notified
740 // that the transfer has completed. We don't attempt any cleanup if this
741 // happens because the transfer is already in progress and could even have
743 if (usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, events))
744 usbi_err(ctx, "failed to add pollable fd %d for transfer %p",
745 transfer_priv->pollable_fd.fd, transfer);
750 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
752 struct windows_context_priv *priv = usbi_get_context_priv(ITRANSFER_CTX(itransfer));
753 struct windows_transfer_priv *transfer_priv = usbi_get_transfer_priv(itransfer);
755 // Try CancelIoEx() on the transfer
756 // If that fails, fall back to the backend's cancel_transfer()
757 // function if it is available
758 if (CancelIoEx(transfer_priv->handle, transfer_priv->pollable_fd.overlapped))
759 return LIBUSB_SUCCESS;
760 else if (GetLastError() == ERROR_NOT_FOUND)
761 return LIBUSB_ERROR_NOT_FOUND;
763 if (priv->backend->cancel_transfer)
764 return priv->backend->cancel_transfer(itransfer);
766 usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
767 return LIBUSB_ERROR_NOT_SUPPORTED;
770 static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, usbi_nfds_t nfds, int num_ready)
772 struct windows_context_priv *priv = usbi_get_context_priv(ctx);
773 struct usbi_transfer *itransfer;
774 struct windows_transfer_priv *transfer_priv;
775 DWORD result, bytes_transferred;
777 int r = LIBUSB_SUCCESS;
779 usbi_mutex_lock(&ctx->open_devs_lock);
780 for (i = 0; i < nfds && num_ready > 0; i++) {
781 usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
788 transfer_priv = NULL;
789 usbi_mutex_lock(&ctx->flying_transfers_lock);
790 list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
791 transfer_priv = usbi_get_transfer_priv(itransfer);
792 if (transfer_priv->pollable_fd.fd == fds[i].fd)
794 transfer_priv = NULL;
796 usbi_mutex_unlock(&ctx->flying_transfers_lock);
798 if (transfer_priv == NULL) {
799 usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd);
800 r = LIBUSB_ERROR_NOT_FOUND;
804 usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
806 if (GetOverlappedResult(transfer_priv->handle, transfer_priv->pollable_fd.overlapped, &bytes_transferred, FALSE))
809 result = GetLastError();
811 windows_transfer_callback(priv->backend, itransfer, result, bytes_transferred);
813 usbi_mutex_unlock(&ctx->open_devs_lock);
818 #if !defined(HAVE_CLOCK_GETTIME)
819 int usbi_clock_gettime(int clk_id, struct timespec *tp)
821 LARGE_INTEGER hires_counter;
822 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
824 ULARGE_INTEGER rtime;
828 case USBI_CLOCK_MONOTONIC:
829 if (hires_frequency) {
830 QueryPerformanceCounter(&hires_counter);
831 tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
832 tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
835 // Fall through and return real-time if monotonic was not detected @ timer init
836 case USBI_CLOCK_REALTIME:
837 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
838 if (!timespec_get(tp, TIME_UTC)) {
843 // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
844 // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00
845 // Note however that our resolution is bounded by the Windows system time
846 // functions and is at best of the order of 1 ms (or, usually, worse)
847 GetSystemTimeAsFileTime(&filetime);
848 rtime.LowPart = filetime.dwLowDateTime;
849 rtime.HighPart = filetime.dwHighDateTime;
850 rtime.QuadPart -= EPOCH_TIME;
851 tp->tv_sec = (long)(rtime.QuadPart / 10000000);
852 tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
862 // NB: MSVC6 does not support named initializers.
863 const struct usbi_os_backend usbi_backend = {
865 USBI_CAP_HAS_HID_ACCESS,
869 windows_get_device_list,
870 NULL, /* hotplug_poll */
871 NULL, /* wrap_sys_device */
874 windows_get_device_descriptor,
875 windows_get_active_config_descriptor,
876 windows_get_config_descriptor,
877 windows_get_config_descriptor_by_value,
878 windows_get_configuration,
879 windows_set_configuration,
880 windows_claim_interface,
881 windows_release_interface,
882 windows_set_interface_altsetting,
884 windows_reset_device,
885 NULL, /* alloc_streams */
886 NULL, /* free_streams */
887 NULL, /* dev_mem_alloc */
888 NULL, /* dev_mem_free */
889 NULL, /* kernel_driver_active */
890 NULL, /* detach_kernel_driver */
891 NULL, /* attach_kernel_driver */
892 windows_destroy_device,
893 windows_submit_transfer,
894 windows_cancel_transfer,
895 NULL, /* clear_transfer_priv */
896 windows_handle_events,
897 NULL, /* handle_transfer_completion */
898 sizeof(struct windows_context_priv),
899 sizeof(union windows_device_priv),
900 sizeof(union windows_device_handle_priv),
901 sizeof(struct windows_transfer_priv),