configure.ac: Cleanup and refactoring
[platform/upstream/libusb.git] / libusb / os / windows_common.c
1 /*
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
9  *
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.
14  *
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.
19  *
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
23  */
24
25 #include <config.h>
26
27 #include <inttypes.h>
28 #include <process.h>
29 #include <stdio.h>
30
31 #include "libusbi.h"
32 #include "windows_common.h"
33
34 #define EPOCH_TIME      UINT64_C(116444736000000000)    // 1970.01.01 00:00:000 in MS Filetime
35
36 // Public
37 enum windows_version windows_version = WINDOWS_UNDEFINED;
38
39  // Global variables for init/exit
40 static unsigned int init_count = 0;
41 static bool usbdk_available = false;
42
43 // Global variables for clock_gettime mechanism
44 static uint64_t hires_ticks_to_ps;
45 static uint64_t hires_frequency;
46
47 /*
48 * Converts a windows error to human readable string
49 * uses retval as errorcode, or, if 0, use GetLastError()
50 */
51 #if defined(ENABLE_LOGGING)
52 const char *windows_error_str(DWORD error_code)
53 {
54         static char err_string[256];
55
56         DWORD size;
57         int len;
58
59         if (error_code == 0)
60                 error_code = GetLastError();
61
62         len = sprintf(err_string, "[%lu] ", error_code);
63
64         // Translate codes returned by SetupAPI. The ones we are dealing with are either
65         // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
66         // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
67         switch (error_code & 0xE0000000) {
68         case 0:
69                 error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
70                 break;
71         case 0xE0000000:
72                 error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
73                 break;
74         default:
75                 break;
76         }
77
78         size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
79                         NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
80                         &err_string[len], sizeof(err_string) - len, NULL);
81         if (size == 0) {
82                 DWORD format_error = GetLastError();
83                 if (format_error)
84                         snprintf(err_string, sizeof(err_string),
85                                 "Windows error code %lu (FormatMessage error code %lu)",
86                                 error_code, format_error);
87                 else
88                         snprintf(err_string, sizeof(err_string), "Unknown error code %lu", error_code);
89         } else {
90                 // Remove CRLF from end of message, if present
91                 size_t pos = len + size - 2;
92                 if (err_string[pos] == '\r')
93                         err_string[pos] = '\0';
94         }
95
96         return err_string;
97 }
98 #endif
99
100 static inline struct windows_context_priv *_context_priv(struct libusb_context *ctx)
101 {
102         return (struct windows_context_priv *)ctx->os_priv;
103 }
104
105 /* Hash table functions - modified From glibc 2.3.2:
106    [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
107    [Knuth]            The Art of Computer Programming, part 3 (6.4)  */
108
109 #define HTAB_SIZE 1021UL        // *MUST* be a prime number!!
110
111 typedef struct htab_entry {
112         unsigned long used;
113         char *str;
114 } htab_entry;
115
116 static htab_entry *htab_table = NULL;
117 static usbi_mutex_t htab_mutex;
118 static unsigned long htab_filled;
119
120 /* Before using the hash table we must allocate memory for it.
121    We allocate one element more as the found prime number says.
122    This is done for more effective indexing as explained in the
123    comment for the hash function.  */
124 static bool htab_create(struct libusb_context *ctx)
125 {
126         if (htab_table != NULL) {
127                 usbi_err(ctx, "hash table already allocated");
128                 return true;
129         }
130
131         // Create a mutex
132         usbi_mutex_init(&htab_mutex);
133
134         usbi_dbg("using %lu entries hash table", HTAB_SIZE);
135         htab_filled = 0;
136
137         // allocate memory and zero out.
138         htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry));
139         if (htab_table == NULL) {
140                 usbi_err(ctx, "could not allocate space for hash table");
141                 return false;
142         }
143
144         return true;
145 }
146
147 /* After using the hash table it has to be destroyed.  */
148 static void htab_destroy(void)
149 {
150         unsigned long i;
151
152         if (htab_table == NULL)
153                 return;
154
155         for (i = 0; i < HTAB_SIZE; i++)
156                 free(htab_table[i].str);
157
158         safe_free(htab_table);
159
160         usbi_mutex_destroy(&htab_mutex);
161 }
162
163 /* This is the search function. It uses double hashing with open addressing.
164    We use a trick to speed up the lookup. The table is created with one
165    more element available. This enables us to use the index zero special.
166    This index will never be used because we store the first hash index in
167    the field used where zero means not used. Every other value means used.
168    The used field can be used as a first fast comparison for equality of
169    the stored and the parameter value. This helps to prevent unnecessary
170    expensive calls of strcmp.  */
171 unsigned long htab_hash(const char *str)
172 {
173         unsigned long hval, hval2;
174         unsigned long idx;
175         unsigned long r = 5381;
176         int c;
177         const char *sz = str;
178
179         if (str == NULL)
180                 return 0;
181
182         // Compute main hash value (algorithm suggested by Nokia)
183         while ((c = *sz++) != 0)
184                 r = ((r << 5) + r) + c;
185         if (r == 0)
186                 ++r;
187
188         // compute table hash: simply take the modulus
189         hval = r % HTAB_SIZE;
190         if (hval == 0)
191                 ++hval;
192
193         // Try the first index
194         idx = hval;
195
196         // Mutually exclusive access (R/W lock would be better)
197         usbi_mutex_lock(&htab_mutex);
198
199         if (htab_table[idx].used) {
200                 if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
201                         goto out_unlock; // existing hash
202
203                 usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
204
205                 // Second hash function, as suggested in [Knuth]
206                 hval2 = 1 + hval % (HTAB_SIZE - 2);
207
208                 do {
209                         // Because size is prime this guarantees to step through all available indexes
210                         if (idx <= hval2)
211                                 idx = HTAB_SIZE + idx - hval2;
212                         else
213                                 idx -= hval2;
214
215                         // If we visited all entries leave the loop unsuccessfully
216                         if (idx == hval)
217                                 break;
218
219                         // If entry is found use it.
220                         if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0))
221                                 goto out_unlock;
222                 } while (htab_table[idx].used);
223         }
224
225         // Not found => New entry
226
227         // If the table is full return an error
228         if (htab_filled >= HTAB_SIZE) {
229                 usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
230                 idx = 0;
231                 goto out_unlock;
232         }
233
234         htab_table[idx].str = _strdup(str);
235         if (htab_table[idx].str == NULL) {
236                 usbi_err(NULL, "could not duplicate string for hash table");
237                 idx = 0;
238                 goto out_unlock;
239         }
240
241         htab_table[idx].used = hval;
242         ++htab_filled;
243
244 out_unlock:
245         usbi_mutex_unlock(&htab_mutex);
246
247         return idx;
248 }
249
250 /*
251 * Make a transfer complete synchronously
252 */
253 void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size)
254 {
255         overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
256         overlapped->InternalHigh = size;
257         SetEvent(overlapped->hEvent);
258 }
259
260 static void windows_init_clock(void)
261 {
262         LARGE_INTEGER li_frequency;
263
264         // Microsoft says that the QueryPerformanceFrequency() and
265         // QueryPerformanceCounter() functions always succeed on XP and later
266         QueryPerformanceFrequency(&li_frequency);
267
268         // The hires frequency can go as high as 4 GHz, so we'll use a conversion
269         // to picoseconds to compute the tv_nsecs part in clock_gettime
270         hires_frequency = li_frequency.QuadPart;
271         hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
272         usbi_dbg("hires timer frequency: %"PRIu64" Hz", hires_frequency);
273 }
274
275 /* Windows version detection */
276 static BOOL is_x64(void)
277 {
278         BOOL ret = FALSE;
279
280         // Detect if we're running a 32 or 64 bit system
281         if (sizeof(uintptr_t) < 8) {
282                 IsWow64Process(GetCurrentProcess(), &ret);
283         } else {
284                 ret = TRUE;
285         }
286
287         return ret;
288 }
289
290 static void get_windows_version(void)
291 {
292         OSVERSIONINFOEXA vi, vi2;
293         const char *arch, *w = NULL;
294         unsigned major, minor, version;
295         ULONGLONG major_equal, minor_equal;
296         BOOL ws;
297
298         windows_version = WINDOWS_UNDEFINED;
299
300         memset(&vi, 0, sizeof(vi));
301         vi.dwOSVersionInfoSize = sizeof(vi);
302         if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
303                 memset(&vi, 0, sizeof(vi));
304                 vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
305                 if (!GetVersionExA((OSVERSIONINFOA *)&vi))
306                         return;
307         }
308
309         if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
310                 return;
311
312         if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) {
313                 // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
314                 // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
315
316                 major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
317                 for (major = vi.dwMajorVersion; major <= 9; major++) {
318                         memset(&vi2, 0, sizeof(vi2));
319                         vi2.dwOSVersionInfoSize = sizeof(vi2);
320                         vi2.dwMajorVersion = major;
321                         if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
322                                 continue;
323
324                         if (vi.dwMajorVersion < major) {
325                                 vi.dwMajorVersion = major;
326                                 vi.dwMinorVersion = 0;
327                         }
328
329                         minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
330                         for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
331                                 memset(&vi2, 0, sizeof(vi2));
332                                 vi2.dwOSVersionInfoSize = sizeof(vi2);
333                                 vi2.dwMinorVersion = minor;
334                                 if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
335                                         continue;
336
337                                 vi.dwMinorVersion = minor;
338                                 break;
339                         }
340
341                         break;
342                 }
343         }
344
345         if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf))
346                 return;
347
348         ws = (vi.wProductType <= VER_NT_WORKSTATION);
349         version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
350         switch (version) {
351         case 0x50: windows_version = WINDOWS_2000;  w = "2000"; break;
352         case 0x51: windows_version = WINDOWS_XP;    w = "XP";   break;
353         case 0x52: windows_version = WINDOWS_2003;  w = "2003"; break;
354         case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008");  break;
355         case 0x61: windows_version = WINDOWS_7;     w = (ws ? "7" : "2008_R2");   break;
356         case 0x62: windows_version = WINDOWS_8;     w = (ws ? "8" : "2012");      break;
357         case 0x63: windows_version = WINDOWS_8_1;   w = (ws ? "8.1" : "2012_R2"); break;
358         case 0x64: // Early Windows 10 Insider Previews and Windows Server 2017 Technical Preview 1 used version 6.4
359         case 0xA0: windows_version = WINDOWS_10;    w = (ws ? "10" : "2016");     break;
360         default:
361                 if (version < 0x50) {
362                         return;
363                 } else {
364                         windows_version = WINDOWS_11_OR_LATER;
365                         w = "11 or later";
366                 }
367         }
368
369         arch = is_x64() ? "64-bit" : "32-bit";
370
371         if (vi.wServicePackMinor)
372                 usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
373         else if (vi.wServicePackMajor)
374                 usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch);
375         else
376                 usbi_dbg("Windows %s %s", w, arch);
377 }
378
379 static void windows_transfer_callback(const struct windows_backend *backend,
380         struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
381 {
382         int status, istatus;
383
384         usbi_dbg("handling I/O completion with errcode %lu, size %lu", io_result, io_size);
385
386         switch (io_result) {
387         case NO_ERROR:
388                 status = backend->copy_transfer_data(itransfer, (uint32_t)io_size);
389                 break;
390         case ERROR_GEN_FAILURE:
391                 usbi_dbg("detected endpoint stall");
392                 status = LIBUSB_TRANSFER_STALL;
393                 break;
394         case ERROR_SEM_TIMEOUT:
395                 usbi_dbg("detected semaphore timeout");
396                 status = LIBUSB_TRANSFER_TIMED_OUT;
397                 break;
398         case ERROR_OPERATION_ABORTED:
399                 istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size);
400                 if (istatus != LIBUSB_TRANSFER_COMPLETED)
401                         usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
402
403                 usbi_dbg("detected operation aborted");
404                 status = LIBUSB_TRANSFER_CANCELLED;
405                 break;
406         case ERROR_FILE_NOT_FOUND:
407         case ERROR_DEVICE_NOT_CONNECTED:
408                 usbi_dbg("detected device removed");
409                 status = LIBUSB_TRANSFER_NO_DEVICE;
410                 break;
411         default:
412                 usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %lu: %s", io_result, windows_error_str(io_result));
413                 status = LIBUSB_TRANSFER_ERROR;
414                 break;
415         }
416         backend->clear_transfer_priv(itransfer);        // Cancel polling
417         if (status == LIBUSB_TRANSFER_CANCELLED)
418                 usbi_handle_transfer_cancellation(itransfer);
419         else
420                 usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
421 }
422
423 static void windows_handle_callback(const struct windows_backend *backend,
424         struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
425 {
426         struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
427
428         switch (transfer->type) {
429         case LIBUSB_TRANSFER_TYPE_CONTROL:
430         case LIBUSB_TRANSFER_TYPE_BULK:
431         case LIBUSB_TRANSFER_TYPE_INTERRUPT:
432         case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
433                 windows_transfer_callback(backend, itransfer, io_result, io_size);
434                 break;
435         case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
436                 usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
437                 break;
438         default:
439                 usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
440         }
441 }
442
443 static int windows_init(struct libusb_context *ctx)
444 {
445         struct windows_context_priv *priv = _context_priv(ctx);
446         HANDLE semaphore;
447         char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
448         int r = LIBUSB_ERROR_OTHER;
449         bool winusb_backend_init = false;
450
451         sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
452         semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
453         if (semaphore == NULL) {
454                 usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
455                 return LIBUSB_ERROR_NO_MEM;
456         }
457
458         // A successful wait brings our semaphore count to 0 (unsignaled)
459         // => any concurent wait stalls until the semaphore's release
460         if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
461                 usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
462                 CloseHandle(semaphore);
463                 return LIBUSB_ERROR_NO_MEM;
464         }
465
466         // NB: concurrent usage supposes that init calls are equally balanced with
467         // exit calls. If init is called more than exit, we will not exit properly
468         if (++init_count == 1) { // First init?
469                 get_windows_version();
470
471                 if (windows_version == WINDOWS_UNDEFINED) {
472                         usbi_err(ctx, "failed to detect Windows version");
473                         r = LIBUSB_ERROR_NOT_SUPPORTED;
474                         goto init_exit;
475                 }
476
477                 windows_init_clock();
478
479                 if (!htab_create(ctx))
480                         goto init_exit;
481
482                 r = winusb_backend.init(ctx);
483                 if (r != LIBUSB_SUCCESS)
484                         goto init_exit;
485                 winusb_backend_init = true;
486
487                 r = usbdk_backend.init(ctx);
488                 if (r == LIBUSB_SUCCESS) {
489                         usbi_dbg("UsbDk backend is available");
490                         usbdk_available = true;
491                 } else {
492                         usbi_info(ctx, "UsbDk backend is not available");
493                         // Do not report this as an error
494                         r = LIBUSB_SUCCESS;
495                 }
496         }
497
498         // By default, new contexts will use the WinUSB backend
499         priv->backend = &winusb_backend;
500
501         r = LIBUSB_SUCCESS;
502
503 init_exit: // Holds semaphore here
504         if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
505                 if (winusb_backend_init)
506                         winusb_backend.exit(ctx);
507                 htab_destroy();
508                 --init_count;
509         }
510
511         ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
512         CloseHandle(semaphore);
513         return r;
514 }
515
516 static void windows_exit(struct libusb_context *ctx)
517 {
518         HANDLE semaphore;
519         char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
520         UNUSED(ctx);
521
522         sprintf(sem_name, "libusb_init%08lX", (GetCurrentProcessId() & 0xFFFFFFFFUL));
523         semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
524         if (semaphore == NULL)
525                 return;
526
527         // A successful wait brings our semaphore count to 0 (unsignaled)
528         // => any concurent wait stalls until the semaphore release
529         if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
530                 CloseHandle(semaphore);
531                 return;
532         }
533
534         // Only works if exits and inits are balanced exactly
535         if (--init_count == 0) { // Last exit
536                 if (usbdk_available) {
537                         usbdk_backend.exit(ctx);
538                         usbdk_available = false;
539                 }
540                 winusb_backend.exit(ctx);
541                 htab_destroy();
542         }
543
544         ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
545         CloseHandle(semaphore);
546 }
547
548 static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
549 {
550         struct windows_context_priv *priv = _context_priv(ctx);
551
552         UNUSED(ap);
553
554         switch (option) {
555         case LIBUSB_OPTION_USE_USBDK:
556                 if (usbdk_available) {
557                         usbi_dbg("switching context %p to use UsbDk backend", ctx);
558                         priv->backend = &usbdk_backend;
559                 } else {
560                         usbi_err(ctx, "UsbDk backend not available");
561                         return LIBUSB_ERROR_NOT_FOUND;
562                 }
563                 return LIBUSB_SUCCESS;
564         default:
565                 return LIBUSB_ERROR_NOT_SUPPORTED;
566         }
567
568 }
569
570 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
571 {
572         struct windows_context_priv *priv = _context_priv(ctx);
573         return priv->backend->get_device_list(ctx, discdevs);
574 }
575
576 static int windows_open(struct libusb_device_handle *dev_handle)
577 {
578         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
579         return priv->backend->open(dev_handle);
580 }
581
582 static void windows_close(struct libusb_device_handle *dev_handle)
583 {
584         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
585         priv->backend->close(dev_handle);
586 }
587
588 static int windows_get_device_descriptor(struct libusb_device *dev,
589         unsigned char *buffer, int *host_endian)
590 {
591         struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
592         *host_endian = 0;
593         return priv->backend->get_device_descriptor(dev, buffer);
594 }
595
596 static int windows_get_active_config_descriptor(struct libusb_device *dev,
597         unsigned char *buffer, size_t len, int *host_endian)
598 {
599         struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
600         *host_endian = 0;
601         return priv->backend->get_active_config_descriptor(dev, buffer, len);
602 }
603
604 static int windows_get_config_descriptor(struct libusb_device *dev,
605         uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
606 {
607         struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
608         *host_endian = 0;
609         return priv->backend->get_config_descriptor(dev, config_index, buffer, len);
610 }
611
612 static int windows_get_config_descriptor_by_value(struct libusb_device *dev,
613         uint8_t bConfigurationValue, unsigned char **buffer, int *host_endian)
614 {
615         struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
616         *host_endian = 0;
617         return priv->backend->get_config_descriptor_by_value(dev, bConfigurationValue, buffer);
618 }
619
620 static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
621 {
622         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
623         return priv->backend->get_configuration(dev_handle, config);
624 }
625
626 static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
627 {
628         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
629         return priv->backend->set_configuration(dev_handle, config);
630 }
631
632 static int windows_claim_interface(struct libusb_device_handle *dev_handle, int interface_number)
633 {
634         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
635         return priv->backend->claim_interface(dev_handle, interface_number);
636 }
637
638 static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number)
639 {
640         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
641         return priv->backend->release_interface(dev_handle, interface_number);
642 }
643
644 static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle,
645         int interface_number, int altsetting)
646 {
647         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
648         return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting);
649 }
650
651 static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
652 {
653         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
654         return priv->backend->clear_halt(dev_handle, endpoint);
655 }
656
657 static int windows_reset_device(struct libusb_device_handle *dev_handle)
658 {
659         struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle));
660         return priv->backend->reset_device(dev_handle);
661 }
662
663 static void windows_destroy_device(struct libusb_device *dev)
664 {
665         struct windows_context_priv *priv = _context_priv(DEVICE_CTX(dev));
666         priv->backend->destroy_device(dev);
667 }
668
669 static int windows_submit_transfer(struct usbi_transfer *itransfer)
670 {
671         struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
672         return priv->backend->submit_transfer(itransfer);
673 }
674
675 static int windows_cancel_transfer(struct usbi_transfer *itransfer)
676 {
677         struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
678         return priv->backend->cancel_transfer(itransfer);
679 }
680
681 static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, usbi_nfds_t nfds, int num_ready)
682 {
683         struct windows_context_priv *priv = _context_priv(ctx);
684         struct usbi_transfer *itransfer;
685         DWORD io_size, io_result;
686         usbi_nfds_t i;
687         bool found;
688         int transfer_fd;
689         int r = LIBUSB_SUCCESS;
690
691         usbi_mutex_lock(&ctx->open_devs_lock);
692         for (i = 0; i < nfds && num_ready > 0; i++) {
693
694                 usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
695
696                 if (!fds[i].revents)
697                         continue;
698
699                 num_ready--;
700
701                 // Because a Windows OVERLAPPED is used for poll emulation,
702                 // a pollable fd is created and stored with each transfer
703                 found = false;
704                 transfer_fd = -1;
705                 usbi_mutex_lock(&ctx->flying_transfers_lock);
706                 list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
707                         transfer_fd = priv->backend->get_transfer_fd(itransfer);
708                         if (transfer_fd == fds[i].fd) {
709                                 found = true;
710                                 break;
711                         }
712                 }
713                 usbi_mutex_unlock(&ctx->flying_transfers_lock);
714
715                 if (found) {
716                         priv->backend->get_overlapped_result(itransfer, &io_result, &io_size);
717
718                         usbi_remove_pollfd(ctx, transfer_fd);
719
720                         // let handle_callback free the event using the transfer wfd
721                         // If you don't use the transfer wfd, you run a risk of trying to free a
722                         // newly allocated wfd that took the place of the one from the transfer.
723                         windows_handle_callback(priv->backend, itransfer, io_result, io_size);
724                 } else {
725                         usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd);
726                         r = LIBUSB_ERROR_NOT_FOUND;
727                         break;
728                 }
729         }
730         usbi_mutex_unlock(&ctx->open_devs_lock);
731
732         return r;
733 }
734
735 static int windows_clock_gettime(int clk_id, struct timespec *tp)
736 {
737         LARGE_INTEGER hires_counter;
738 #if !defined(_MSC_VER) || (_MSC_VER < 1900)
739         FILETIME filetime;
740         ULARGE_INTEGER rtime;
741 #endif
742
743         switch (clk_id) {
744         case USBI_CLOCK_MONOTONIC:
745                 if (hires_frequency) {
746                         QueryPerformanceCounter(&hires_counter);
747                         tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
748                         tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) * hires_ticks_to_ps) / UINT64_C(1000));
749                         return LIBUSB_SUCCESS;
750                 }
751                 // Fall through and return real-time if monotonic was not detected @ timer init
752         case USBI_CLOCK_REALTIME:
753 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
754                 if (!timespec_get(tp, TIME_UTC))
755                         return LIBUSB_ERROR_OTHER;
756 #else
757                 // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
758                 // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00
759                 // Note however that our resolution is bounded by the Windows system time
760                 // functions and is at best of the order of 1 ms (or, usually, worse)
761                 GetSystemTimeAsFileTime(&filetime);
762                 rtime.LowPart = filetime.dwLowDateTime;
763                 rtime.HighPart = filetime.dwHighDateTime;
764                 rtime.QuadPart -= EPOCH_TIME;
765                 tp->tv_sec = (long)(rtime.QuadPart / 10000000);
766                 tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
767 #endif
768                 return LIBUSB_SUCCESS;
769         default:
770                 return LIBUSB_ERROR_INVALID_PARAM;
771         }
772 }
773
774 // NB: MSVC6 does not support named initializers.
775 const struct usbi_os_backend usbi_backend = {
776         "Windows",
777         USBI_CAP_HAS_HID_ACCESS,
778         windows_init,
779         windows_exit,
780         windows_set_option,
781         windows_get_device_list,
782         NULL,   /* hotplug_poll */
783         NULL,   /* wrap_sys_device */
784         windows_open,
785         windows_close,
786         windows_get_device_descriptor,
787         windows_get_active_config_descriptor,
788         windows_get_config_descriptor,
789         windows_get_config_descriptor_by_value,
790         windows_get_configuration,
791         windows_set_configuration,
792         windows_claim_interface,
793         windows_release_interface,
794         windows_set_interface_altsetting,
795         windows_clear_halt,
796         windows_reset_device,
797         NULL,   /* alloc_streams */
798         NULL,   /* free_streams */
799         NULL,   /* dev_mem_alloc */
800         NULL,   /* dev_mem_free */
801         NULL,   /* kernel_driver_active */
802         NULL,   /* detach_kernel_driver */
803         NULL,   /* attach_kernel_driver */
804         windows_destroy_device,
805         windows_submit_transfer,
806         windows_cancel_transfer,
807         NULL,   /* clear_transfer_priv */
808         windows_handle_events,
809         NULL,   /* handle_transfer_completion */
810         windows_clock_gettime,
811         sizeof(struct windows_context_priv),
812         sizeof(union windows_device_priv),
813         sizeof(union windows_device_handle_priv),
814         sizeof(union windows_transfer_priv),
815 };