libusb 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +10 -0
  3. data/.yardopts +6 -1
  4. data/Gemfile +16 -0
  5. data/{History.txt → History.md} +28 -16
  6. data/README.md +144 -0
  7. data/Rakefile +28 -24
  8. data/ext/extconf.rb +33 -0
  9. data/ext/libusbx-1.0.14/AUTHORS +50 -0
  10. data/ext/libusbx-1.0.14/COPYING +504 -0
  11. data/ext/libusbx-1.0.14/ChangeLog +139 -0
  12. data/ext/libusbx-1.0.14/INSTALL +234 -0
  13. data/ext/libusbx-1.0.14/Makefile.am +23 -0
  14. data/ext/libusbx-1.0.14/Makefile.in +803 -0
  15. data/ext/libusbx-1.0.14/NEWS +2 -0
  16. data/ext/libusbx-1.0.14/PORTING +94 -0
  17. data/ext/libusbx-1.0.14/README +28 -0
  18. data/ext/libusbx-1.0.14/THANKS +7 -0
  19. data/ext/libusbx-1.0.14/TODO +2 -0
  20. data/ext/libusbx-1.0.14/aclocal.m4 +9480 -0
  21. data/ext/libusbx-1.0.14/compile +143 -0
  22. data/ext/libusbx-1.0.14/config.guess +1501 -0
  23. data/ext/libusbx-1.0.14/config.h.in +116 -0
  24. data/ext/libusbx-1.0.14/config.sub +1705 -0
  25. data/ext/libusbx-1.0.14/configure +14818 -0
  26. data/ext/libusbx-1.0.14/configure.ac +230 -0
  27. data/ext/libusbx-1.0.14/depcomp +630 -0
  28. data/ext/libusbx-1.0.14/doc/Makefile.am +9 -0
  29. data/ext/libusbx-1.0.14/doc/Makefile.in +380 -0
  30. data/ext/libusbx-1.0.14/doc/doxygen.cfg.in +1288 -0
  31. data/ext/libusbx-1.0.14/examples/Makefile.am +18 -0
  32. data/ext/libusbx-1.0.14/examples/Makefile.in +596 -0
  33. data/ext/libusbx-1.0.14/examples/dpfp.c +506 -0
  34. data/ext/libusbx-1.0.14/examples/dpfp_threaded.c +544 -0
  35. data/ext/libusbx-1.0.14/examples/ezusb.c +616 -0
  36. data/ext/libusbx-1.0.14/examples/ezusb.h +107 -0
  37. data/ext/libusbx-1.0.14/examples/fxload.c +261 -0
  38. data/ext/libusbx-1.0.14/examples/getopt/getopt.c +1060 -0
  39. data/ext/libusbx-1.0.14/examples/getopt/getopt.h +180 -0
  40. data/ext/libusbx-1.0.14/examples/getopt/getopt1.c +188 -0
  41. data/ext/libusbx-1.0.14/examples/listdevs.c +63 -0
  42. data/ext/libusbx-1.0.14/examples/xusb.c +1036 -0
  43. data/ext/libusbx-1.0.14/install-sh +520 -0
  44. data/ext/libusbx-1.0.14/libusb-1.0.pc.in +11 -0
  45. data/ext/libusbx-1.0.14/libusb/Makefile.am +56 -0
  46. data/ext/libusbx-1.0.14/libusb/Makefile.in +721 -0
  47. data/ext/libusbx-1.0.14/libusb/core.c +1951 -0
  48. data/ext/libusbx-1.0.14/libusb/descriptor.c +731 -0
  49. data/ext/libusbx-1.0.14/libusb/io.c +2450 -0
  50. data/ext/libusbx-1.0.14/libusb/libusb-1.0.def +126 -0
  51. data/ext/libusbx-1.0.14/libusb/libusb-1.0.rc +59 -0
  52. data/ext/libusbx-1.0.14/libusb/libusb.h +1506 -0
  53. data/ext/libusbx-1.0.14/libusb/libusbi.h +910 -0
  54. data/ext/libusbx-1.0.14/libusb/os/darwin_usb.c +1807 -0
  55. data/ext/libusbx-1.0.14/libusb/os/darwin_usb.h +169 -0
  56. data/ext/libusbx-1.0.14/libusb/os/linux_usbfs.c +2569 -0
  57. data/ext/libusbx-1.0.14/libusb/os/linux_usbfs.h +149 -0
  58. data/ext/libusbx-1.0.14/libusb/os/openbsd_usb.c +727 -0
  59. data/ext/libusbx-1.0.14/libusb/os/poll_posix.h +10 -0
  60. data/ext/libusbx-1.0.14/libusb/os/poll_windows.c +747 -0
  61. data/ext/libusbx-1.0.14/libusb/os/poll_windows.h +114 -0
  62. data/ext/libusbx-1.0.14/libusb/os/threads_posix.c +80 -0
  63. data/ext/libusbx-1.0.14/libusb/os/threads_posix.h +50 -0
  64. data/ext/libusbx-1.0.14/libusb/os/threads_windows.c +211 -0
  65. data/ext/libusbx-1.0.14/libusb/os/threads_windows.h +87 -0
  66. data/ext/libusbx-1.0.14/libusb/os/windows_usb.c +4369 -0
  67. data/ext/libusbx-1.0.14/libusb/os/windows_usb.h +979 -0
  68. data/ext/libusbx-1.0.14/libusb/sync.c +321 -0
  69. data/ext/libusbx-1.0.14/libusb/version.h +18 -0
  70. data/ext/libusbx-1.0.14/libusb/version_nano.h +1 -0
  71. data/ext/libusbx-1.0.14/ltmain.sh +9636 -0
  72. data/ext/libusbx-1.0.14/missing +376 -0
  73. data/lib/libusb.rb +2 -3
  74. data/lib/libusb/call.rb +49 -7
  75. data/lib/libusb/compat.rb +15 -9
  76. data/lib/libusb/configuration.rb +15 -3
  77. data/lib/libusb/constants.rb +19 -6
  78. data/lib/libusb/context.rb +181 -3
  79. data/lib/libusb/dev_handle.rb +91 -40
  80. data/lib/libusb/endpoint.rb +41 -14
  81. data/lib/libusb/eventmachine.rb +183 -0
  82. data/lib/libusb/transfer.rb +21 -8
  83. data/lib/libusb/version_gem.rb +19 -0
  84. data/lib/libusb/{version.rb → version_struct.rb} +0 -0
  85. data/libusb.gemspec +31 -0
  86. data/test/test_libusb_compat.rb +1 -1
  87. data/test/test_libusb_compat_mass_storage.rb +2 -2
  88. data/test/test_libusb_descriptors.rb +1 -1
  89. data/test/test_libusb_event_machine.rb +118 -0
  90. data/test/test_libusb_iso_transfer.rb +6 -1
  91. data/test/test_libusb_mass_storage.rb +9 -3
  92. data/test/test_libusb_mass_storage2.rb +1 -1
  93. data/test/test_libusb_structs.rb +45 -0
  94. data/test/test_libusb_threads.rb +89 -0
  95. data/test/test_libusb_version.rb +4 -0
  96. metadata +109 -44
  97. data/.autotest +0 -23
  98. data/.gemtest +0 -0
  99. data/Manifest.txt +0 -3
  100. data/README.rdoc +0 -115
  101. data/test/test_libusb_keyboard.rb +0 -50
@@ -0,0 +1,114 @@
1
+ /*
2
+ * Windows compat: POSIX compatibility wrapper
3
+ * Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
4
+ * With contributions from Michael Plante, Orin Eman et al.
5
+ * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ *
21
+ */
22
+ #pragma once
23
+
24
+ #if defined(_MSC_VER)
25
+ // disable /W4 MSVC warnings that are benign
26
+ #pragma warning(disable:4127) // conditional expression is constant
27
+ #endif
28
+
29
+ // Handle synchronous completion through the overlapped structure
30
+ #if !defined(STATUS_REPARSE) // reuse the REPARSE status code
31
+ #define STATUS_REPARSE ((LONG)0x00000104L)
32
+ #endif
33
+ #define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE
34
+ #define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY)
35
+
36
+ #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
37
+
38
+ enum windows_version {
39
+ WINDOWS_UNSUPPORTED,
40
+ WINDOWS_XP,
41
+ WINDOWS_2003, // also includes XP 64
42
+ WINDOWS_VISTA_AND_LATER,
43
+ };
44
+ extern enum windows_version windows_version;
45
+
46
+ #define MAX_FDS 256
47
+
48
+ #define POLLIN 0x0001 /* There is data to read */
49
+ #define POLLPRI 0x0002 /* There is urgent data to read */
50
+ #define POLLOUT 0x0004 /* Writing now will not block */
51
+ #define POLLERR 0x0008 /* Error condition */
52
+ #define POLLHUP 0x0010 /* Hung up */
53
+ #define POLLNVAL 0x0020 /* Invalid request: fd not open */
54
+
55
+ struct pollfd {
56
+ int fd; /* file descriptor */
57
+ short events; /* requested events */
58
+ short revents; /* returned events */
59
+ };
60
+
61
+ // access modes
62
+ enum rw_type {
63
+ RW_NONE,
64
+ RW_READ,
65
+ RW_WRITE,
66
+ };
67
+
68
+ // fd struct that can be used for polling on Windows
69
+ struct winfd {
70
+ int fd; // what's exposed to libusb core
71
+ HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it
72
+ OVERLAPPED* overlapped; // what will report our I/O status
73
+ enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH)
74
+ };
75
+ extern const struct winfd INVALID_WINFD;
76
+
77
+ int usbi_pipe(int pipefd[2]);
78
+ int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout);
79
+ ssize_t usbi_write(int fd, const void *buf, size_t count);
80
+ ssize_t usbi_read(int fd, void *buf, size_t count);
81
+ int usbi_close(int fd);
82
+
83
+ void init_polling(void);
84
+ void exit_polling(void);
85
+ struct winfd usbi_create_fd(HANDLE handle, int access_mode);
86
+ void usbi_free_fd(int fd);
87
+ struct winfd fd_to_winfd(int fd);
88
+ struct winfd handle_to_winfd(HANDLE handle);
89
+ struct winfd overlapped_to_winfd(OVERLAPPED* overlapped);
90
+
91
+ /*
92
+ * Timeval operations
93
+ */
94
+ #if defined(DDKBUILD)
95
+ #include <winsock.h> // defines timeval functions on DDK
96
+ #endif
97
+
98
+ #if !defined(TIMESPEC_TO_TIMEVAL)
99
+ #define TIMESPEC_TO_TIMEVAL(tv, ts) { \
100
+ (tv)->tv_sec = (long)(ts)->tv_sec; \
101
+ (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \
102
+ }
103
+ #endif
104
+ #if !defined(timersub)
105
+ #define timersub(a, b, result) \
106
+ do { \
107
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
108
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
109
+ if ((result)->tv_usec < 0) { \
110
+ --(result)->tv_sec; \
111
+ (result)->tv_usec += 1000000; \
112
+ } \
113
+ } while (0)
114
+ #endif
@@ -0,0 +1,80 @@
1
+ /*
2
+ * libusbx synchronization using POSIX Threads
3
+ *
4
+ * Copyright © 2011 Vitali Lovich <vlovich@aliph.com>
5
+ * Copyright © 2011 Peter Stuge <peter@stuge.se>
6
+ *
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with this library; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+
22
+ #if defined(__linux__) || defined(__OpenBSD__)
23
+ # if defined(__linux__)
24
+ # define _GNU_SOURCE
25
+ # else
26
+ # define _BSD_SOURCE
27
+ # endif
28
+ # include <unistd.h>
29
+ # include <sys/syscall.h>
30
+ #elif defined(__APPLE__)
31
+ # include <mach/mach.h>
32
+ #elif defined(__CYGWIN__)
33
+ # include <windows.h>
34
+ #endif
35
+
36
+ #include "threads_posix.h"
37
+
38
+ int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
39
+ {
40
+ int err;
41
+ pthread_mutexattr_t stack_attr;
42
+ if (!attr) {
43
+ attr = &stack_attr;
44
+ err = pthread_mutexattr_init(&stack_attr);
45
+ if (err != 0)
46
+ return err;
47
+ }
48
+
49
+ /* mutexattr_settype requires _GNU_SOURCE or _XOPEN_SOURCE >= 500 on Linux */
50
+ err = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_RECURSIVE);
51
+ if (err != 0)
52
+ goto finish;
53
+
54
+ err = pthread_mutex_init(mutex, attr);
55
+
56
+ finish:
57
+ if (attr == &stack_attr)
58
+ pthread_mutexattr_destroy(&stack_attr);
59
+
60
+ return err;
61
+ }
62
+
63
+ int usbi_get_tid(void)
64
+ {
65
+ int ret = -1;
66
+ #if defined(__linux__)
67
+ ret = syscall(SYS_gettid);
68
+ #elif defined(__OpenBSD__)
69
+ /* The following only works with OpenBSD > 5.1 as it requires
70
+ real thread support. For 5.1 and earlier, -1 is returned. */
71
+ ret = syscall(SYS_getthrid);
72
+ #elif defined(__APPLE__)
73
+ ret = mach_thread_self();
74
+ mach_port_deallocate(mach_task_self(), ret);
75
+ #elif defined(__CYGWIN__)
76
+ ret = GetCurrentThreadId();
77
+ #endif
78
+ /* TODO: NetBSD thread ID support */
79
+ return ret;
80
+ }
@@ -0,0 +1,50 @@
1
+ /*
2
+ * libusbx synchronization using POSIX Threads
3
+ *
4
+ * Copyright © 2010 Peter Stuge <peter@stuge.se>
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ #ifndef LIBUSB_THREADS_POSIX_H
22
+ #define LIBUSB_THREADS_POSIX_H
23
+
24
+ #include <pthread.h>
25
+
26
+ #define usbi_mutex_static_t pthread_mutex_t
27
+ #define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
28
+ #define usbi_mutex_static_lock pthread_mutex_lock
29
+ #define usbi_mutex_static_unlock pthread_mutex_unlock
30
+
31
+ #define usbi_mutex_t pthread_mutex_t
32
+ #define usbi_mutex_init pthread_mutex_init
33
+ #define usbi_mutex_lock pthread_mutex_lock
34
+ #define usbi_mutex_unlock pthread_mutex_unlock
35
+ #define usbi_mutex_trylock pthread_mutex_trylock
36
+ #define usbi_mutex_destroy pthread_mutex_destroy
37
+
38
+ #define usbi_cond_t pthread_cond_t
39
+ #define usbi_cond_init pthread_cond_init
40
+ #define usbi_cond_wait pthread_cond_wait
41
+ #define usbi_cond_timedwait pthread_cond_timedwait
42
+ #define usbi_cond_broadcast pthread_cond_broadcast
43
+ #define usbi_cond_destroy pthread_cond_destroy
44
+ #define usbi_cond_signal pthread_cond_signal
45
+
46
+ extern int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr);
47
+
48
+ int usbi_get_tid(void);
49
+
50
+ #endif /* LIBUSB_THREADS_POSIX_H */
@@ -0,0 +1,211 @@
1
+ /*
2
+ * libusbx synchronization on Microsoft Windows
3
+ *
4
+ * Copyright © 2010 Michael Plante <michael.plante@gmail.com>
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+ #include <config.h>
22
+ #include <objbase.h>
23
+ #include <errno.h>
24
+ #include <stdarg.h>
25
+
26
+ #include "libusbi.h"
27
+
28
+
29
+ int usbi_mutex_init(usbi_mutex_t *mutex,
30
+ const usbi_mutexattr_t *attr) {
31
+ UNUSED(attr);
32
+ if(! mutex) return ((errno=EINVAL));
33
+ *mutex = CreateMutex(NULL, FALSE, NULL);
34
+ if(!*mutex) return ((errno=ENOMEM));
35
+ return 0;
36
+ }
37
+ int usbi_mutex_destroy(usbi_mutex_t *mutex) {
38
+ // It is not clear if CloseHandle failure is due to failure to unlock.
39
+ // If so, this should be errno=EBUSY.
40
+ if(!mutex || !CloseHandle(*mutex)) return ((errno=EINVAL));
41
+ *mutex = NULL;
42
+ return 0;
43
+ }
44
+ int usbi_mutex_trylock(usbi_mutex_t *mutex) {
45
+ DWORD result;
46
+ if(!mutex) return ((errno=EINVAL));
47
+ result = WaitForSingleObject(*mutex, 0);
48
+ if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
49
+ return 0; // acquired (ToDo: check that abandoned is ok)
50
+ if(result == WAIT_TIMEOUT)
51
+ return ((errno=EBUSY));
52
+ return ((errno=EINVAL)); // don't know how this would happen
53
+ // so don't know proper errno
54
+ }
55
+ int usbi_mutex_lock(usbi_mutex_t *mutex) {
56
+ DWORD result;
57
+ if(!mutex) return ((errno=EINVAL));
58
+ result = WaitForSingleObject(*mutex, INFINITE);
59
+ if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
60
+ return 0; // acquired (ToDo: check that abandoned is ok)
61
+ return ((errno=EINVAL)); // don't know how this would happen
62
+ // so don't know proper errno
63
+ }
64
+ int usbi_mutex_unlock(usbi_mutex_t *mutex) {
65
+ if(!mutex) return ((errno=EINVAL));
66
+ if(!ReleaseMutex(*mutex)) return ((errno=EPERM ));
67
+ return 0;
68
+ }
69
+
70
+ int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) {
71
+ if(!mutex) return ((errno=EINVAL));
72
+ while (InterlockedExchange((LONG *)mutex, 1) == 1) {
73
+ SleepEx(0, TRUE);
74
+ }
75
+ return 0;
76
+ }
77
+ int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) {
78
+ if(!mutex) return ((errno=EINVAL));
79
+ *mutex = 0;
80
+ return 0;
81
+ }
82
+
83
+
84
+
85
+ int usbi_cond_init(usbi_cond_t *cond,
86
+ const usbi_condattr_t *attr) {
87
+ UNUSED(attr);
88
+ if(!cond) return ((errno=EINVAL));
89
+ list_init(&cond->waiters );
90
+ list_init(&cond->not_waiting);
91
+ return 0;
92
+ }
93
+ int usbi_cond_destroy(usbi_cond_t *cond) {
94
+ // This assumes no one is using this anymore. The check MAY NOT BE safe.
95
+ struct usbi_cond_perthread *pos, *next_pos = NULL;
96
+ if(!cond) return ((errno=EINVAL));
97
+ if(!list_empty(&cond->waiters)) return ((errno=EBUSY )); // (!see above!)
98
+ list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
99
+ CloseHandle(pos->event);
100
+ list_del(&pos->list);
101
+ free(pos);
102
+ }
103
+
104
+ return 0;
105
+ }
106
+
107
+ int usbi_cond_broadcast(usbi_cond_t *cond) {
108
+ // Assumes mutex is locked; this is not in keeping with POSIX spec, but
109
+ // libusb does this anyway, so we simplify by not adding more sync
110
+ // primitives to the CV definition!
111
+ int fail = 0;
112
+ struct usbi_cond_perthread *pos;
113
+ if(!cond) return ((errno=EINVAL));
114
+ list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) {
115
+ if(!SetEvent(pos->event))
116
+ fail = 1;
117
+ }
118
+ // The wait function will remove its respective item from the list.
119
+ return fail ? ((errno=EINVAL)) : 0;
120
+ }
121
+ int usbi_cond_signal(usbi_cond_t *cond) {
122
+ // Assumes mutex is locked; this is not in keeping with POSIX spec, but
123
+ // libusb does this anyway, so we simplify by not adding more sync
124
+ // primitives to the CV definition!
125
+ struct usbi_cond_perthread *pos;
126
+ if(!cond) return ((errno=EINVAL));
127
+ if(list_empty(&cond->waiters)) return 0; // no one to wakeup.
128
+ pos = list_entry(&cond->waiters.next, struct usbi_cond_perthread, list);
129
+ // The wait function will remove its respective item from the list.
130
+ return SetEvent(pos->event) ? 0 : ((errno=EINVAL));
131
+ }
132
+ static int __inline usbi_cond_intwait(usbi_cond_t *cond,
133
+ usbi_mutex_t *mutex,
134
+ DWORD timeout_ms) {
135
+ struct usbi_cond_perthread *pos;
136
+ int found = 0, r;
137
+ DWORD r2,tid = GetCurrentThreadId();
138
+ if(!cond || !mutex) return ((errno=EINVAL));
139
+ list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
140
+ if(tid == pos->tid) {
141
+ found = 1;
142
+ break;
143
+ }
144
+ }
145
+ if(!found) {
146
+ pos = (struct usbi_cond_perthread*) calloc(1, sizeof(struct usbi_cond_perthread));
147
+ if(!pos) return ((errno=ENOMEM)); // This errno is not POSIX-allowed.
148
+ pos->tid = tid;
149
+ pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
150
+ if(!pos->event) {
151
+ free(pos);
152
+ return ((errno=ENOMEM));
153
+ }
154
+ list_add(&pos->list, &cond->not_waiting);
155
+ }
156
+
157
+ list_del(&pos->list); // remove from not_waiting list.
158
+ list_add(&pos->list, &cond->waiters);
159
+
160
+ r = usbi_mutex_unlock(mutex);
161
+ if(r) return r;
162
+ r2 = WaitForSingleObject(pos->event, timeout_ms);
163
+ r = usbi_mutex_lock(mutex);
164
+ if(r) return r;
165
+
166
+ list_del(&pos->list);
167
+ list_add(&pos->list, &cond->not_waiting);
168
+
169
+ if(r2 == WAIT_TIMEOUT) return ((errno=ETIMEDOUT));
170
+
171
+ return 0;
172
+ }
173
+ // N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
174
+ int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) {
175
+ return usbi_cond_intwait(cond, mutex, INFINITE);
176
+ }
177
+ int usbi_cond_timedwait(usbi_cond_t *cond,
178
+ usbi_mutex_t *mutex,
179
+ const struct timespec *abstime) {
180
+ FILETIME filetime;
181
+ ULARGE_INTEGER rtime;
182
+ struct timeval targ_time, cur_time, delta_time;
183
+ struct timespec cur_time_ns;
184
+ DWORD millis;
185
+ extern const uint64_t epoch_time;
186
+
187
+ GetSystemTimeAsFileTime(&filetime);
188
+ rtime.LowPart = filetime.dwLowDateTime;
189
+ rtime.HighPart = filetime.dwHighDateTime;
190
+ rtime.QuadPart -= epoch_time;
191
+ cur_time_ns.tv_sec = (long)(rtime.QuadPart / 10000000);
192
+ cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
193
+ TIMESPEC_TO_TIMEVAL(&cur_time, &cur_time_ns);
194
+
195
+ TIMESPEC_TO_TIMEVAL(&targ_time, abstime);
196
+ timersub(&targ_time, &cur_time, &delta_time);
197
+ if(delta_time.tv_sec < 0) // abstime already passed?
198
+ millis = 0;
199
+ else {
200
+ millis = delta_time.tv_usec/1000;
201
+ millis += delta_time.tv_sec *1000;
202
+ if (delta_time.tv_usec % 1000) // round up to next millisecond
203
+ millis++;
204
+ }
205
+
206
+ return usbi_cond_intwait(cond, mutex, millis);
207
+ }
208
+
209
+ int usbi_get_tid(void) {
210
+ return GetCurrentThreadId();
211
+ }