usb 2.17.0 → 3.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/LICENSE +18 -4
  2. package/README.md +25 -516
  3. package/dist/index.d.ts +67 -13
  4. package/dist/index.js +333 -64
  5. package/index.d.ts +89 -0
  6. package/index.js +583 -0
  7. package/package.json +53 -33
  8. package/CHANGELOG.md +0 -294
  9. package/binding.gyp +0 -128
  10. package/dist/index.js.map +0 -1
  11. package/dist/usb/bindings.d.ts +0 -266
  12. package/dist/usb/bindings.js +0 -10
  13. package/dist/usb/bindings.js.map +0 -1
  14. package/dist/usb/capability.d.ts +0 -13
  15. package/dist/usb/capability.js +0 -17
  16. package/dist/usb/capability.js.map +0 -1
  17. package/dist/usb/descriptors.d.ts +0 -128
  18. package/dist/usb/descriptors.js +0 -3
  19. package/dist/usb/descriptors.js.map +0 -1
  20. package/dist/usb/device.d.ts +0 -100
  21. package/dist/usb/device.js +0 -297
  22. package/dist/usb/device.js.map +0 -1
  23. package/dist/usb/endpoint.d.ts +0 -94
  24. package/dist/usb/endpoint.js +0 -219
  25. package/dist/usb/endpoint.js.map +0 -1
  26. package/dist/usb/index.d.ts +0 -31
  27. package/dist/usb/index.js +0 -116
  28. package/dist/usb/index.js.map +0 -1
  29. package/dist/usb/interface.d.ts +0 -80
  30. package/dist/usb/interface.js +0 -133
  31. package/dist/usb/interface.js.map +0 -1
  32. package/dist/webusb/index.d.ts +0 -64
  33. package/dist/webusb/index.js +0 -295
  34. package/dist/webusb/index.js.map +0 -1
  35. package/dist/webusb/webusb-device.d.ts +0 -54
  36. package/dist/webusb/webusb-device.js +0 -434
  37. package/dist/webusb/webusb-device.js.map +0 -1
  38. package/libusb/.clang-tidy +0 -34
  39. package/libusb/.codespellrc +0 -3
  40. package/libusb/.private/README.txt +0 -5
  41. package/libusb/.private/appveyor_build.sh +0 -26
  42. package/libusb/.private/bm.sh +0 -54
  43. package/libusb/.private/ci-build.sh +0 -92
  44. package/libusb/.private/ci-container-build.sh +0 -67
  45. package/libusb/.private/post-rewrite.sh +0 -32
  46. package/libusb/.private/pre-commit.sh +0 -52
  47. package/libusb/.private/wbs.txt +0 -43
  48. package/libusb/.travis.yml +0 -58
  49. package/libusb/AUTHORS +0 -231
  50. package/libusb/COPYING +0 -504
  51. package/libusb/ChangeLog +0 -365
  52. package/libusb/HACKING +0 -25
  53. package/libusb/INSTALL_WIN.txt +0 -52
  54. package/libusb/KEYS +0 -123
  55. package/libusb/Makefile.am +0 -50
  56. package/libusb/NEWS +0 -2
  57. package/libusb/PORTING +0 -94
  58. package/libusb/README +0 -29
  59. package/libusb/README.git +0 -41
  60. package/libusb/TODO +0 -2
  61. package/libusb/Xcode/common.xcconfig +0 -92
  62. package/libusb/Xcode/config.h +0 -31
  63. package/libusb/Xcode/debug.xcconfig +0 -32
  64. package/libusb/Xcode/libusb.xcconfig +0 -21
  65. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +0 -1391
  66. package/libusb/Xcode/libusb_debug.xcconfig +0 -21
  67. package/libusb/Xcode/libusb_release.xcconfig +0 -21
  68. package/libusb/Xcode/release.xcconfig +0 -30
  69. package/libusb/android/README +0 -152
  70. package/libusb/android/config.h +0 -55
  71. package/libusb/android/examples/unrooted_android.c +0 -301
  72. package/libusb/android/examples/unrooted_android.h +0 -36
  73. package/libusb/android/jni/Android.mk +0 -23
  74. package/libusb/android/jni/Application.mk +0 -40
  75. package/libusb/android/jni/examples.mk +0 -168
  76. package/libusb/android/jni/libusb.mk +0 -60
  77. package/libusb/android/jni/tests.mk +0 -45
  78. package/libusb/appveyor.yml +0 -108
  79. package/libusb/autogen.sh +0 -10
  80. package/libusb/bootstrap.sh +0 -10
  81. package/libusb/configure.ac +0 -450
  82. package/libusb/doc/Makefile.in +0 -22
  83. package/libusb/doc/doxygen.cfg.in +0 -2571
  84. package/libusb/doc/libusb.png +0 -0
  85. package/libusb/examples/Makefile.am +0 -12
  86. package/libusb/examples/dpfp.c +0 -711
  87. package/libusb/examples/ezusb.c +0 -846
  88. package/libusb/examples/ezusb.h +0 -109
  89. package/libusb/examples/fxload.c +0 -310
  90. package/libusb/examples/hotplugtest.c +0 -147
  91. package/libusb/examples/listdevs.c +0 -73
  92. package/libusb/examples/sam3u_benchmark.c +0 -228
  93. package/libusb/examples/testlibusb.c +0 -312
  94. package/libusb/examples/xusb.c +0 -1254
  95. package/libusb/libusb/Makefile.am +0 -98
  96. package/libusb/libusb/Makefile.am.extra +0 -26
  97. package/libusb/libusb/core.c +0 -2925
  98. package/libusb/libusb/descriptor.c +0 -1558
  99. package/libusb/libusb/hotplug.c +0 -489
  100. package/libusb/libusb/io.c +0 -2865
  101. package/libusb/libusb/libusb-1.0.def +0 -199
  102. package/libusb/libusb/libusb-1.0.rc +0 -53
  103. package/libusb/libusb/libusb.h +0 -2421
  104. package/libusb/libusb/libusbi.h +0 -1535
  105. package/libusb/libusb/os/darwin_usb.c +0 -2977
  106. package/libusb/libusb/os/darwin_usb.h +0 -156
  107. package/libusb/libusb/os/emscripten_webusb.cpp +0 -875
  108. package/libusb/libusb/os/events_posix.c +0 -340
  109. package/libusb/libusb/os/events_posix.h +0 -62
  110. package/libusb/libusb/os/events_windows.c +0 -214
  111. package/libusb/libusb/os/events_windows.h +0 -46
  112. package/libusb/libusb/os/haiku_pollfs.cpp +0 -372
  113. package/libusb/libusb/os/haiku_usb.h +0 -113
  114. package/libusb/libusb/os/haiku_usb_backend.cpp +0 -532
  115. package/libusb/libusb/os/haiku_usb_raw.cpp +0 -231
  116. package/libusb/libusb/os/haiku_usb_raw.h +0 -188
  117. package/libusb/libusb/os/linux_netlink.c +0 -401
  118. package/libusb/libusb/os/linux_udev.c +0 -321
  119. package/libusb/libusb/os/linux_usbfs.c +0 -2829
  120. package/libusb/libusb/os/linux_usbfs.h +0 -221
  121. package/libusb/libusb/os/netbsd_usb.c +0 -617
  122. package/libusb/libusb/os/null_usb.c +0 -111
  123. package/libusb/libusb/os/openbsd_usb.c +0 -700
  124. package/libusb/libusb/os/sunos_usb.c +0 -1619
  125. package/libusb/libusb/os/sunos_usb.h +0 -79
  126. package/libusb/libusb/os/threads_posix.c +0 -126
  127. package/libusb/libusb/os/threads_posix.h +0 -98
  128. package/libusb/libusb/os/threads_windows.c +0 -40
  129. package/libusb/libusb/os/threads_windows.h +0 -113
  130. package/libusb/libusb/os/windows_common.c +0 -923
  131. package/libusb/libusb/os/windows_common.h +0 -424
  132. package/libusb/libusb/os/windows_usbdk.c +0 -724
  133. package/libusb/libusb/os/windows_usbdk.h +0 -106
  134. package/libusb/libusb/os/windows_winusb.c +0 -4766
  135. package/libusb/libusb/os/windows_winusb.h +0 -787
  136. package/libusb/libusb/strerror.c +0 -223
  137. package/libusb/libusb/sync.c +0 -342
  138. package/libusb/libusb/version.h +0 -18
  139. package/libusb/libusb/version_nano.h +0 -1
  140. package/libusb/libusb-1.0.pc.in +0 -11
  141. package/libusb/msvc/Base.props +0 -60
  142. package/libusb/msvc/Configuration.Application.props +0 -7
  143. package/libusb/msvc/Configuration.Base.props +0 -47
  144. package/libusb/msvc/Configuration.DynamicLibrary.props +0 -21
  145. package/libusb/msvc/Configuration.StaticLibrary.props +0 -7
  146. package/libusb/msvc/ProjectConfigurations.Base.props +0 -69
  147. package/libusb/msvc/build_all.ps1 +0 -17
  148. package/libusb/msvc/config.h +0 -58
  149. package/libusb/msvc/dpfp.vcxproj +0 -33
  150. package/libusb/msvc/dpfp_threaded.vcxproj +0 -38
  151. package/libusb/msvc/fxload.vcxproj +0 -46
  152. package/libusb/msvc/getopt/getopt.c +0 -1060
  153. package/libusb/msvc/getopt/getopt.h +0 -180
  154. package/libusb/msvc/getopt/getopt1.c +0 -188
  155. package/libusb/msvc/getopt.vcxproj +0 -33
  156. package/libusb/msvc/hotplugtest.vcxproj +0 -32
  157. package/libusb/msvc/init_context.vcxproj +0 -35
  158. package/libusb/msvc/libusb.sln +0 -542
  159. package/libusb/msvc/libusb_dll.vcxproj +0 -61
  160. package/libusb/msvc/libusb_static.vcxproj +0 -49
  161. package/libusb/msvc/listdevs.vcxproj +0 -32
  162. package/libusb/msvc/sam3u_benchmark.vcxproj +0 -33
  163. package/libusb/msvc/set_option.vcxproj +0 -35
  164. package/libusb/msvc/stress.vcxproj +0 -35
  165. package/libusb/msvc/stress_mt.vcxproj +0 -33
  166. package/libusb/msvc/testlibusb.vcxproj +0 -32
  167. package/libusb/msvc/xusb.vcxproj +0 -38
  168. package/libusb/tests/Makefile.am +0 -40
  169. package/libusb/tests/init_context.c +0 -153
  170. package/libusb/tests/libusb_testlib.h +0 -76
  171. package/libusb/tests/macos.c +0 -130
  172. package/libusb/tests/set_option.c +0 -253
  173. package/libusb/tests/stress.c +0 -172
  174. package/libusb/tests/stress_mt.c +0 -267
  175. package/libusb/tests/testlib.c +0 -184
  176. package/libusb/tests/umockdev.c +0 -1175
  177. package/libusb/tests/webusb-test-shim/index.js +0 -12
  178. package/libusb/tests/webusb-test-shim/package-lock.json +0 -50
  179. package/libusb/tests/webusb-test-shim/package.json +0 -10
  180. package/libusb.gypi +0 -154
  181. package/libusb_config/config.h +0 -1
  182. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  183. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  184. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  185. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  186. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  187. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  188. package/prebuilds/linux-ia32/node.napi.node +0 -0
  189. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  190. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  191. package/prebuilds/win32-arm64/node.napi.node +0 -0
  192. package/prebuilds/win32-ia32/node.napi.node +0 -0
  193. package/prebuilds/win32-x64/node.napi.node +0 -0
  194. package/src/device.cc +0 -439
  195. package/src/helpers.h +0 -64
  196. package/src/hotplug/hotplug.h +0 -22
  197. package/src/hotplug/libusb.cc +0 -90
  198. package/src/hotplug/windows.cc +0 -168
  199. package/src/node_usb.cc +0 -314
  200. package/src/node_usb.h +0 -131
  201. package/src/thread_name.cc +0 -79
  202. package/src/thread_name.h +0 -11
  203. package/src/transfer.cc +0 -143
  204. package/src/uv_async_queue.h +0 -41
  205. package/test/usb.coffee +0 -250
  206. package/test/webusb.coffee +0 -227
  207. package/test/worker.cjs +0 -13
@@ -1,1175 +0,0 @@
1
- /*
2
- * libusb umockdev based tests
3
- *
4
- * Copyright (C) 2022 Benjamin Berg <bberg@redhat.com>
5
- *
6
- * This program 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 program 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 License
17
- * along with this program; If not, see <http://www.gnu.org/licenses/>.
18
- */
19
-
20
- #include "config.h"
21
- #include <glib.h>
22
- #include <glib/gstdio.h>
23
- #include <unistd.h>
24
- #include <string.h>
25
- #include <errno.h>
26
- #include <linux/ioctl.h>
27
- #include <linux/usbdevice_fs.h>
28
-
29
- #include "libusb.h"
30
-
31
- #include "umockdev.h"
32
-
33
- #define UNUSED_DATA __attribute__ ((unused)) gconstpointer unused_data
34
-
35
- /* avoid leak reports inside assertions; leaking stuff on assertion failures does not matter in tests */
36
- #if !defined(__clang__) && __GNUC__ > 9
37
- #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
38
- #pragma GCC diagnostic ignored "-Wanalyzer-file-leak"
39
- #endif
40
-
41
- typedef struct {
42
- pid_t thread;
43
- libusb_context *ctx;
44
- enum libusb_log_level level;
45
- char *str;
46
- } LogMessage;
47
-
48
- static void
49
- log_message_free(LogMessage *msg)
50
- {
51
- g_free(msg->str);
52
- g_free(msg);
53
- }
54
- G_DEFINE_AUTOPTR_CLEANUP_FUNC(LogMessage, log_message_free)
55
-
56
- typedef struct _UsbChat UsbChat;
57
-
58
- struct _UsbChat {
59
- gboolean submit;
60
- gboolean reap;
61
- UsbChat *reaps;
62
- UsbChat *next;
63
-
64
- /* struct usbdevfs_urb */
65
- unsigned char type;
66
- unsigned char endpoint;
67
- int status;
68
- unsigned int flags;
69
- const unsigned char *buffer;
70
- int buffer_length;
71
- int actual_length;
72
-
73
- /* <submit urb> */
74
- UMockdevIoctlData *submit_urb;
75
- };
76
-
77
- typedef struct {
78
- UMockdevTestbed *testbed;
79
- UMockdevIoctlBase *handler;
80
- struct libusb_context *ctx;
81
-
82
- gchar *root_dir;
83
- gchar *sys_dir;
84
-
85
- gboolean libusb_log_silence;
86
- GList *libusb_log;
87
-
88
- UsbChat *chat;
89
- GList *flying_urbs;
90
- GList *discarded_urbs;
91
-
92
- /* GMutex confuses TSan unnecessarily */
93
- pthread_mutex_t mutex;
94
- } UMockdevTestbedFixture;
95
-
96
- /* Global for log handler */
97
- static UMockdevTestbedFixture *cur_fixture = NULL;
98
-
99
- static void
100
- log_handler(libusb_context *ctx, enum libusb_log_level level, const char *str)
101
- {
102
- /* May be called from different threads without synchronization! */
103
- LogMessage *msg;
104
- pid_t tid = gettid();
105
-
106
- g_assert (cur_fixture != NULL);
107
- g_assert(pthread_mutex_lock(&cur_fixture->mutex) == 0);
108
-
109
- msg = g_new0(LogMessage, 1);
110
- msg->ctx = ctx;
111
- msg->level = level;
112
- msg->str = g_strchomp (g_strdup(str));
113
- msg->thread = tid;
114
-
115
- if (!cur_fixture->libusb_log_silence)
116
- g_printerr("%s\n", msg->str);
117
-
118
- cur_fixture->libusb_log = g_list_append(cur_fixture->libusb_log, msg);
119
- pthread_mutex_unlock(&cur_fixture->mutex);
120
- }
121
-
122
- static void
123
- log_handler_null(libusb_context *ctx, enum libusb_log_level level, const char *str)
124
- {
125
- (void) ctx;
126
- (void) level;
127
- (void) str;
128
- }
129
-
130
- static void
131
- clear_libusb_log(UMockdevTestbedFixture * fixture, enum libusb_log_level level)
132
- {
133
- g_assert(pthread_mutex_lock(&fixture->mutex) == 0);
134
-
135
- while (fixture->libusb_log) {
136
- LogMessage *msg = fixture->libusb_log->data;
137
-
138
- g_assert(msg->ctx == fixture->ctx);
139
-
140
- if (msg->level < level) {
141
- pthread_mutex_unlock(&fixture->mutex);
142
- return;
143
- }
144
-
145
- fixture->libusb_log = g_list_delete_link(fixture->libusb_log, fixture->libusb_log);
146
- log_message_free(msg);
147
- }
148
- pthread_mutex_unlock(&fixture->mutex);
149
- }
150
-
151
- static void
152
- assert_libusb_log_msg(UMockdevTestbedFixture * fixture, enum libusb_log_level level, const char *re)
153
- {
154
- g_assert(pthread_mutex_lock(&fixture->mutex) == 0);
155
-
156
- while (fixture->libusb_log) {
157
- g_autoptr(LogMessage) msg = NULL;
158
-
159
- if (fixture->libusb_log == NULL)
160
- g_error ("No level %d message found searching for %s", level, re);
161
-
162
- msg = fixture->libusb_log->data;
163
- fixture->libusb_log = g_list_delete_link(fixture->libusb_log, fixture->libusb_log);
164
-
165
- if (msg->ctx != fixture->ctx)
166
- g_error ("Saw unexpected message \"%s\" from context %p while %p was expected",
167
- msg->str, msg->ctx, fixture->ctx);
168
-
169
- if (msg->level == level && g_regex_match_simple(re, msg->str, 0, 0)) {
170
- pthread_mutex_unlock(&fixture->mutex);
171
- return;
172
- }
173
-
174
- /* Allow skipping INFO and DEBUG messages */
175
- if (msg->level >= LIBUSB_LOG_LEVEL_INFO)
176
- continue;
177
-
178
- g_error ("Searched for \"%s\" (%d) but found \"%s\" (%d)", re, level, msg->str, msg->level);
179
- }
180
-
181
- pthread_mutex_unlock(&fixture->mutex);
182
- g_error ("Searched for \"%s\" (%d) but no message matched", re, level);
183
- }
184
-
185
- static void
186
- assert_libusb_no_log_msg(UMockdevTestbedFixture * fixture, enum libusb_log_level level, const char *re)
187
- {
188
- g_assert(pthread_mutex_lock(&fixture->mutex) == 0);
189
-
190
- while (fixture->libusb_log) {
191
- g_autoptr(LogMessage) msg = NULL;
192
- gboolean matching;
193
-
194
- msg = fixture->libusb_log->data;
195
- fixture->libusb_log = g_list_delete_link(fixture->libusb_log, fixture->libusb_log);
196
-
197
- g_assert(msg->ctx == fixture->ctx);
198
-
199
- matching = (msg->level == level && g_regex_match_simple(re, msg->str, 0, 0));
200
-
201
- /* Allow skipping INFO and DEBUG messages */
202
- if (!matching && msg->level >= LIBUSB_LOG_LEVEL_INFO)
203
- continue;
204
-
205
- g_error ("Asserting \"%s\" (%d) not logged and found \"%s\" (%d)", re, level, msg->str, msg->level);
206
- }
207
-
208
- pthread_mutex_unlock(&fixture->mutex);
209
- }
210
-
211
- static void
212
- dump_buffer(const unsigned char *buffer, int len)
213
- {
214
- g_autoptr(GString) line = NULL;
215
-
216
- line = g_string_new ("");
217
- for (gint i = 0; i < len; i++) {
218
- g_string_append_printf(line, "%02x ", buffer[i]);
219
- if ((i + 1) % 16 == 0) {
220
- g_printerr(" %s\n", line->str);
221
- g_string_set_size(line, 0);
222
- }
223
- }
224
-
225
- if (line->len)
226
- g_printerr(" %s\n", line->str);
227
- }
228
-
229
- static gint
230
- cmp_ioctl_data_addr(const void *data, const void *addr)
231
- {
232
- return ((const UMockdevIoctlData*) data)->client_addr != (gulong) addr;
233
- }
234
-
235
- static gboolean
236
- handle_ioctl_cb (UMockdevIoctlBase *handler, UMockdevIoctlClient *client, UMockdevTestbedFixture *fixture)
237
- {
238
- UMockdevIoctlData *ioctl_arg;
239
- long int request;
240
- struct usbdevfs_urb *urb;
241
-
242
- (void) handler;
243
-
244
- request = umockdev_ioctl_client_get_request (client);
245
- ioctl_arg = umockdev_ioctl_client_get_arg (client);
246
-
247
- /* NOTE: We share the address space, dereferencing pointers *will* work.
248
- * However, to make TSan work, we still stick to the API that resolves
249
- * the data into a local copy! */
250
-
251
- switch (request) {
252
- case USBDEVFS_GET_CAPABILITIES: {
253
- g_autoptr(UMockdevIoctlData) d = NULL;
254
- d = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(guint32), NULL);
255
-
256
- *(guint32*) d->data = USBDEVFS_CAP_BULK_SCATTER_GATHER |
257
- USBDEVFS_CAP_BULK_CONTINUATION |
258
- USBDEVFS_CAP_NO_PACKET_SIZE_LIM |
259
- USBDEVFS_CAP_REAP_AFTER_DISCONNECT |
260
- USBDEVFS_CAP_ZERO_PACKET;
261
-
262
- umockdev_ioctl_client_complete(client, 0, 0);
263
- return TRUE;
264
- }
265
-
266
- case USBDEVFS_CLAIMINTERFACE:
267
- case USBDEVFS_RELEASEINTERFACE:
268
- case USBDEVFS_CLEAR_HALT:
269
- case USBDEVFS_RESET:
270
- case USBDEVFS_RESETEP:
271
- umockdev_ioctl_client_complete(client, 0, 0);
272
- return TRUE;
273
-
274
- case USBDEVFS_SUBMITURB: {
275
- g_autoptr(UMockdevIoctlData) urb_buffer = NULL;
276
- g_autoptr(UMockdevIoctlData) urb_data = NULL;
277
- gsize buflen;
278
-
279
- if (!fixture->chat || !fixture->chat->submit)
280
- return FALSE;
281
-
282
- buflen = fixture->chat->buffer_length;
283
- if (fixture->chat->type == USBDEVFS_URB_TYPE_CONTROL)
284
- buflen = 8;
285
-
286
- urb_data = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(struct usbdevfs_urb), NULL);
287
- urb = (struct usbdevfs_urb*) urb_data->data;
288
- urb_buffer = umockdev_ioctl_data_resolve(urb_data, G_STRUCT_OFFSET(struct usbdevfs_urb, buffer), urb->buffer_length, NULL);
289
-
290
- if (fixture->chat->type == urb->type &&
291
- fixture->chat->endpoint == urb->endpoint &&
292
- fixture->chat->buffer_length == urb->buffer_length &&
293
- (fixture->chat->buffer == NULL || memcmp (fixture->chat->buffer, urb_buffer->data, buflen) == 0)) {
294
- fixture->flying_urbs = g_list_append (fixture->flying_urbs, umockdev_ioctl_data_ref(urb_data));
295
-
296
- if (fixture->chat->reaps)
297
- fixture->chat->reaps->submit_urb = urb_data;
298
-
299
- if (fixture->chat->status)
300
- umockdev_ioctl_client_complete(client, -1, -fixture->chat->status);
301
- else
302
- umockdev_ioctl_client_complete(client, 0, 0);
303
-
304
- if (fixture->chat->next)
305
- fixture->chat = fixture->chat->next;
306
- else
307
- fixture->chat += 1;
308
- return TRUE;
309
- }
310
-
311
- /* chat message didn't match, don't accept it */
312
- g_printerr("Could not process submit urb:\n");
313
- g_printerr(" t: %d, ep: %d, actual_length: %d, buffer_length: %d\n",
314
- urb->type, urb->endpoint, urb->actual_length, urb->buffer_length);
315
- if (urb->type == USBDEVFS_URB_TYPE_CONTROL || urb->endpoint & LIBUSB_ENDPOINT_IN)
316
- dump_buffer(urb->buffer, urb->buffer_length);
317
- g_printerr("Looking for:\n");
318
- g_printerr(" t: %d, ep: %d, actual_length: %d, buffer_length: %d\n",
319
- fixture->chat->type, fixture->chat->endpoint,
320
- fixture->chat->actual_length, fixture->chat->buffer_length);
321
- if (fixture->chat->buffer)
322
- dump_buffer(fixture->chat->buffer, buflen);
323
-
324
- return FALSE;
325
- }
326
-
327
- case USBDEVFS_REAPURB:
328
- case USBDEVFS_REAPURBNDELAY: {
329
- g_autoptr(UMockdevIoctlData) urb_ptr = NULL;
330
- g_autoptr(UMockdevIoctlData) urb_data = NULL;
331
-
332
- if (fixture->discarded_urbs) {
333
- urb_data = fixture->discarded_urbs->data;
334
- urb = (struct usbdevfs_urb*) urb_data->data;
335
- fixture->discarded_urbs = g_list_delete_link(fixture->discarded_urbs, fixture->discarded_urbs);
336
- urb->status = -ENOENT;
337
-
338
- urb_ptr = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(gpointer), NULL);
339
- umockdev_ioctl_data_set_ptr(urb_ptr, 0, urb_data);
340
-
341
- umockdev_ioctl_client_complete(client, 0, 0);
342
- return TRUE;
343
- }
344
-
345
- if (fixture->chat && fixture->chat->reap) {
346
- GList *l = g_list_find(fixture->flying_urbs, fixture->chat->submit_urb);
347
-
348
- if (l) {
349
- fixture->flying_urbs = g_list_remove_link(fixture->flying_urbs, fixture->flying_urbs);
350
-
351
- urb_data = fixture->chat->submit_urb;
352
- urb = (struct usbdevfs_urb*) urb_data->data;
353
- urb->actual_length = fixture->chat->actual_length;
354
- if (urb->type == USBDEVFS_URB_TYPE_CONTROL && urb->actual_length)
355
- urb->actual_length -= 8;
356
- if (fixture->chat->buffer)
357
- memcpy(urb->buffer, fixture->chat->buffer, fixture->chat->actual_length);
358
- urb->status = fixture->chat->status;
359
-
360
- urb_ptr = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(gpointer), NULL);
361
- umockdev_ioctl_data_set_ptr(urb_ptr, 0, urb_data);
362
- if (fixture->chat->next)
363
- fixture->chat = fixture->chat->next;
364
- else
365
- fixture->chat += 1;
366
- umockdev_ioctl_client_complete(client, 0, 0);
367
- return TRUE;
368
- }
369
- }
370
-
371
- /* Nothing to reap */
372
- umockdev_ioctl_client_complete(client, -1, EAGAIN);
373
- return TRUE;
374
- }
375
-
376
- case USBDEVFS_DISCARDURB: {
377
- GList *l = g_list_find_custom(fixture->flying_urbs, *(void**) ioctl_arg->data, cmp_ioctl_data_addr);
378
-
379
- if (l) {
380
- fixture->discarded_urbs = g_list_append(fixture->discarded_urbs, l->data);
381
- fixture->flying_urbs = g_list_delete_link(fixture->flying_urbs, l);
382
- umockdev_ioctl_client_complete(client, 0, 0);
383
- } else {
384
- umockdev_ioctl_client_complete(client, -1, EINVAL);
385
- }
386
-
387
- return TRUE;
388
- }
389
-
390
- default:
391
- return FALSE;
392
- }
393
- }
394
-
395
- static void
396
- test_fixture_add_canon(UMockdevTestbedFixture * fixture)
397
- {
398
- /* Setup first, so we can be sure libusb_open works when the add uevent
399
- * happens.
400
- */
401
- g_assert_cmpint(umockdev_testbed_attach_ioctl(fixture->testbed, "/dev/bus/usb/001/001", fixture->handler, NULL), ==, 1);
402
-
403
- /* NOTE: add_device would not create a file, needed for device emulation */
404
- /* XXX: Racy, see https://github.com/martinpitt/umockdev/issues/173 */
405
- umockdev_testbed_add_from_string(fixture->testbed,
406
- "P: /devices/usb1\n"
407
- "N: bus/usb/001/001\n"
408
- "E: SUBSYSTEM=usb\n"
409
- "E: DRIVER=usb\n"
410
- "E: BUSNUM=001\n"
411
- "E: DEVNUM=001\n"
412
- "E: DEVNAME=/dev/bus/usb/001/001\n"
413
- "E: DEVTYPE=usb_device\n"
414
- "A: bConfigurationValue=1\\n\n"
415
- "A: busnum=1\\n\n"
416
- "A: devnum=1\\n\n"
417
- "A: bConfigurationValue=1\\n\n"
418
- "A: speed=480\\n\n"
419
- /* descriptor from a Canon PowerShot SX200; VID 04a9 PID 31c0 */
420
- "H: descriptors="
421
- "1201000200000040a904c03102000102"
422
- "030109022700010100c0010904000003"
423
- "06010100070581020002000705020200"
424
- "020007058303080009\n",
425
- NULL);
426
- }
427
-
428
- static void
429
- test_fixture_setup_libusb(UMockdevTestbedFixture * fixture, int devcount)
430
- {
431
- libusb_device **devs = NULL;
432
-
433
- libusb_init_context(/*ctx=*/&fixture->ctx, /*options=*/NULL, /*num_options=*/0);
434
-
435
- /* Suppress global log messages completely
436
- * (though, in some tests it might be interesting to check there are no real ones).
437
- */
438
- libusb_set_log_cb (NULL, log_handler_null, LIBUSB_LOG_CB_GLOBAL);
439
- libusb_set_option (fixture->ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
440
- g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, devcount);
441
- libusb_free_device_list(devs, TRUE);
442
- libusb_set_log_cb (fixture->ctx, log_handler, LIBUSB_LOG_CB_CONTEXT);
443
- }
444
-
445
- static void
446
- test_fixture_setup_common(UMockdevTestbedFixture * fixture)
447
- {
448
- g_assert(cur_fixture == NULL);
449
- cur_fixture = fixture;
450
-
451
- pthread_mutex_init(&fixture->mutex, NULL);
452
-
453
- fixture->testbed = umockdev_testbed_new();
454
- g_assert(fixture->testbed != NULL);
455
- fixture->root_dir = umockdev_testbed_get_root_dir(fixture->testbed);
456
- fixture->sys_dir = umockdev_testbed_get_sys_dir(fixture->testbed);
457
-
458
- fixture->handler = umockdev_ioctl_base_new();
459
- g_object_connect(fixture->handler, "signal-after::handle-ioctl", handle_ioctl_cb, fixture, NULL);
460
- }
461
-
462
- static void
463
- test_fixture_setup_empty(UMockdevTestbedFixture * fixture, UNUSED_DATA)
464
- {
465
- test_fixture_setup_common(fixture);
466
-
467
- test_fixture_setup_libusb(fixture, 0);
468
- }
469
-
470
- static void
471
- test_fixture_setup_with_canon(UMockdevTestbedFixture * fixture, UNUSED_DATA)
472
- {
473
- test_fixture_setup_common(fixture);
474
-
475
- test_fixture_add_canon(fixture);
476
-
477
- test_fixture_setup_libusb(fixture, 1);
478
- }
479
-
480
- static void
481
- test_fixture_teardown(UMockdevTestbedFixture * fixture, UNUSED_DATA)
482
- {
483
- g_assert(cur_fixture == fixture);
484
-
485
- /* Abort if there are any warnings/errors in the log */
486
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
487
-
488
- if (fixture->ctx) {
489
- libusb_device **devs = NULL;
490
- int count = libusb_get_device_list(fixture->ctx, &devs);
491
- libusb_free_device_list(devs, TRUE);
492
-
493
- libusb_exit (fixture->ctx);
494
-
495
- /* libusb_exit should result in the correct number of devices being destroyed */
496
- for (int i = 0; i < count; i++)
497
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_unref_device");
498
-
499
- assert_libusb_no_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_unref_device");
500
- }
501
- libusb_set_log_cb (NULL, NULL, LIBUSB_LOG_CB_GLOBAL);
502
- cur_fixture = NULL;
503
-
504
- /* Abort if there are any warnings/errors in the log */
505
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
506
- fixture->ctx = NULL;
507
- g_assert_null(fixture->libusb_log);
508
-
509
- g_clear_object(&fixture->handler);
510
- g_clear_object(&fixture->testbed);
511
-
512
- /* verify that temp dir gets cleaned up properly */
513
- g_assert(!g_file_test(fixture->root_dir, G_FILE_TEST_EXISTS));
514
- g_free(fixture->root_dir);
515
- g_free(fixture->sys_dir);
516
-
517
- while (fixture->flying_urbs) {
518
- umockdev_ioctl_data_unref (fixture->flying_urbs->data);
519
- fixture->flying_urbs = g_list_delete_link (fixture->flying_urbs, fixture->flying_urbs);
520
- }
521
-
522
- pthread_mutex_destroy(&fixture->mutex);
523
- }
524
-
525
- static void
526
- test_open_close(UMockdevTestbedFixture * fixture, UNUSED_DATA)
527
- {
528
- libusb_device **devs = NULL;
529
- struct libusb_device_descriptor desc;
530
- libusb_device_handle *handle = NULL;
531
-
532
- g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 1);
533
- /* The linux_enumerate_device may happen from a different thread */
534
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_get_device_list");
535
- /* We have exactly one device */
536
- g_assert_cmpint(libusb_get_bus_number(devs[0]), ==, 1);
537
- g_assert_cmpint(libusb_get_device_address(devs[0]), ==, 1);
538
-
539
- /* Get/Check descriptor */
540
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
541
- libusb_get_device_descriptor (devs[0], &desc);
542
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_get_device_descriptor");
543
- g_assert_cmpint(desc.idVendor, ==, 0x04a9);
544
- g_assert_cmpint(desc.idProduct, ==, 0x31c0);
545
-
546
- /* Open and close */
547
- g_assert_cmpint(libusb_open(devs[0], &handle), ==, 0);
548
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "usbi_add_event_source");
549
- g_assert_nonnull(handle);
550
- libusb_close(handle);
551
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "usbi_remove_event_source");
552
-
553
- libusb_free_device_list(devs, TRUE);
554
-
555
- /* Open and close using vid/pid */
556
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
557
- g_assert_nonnull(handle);
558
- libusb_close(handle);
559
- }
560
-
561
- static void
562
- test_implicit_default(UMockdevTestbedFixture * fixture, UNUSED_DATA)
563
- {
564
- libusb_device **devs = NULL;
565
-
566
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
567
- g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
568
- libusb_free_device_list(devs, TRUE);
569
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[usbi_get_context\\].*implicit default");
570
-
571
- /* Only warns once */
572
- g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
573
- libusb_free_device_list(devs, TRUE);
574
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
575
-
576
- libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0);
577
- g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
578
- libusb_exit(NULL);
579
-
580
- /* We free late, causing a warning from libusb_exit. However,
581
- * we never see this warning (i.e. test success) because it is on a
582
- * different context.
583
- */
584
- libusb_free_device_list(devs, TRUE);
585
- }
586
-
587
- static void
588
- test_close_flying(UMockdevTestbedFixture * fixture, UNUSED_DATA)
589
- {
590
- UsbChat chat[] = {
591
- {
592
- .submit = TRUE,
593
- .type = USBDEVFS_URB_TYPE_BULK,
594
- .endpoint = LIBUSB_ENDPOINT_OUT,
595
- .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
596
- .buffer_length = 4,
597
- },
598
- { .submit = FALSE }
599
- };
600
- libusb_device_handle *handle = NULL;
601
- struct libusb_transfer *transfer = NULL;
602
-
603
- fixture->chat = chat;
604
-
605
- /* Open */
606
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
607
- g_assert_nonnull(handle);
608
-
609
- transfer = libusb_alloc_transfer(0);
610
- libusb_fill_bulk_transfer(transfer,
611
- handle,
612
- LIBUSB_ENDPOINT_OUT,
613
- (unsigned char*) chat[0].buffer,
614
- chat[0].buffer_length,
615
- NULL,
616
- NULL,
617
- 1);
618
-
619
- /* Submit */
620
- libusb_submit_transfer(transfer);
621
-
622
- /* Closing logs fat error (two lines) */
623
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
624
- libusb_close(handle);
625
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[do_close\\] .*connected as far as we know");
626
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[do_close\\] .*cancellation hasn't even been scheduled");
627
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "\\[do_close\\] Removed transfer");
628
-
629
- /* Free'ing the transfer works, and logs to the right context */
630
- libusb_free_transfer(transfer);
631
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "\\[libusb_free_transfer\\]");
632
- }
633
-
634
- static void
635
- test_close_cancelled(UMockdevTestbedFixture * fixture, UNUSED_DATA)
636
- {
637
- UsbChat chat[] = {
638
- {
639
- .submit = TRUE,
640
- .type = USBDEVFS_URB_TYPE_BULK,
641
- .endpoint = LIBUSB_ENDPOINT_OUT,
642
- .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
643
- .buffer_length = 4,
644
- },
645
- { .submit = FALSE }
646
- };
647
- libusb_device_handle *handle = NULL;
648
- struct libusb_transfer *transfer = NULL;
649
-
650
- fixture->chat = chat;
651
-
652
- /* Open */
653
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
654
- g_assert_nonnull(handle);
655
-
656
- transfer = libusb_alloc_transfer(0);
657
- libusb_fill_bulk_transfer(transfer,
658
- handle,
659
- LIBUSB_ENDPOINT_OUT,
660
- (unsigned char*) chat[0].buffer,
661
- chat[0].buffer_length,
662
- NULL,
663
- NULL,
664
- 1);
665
-
666
- /* Submit */
667
- libusb_submit_transfer(transfer);
668
- libusb_cancel_transfer(transfer);
669
-
670
- /* Closing logs fat error (two lines) */
671
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
672
- libusb_close(handle);
673
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[do_close\\] .*connected as far as we know");
674
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_WARNING, "\\[do_close\\] .*cancellation.*hasn't completed");
675
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "\\[do_close\\] Removed transfer");
676
-
677
- libusb_free_transfer(transfer);
678
- }
679
-
680
- static void
681
- test_ctx_destroy(UMockdevTestbedFixture * fixture, UNUSED_DATA)
682
- {
683
- UsbChat chat[] = {
684
- {
685
- .submit = TRUE,
686
- .type = USBDEVFS_URB_TYPE_BULK,
687
- .endpoint = LIBUSB_ENDPOINT_OUT,
688
- .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
689
- .buffer_length = 4,
690
- },
691
- { .submit = FALSE }
692
- };
693
- libusb_device_handle *handle = NULL;
694
- struct libusb_transfer *transfer = NULL;
695
-
696
- fixture->chat = chat;
697
-
698
- /* Open */
699
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
700
- g_assert_nonnull(handle);
701
-
702
- transfer = libusb_alloc_transfer(0);
703
- libusb_fill_bulk_transfer(transfer,
704
- handle,
705
- LIBUSB_ENDPOINT_OUT,
706
- (unsigned char*) chat[0].buffer,
707
- chat[0].buffer_length,
708
- NULL,
709
- NULL,
710
- 1);
711
-
712
- /* Submit */
713
- libusb_submit_transfer(transfer);
714
-
715
- /* Now we are evil and destroy the ctx! */
716
- libusb_exit(fixture->ctx);
717
-
718
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_WARNING, "\\[libusb_exit\\] device.*still referenced");
719
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_WARNING, "\\[libusb_exit\\] application left some devices open");
720
-
721
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
722
- fixture->ctx = NULL;
723
-
724
- /* XXX: Closing crashes the application as it unref's the NULL pointer */
725
- /* libusb_close(handle); */
726
-
727
- libusb_free_transfer(transfer);
728
- }
729
-
730
- static void
731
- test_get_string_descriptor(UMockdevTestbedFixture * fixture, UNUSED_DATA)
732
- {
733
- unsigned char data[255] = { 0, };
734
- libusb_device_handle *handle = NULL;
735
- UsbChat chat[] = {
736
- {
737
- .submit = TRUE,
738
- .reaps = &chat[1],
739
- .type = USBDEVFS_URB_TYPE_CONTROL,
740
- .buffer_length = 12, /* 8 byte out*/
741
- .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00",
742
- }, {
743
- /* String with content 0x0409 (en_US) */
744
- .reap = TRUE,
745
- .actual_length = 12,
746
- .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00\x04\x03\x09\x04",
747
- }, {
748
- .submit = TRUE,
749
- .reaps = &chat[3],
750
- .type = USBDEVFS_URB_TYPE_CONTROL,
751
- .buffer_length = 263, /* 8 byte out*/
752
- .buffer = (const unsigned char*) "\x80\x06\x01\x03\x09\x04\xff\x00",
753
- }, {
754
- /* 4 byte string, "ab" */
755
- .reap = TRUE,
756
- .actual_length = 14,
757
- .buffer = (const unsigned char*) "\x80\x06\x01\x03\x09\x04\xff\x00\x06\x03\x61\x00\x62\x00",
758
- }, {
759
- .submit = TRUE,
760
- .reaps = &chat[5],
761
- .type = USBDEVFS_URB_TYPE_CONTROL,
762
- .buffer_length = 12, /* 8 byte out*/
763
- .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00",
764
- }, {
765
- .reap = TRUE,
766
- .status = -ENOENT,
767
- }, {
768
- .submit = TRUE,
769
- .status = -ENOENT,
770
- .type = USBDEVFS_URB_TYPE_CONTROL,
771
- .buffer_length = 12, /* 8 byte out*/
772
- .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00",
773
- }, {
774
- .submit = FALSE,
775
- }
776
- };
777
-
778
- fixture->chat = chat;
779
-
780
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
781
- g_assert_nonnull(handle);
782
-
783
- /* The chat allows us to fetch the descriptor */
784
- g_assert_cmpint(libusb_get_string_descriptor_ascii(handle, 1, data, sizeof(data)), ==, 2);
785
- g_assert_cmpint(memcmp(data, "ab", 2), ==, 0);
786
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
787
-
788
- /* Again, but the URB fails with ENOENT when reaping */
789
- g_assert_cmpint(libusb_get_string_descriptor_ascii(handle, 1, data, sizeof(data)), ==, -1);
790
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
791
-
792
- /* Again, but the URB fails to submit with ENOENT */
793
- g_assert_cmpint(libusb_get_string_descriptor_ascii(handle, 1, data, sizeof(data)), ==, -1);
794
- assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[submit_control_transfer\\] submiturb failed, errno=2");
795
- clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
796
-
797
- libusb_close(handle);
798
- }
799
-
800
- static void
801
- transfer_cb_inc_user_data(struct libusb_transfer *transfer)
802
- {
803
- *(int*)transfer->user_data += 1;
804
- }
805
-
806
- static void
807
- test_timeout(UMockdevTestbedFixture * fixture, UNUSED_DATA)
808
- {
809
- UsbChat chat[] = {
810
- {
811
- .submit = TRUE,
812
- .type = USBDEVFS_URB_TYPE_BULK,
813
- .endpoint = LIBUSB_ENDPOINT_OUT,
814
- .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
815
- .buffer_length = 4,
816
- },
817
- {
818
- .submit = FALSE,
819
- }
820
- };
821
- int completed = 0;
822
- libusb_device_handle *handle = NULL;
823
- struct libusb_transfer *transfer = NULL;
824
-
825
- fixture->chat = chat;
826
-
827
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
828
- g_assert_nonnull(handle);
829
-
830
- transfer = libusb_alloc_transfer(0);
831
- libusb_fill_bulk_transfer(transfer,
832
- handle,
833
- LIBUSB_ENDPOINT_OUT,
834
- (unsigned char*) chat[0].buffer,
835
- chat[0].buffer_length,
836
- transfer_cb_inc_user_data,
837
- &completed,
838
- 10);
839
-
840
- libusb_submit_transfer(transfer);
841
- while (!completed) {
842
- g_assert_cmpint(libusb_handle_events_completed(fixture->ctx, &completed), ==, 0);
843
- /* Silence after one iteration. */
844
- fixture->libusb_log_silence = TRUE;
845
- }
846
- fixture->libusb_log_silence = FALSE;
847
-
848
- g_assert_cmpint(transfer->status, ==, LIBUSB_TRANSFER_TIMED_OUT);
849
- libusb_free_transfer(transfer);
850
-
851
- libusb_close(handle);
852
- }
853
-
854
- #define THREADED_SUBMIT_URB_SETS 64
855
- #define THREADED_SUBMIT_URB_IN_FLIGHT 64
856
- typedef struct {
857
- struct libusb_transfer *transfers[THREADED_SUBMIT_URB_IN_FLIGHT * THREADED_SUBMIT_URB_SETS];
858
- int submitted;
859
- int completed;
860
- int done;
861
- UMockdevTestbedFixture *fixture;
862
- } TestThreadedSubmit;
863
-
864
- static gpointer
865
- transfer_submit_all_retry(TestThreadedSubmit *data)
866
- {
867
- for (guint i = 0; i < G_N_ELEMENTS(data->transfers); i++) {
868
- while (libusb_submit_transfer(data->transfers[i]) < 0) {
869
- assert_libusb_log_msg(data->fixture, LIBUSB_LOG_LEVEL_ERROR, "submit_bulk_transfer");
870
- continue;
871
- }
872
-
873
- data->submitted += 1;
874
- }
875
-
876
- return NULL;
877
- }
878
-
879
- static void LIBUSB_CALL
880
- test_threaded_submit_transfer_cb(struct libusb_transfer *transfer)
881
- {
882
- TestThreadedSubmit *data = transfer->user_data;
883
-
884
- /* We should only be receiving packets in the main thread */
885
- g_assert_cmpint (getpid(), ==, gettid());
886
-
887
- /* Check that the transfer buffer has the expected value */
888
- g_assert_cmpint (*(int*)transfer->buffer, ==, data->completed);
889
- data->completed += 1;
890
-
891
- if (data->completed == G_N_ELEMENTS(data->transfers))
892
- data->done = TRUE;
893
- }
894
-
895
- static void
896
- test_threaded_submit(UMockdevTestbedFixture * fixture, UNUSED_DATA)
897
- {
898
- GThread *thread = NULL;
899
- TestThreadedSubmit data = { .fixture = fixture };
900
- UsbChat out_msg = {
901
- .submit = TRUE,
902
- .type = USBDEVFS_URB_TYPE_BULK,
903
- .endpoint = LIBUSB_ENDPOINT_IN,
904
- .buffer_length = sizeof(int),
905
- };
906
- UsbChat in_msg = {
907
- .reap = TRUE,
908
- .actual_length = 4,
909
- };
910
- UsbChat *c;
911
- libusb_device_handle *handle = NULL;
912
- int urb;
913
-
914
- handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
915
- g_assert_nonnull(handle);
916
-
917
- fixture->libusb_log_silence = TRUE;
918
-
919
- c = fixture->chat = g_new0(UsbChat, G_N_ELEMENTS(data.transfers) * 2 + 1);
920
- urb = 0;
921
- for (int i = 0; i < THREADED_SUBMIT_URB_SETS; i++) {
922
- for (int j = 0; j < THREADED_SUBMIT_URB_IN_FLIGHT; j++) {
923
- c[i*2*THREADED_SUBMIT_URB_IN_FLIGHT + j] = out_msg;
924
- c[i*2*THREADED_SUBMIT_URB_IN_FLIGHT + j].reaps = &c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j];
925
- c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j] = in_msg;
926
- c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j].buffer = (unsigned char*) g_new0(int, 1);
927
- *(int*) c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j].buffer = urb;
928
-
929
- data.transfers[urb] = libusb_alloc_transfer(0);
930
- libusb_fill_bulk_transfer(data.transfers[urb],
931
- handle,
932
- LIBUSB_ENDPOINT_IN,
933
- g_malloc(out_msg.buffer_length),
934
- out_msg.buffer_length,
935
- test_threaded_submit_transfer_cb,
936
- &data,
937
- G_MAXUINT);
938
- data.transfers[urb]->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
939
- urb++;
940
- }
941
- }
942
-
943
- thread = g_thread_new("transfer all", (GThreadFunc) transfer_submit_all_retry, &data);
944
-
945
- while (!data.done)
946
- g_assert_cmpint(libusb_handle_events_completed(fixture->ctx, &data.done), ==, 0);
947
-
948
- g_thread_join(thread);
949
-
950
- fixture->libusb_log_silence = FALSE;
951
- libusb_close(handle);
952
-
953
- for (int i = 0; i < 2 * THREADED_SUBMIT_URB_SETS * THREADED_SUBMIT_URB_SETS; i++)
954
- g_clear_pointer ((void**) &c->buffer, g_free);
955
- g_free (c);
956
- }
957
-
958
- static int LIBUSB_CALL
959
- hotplug_count_arrival_cb(libusb_context *ctx,
960
- libusb_device *device,
961
- libusb_hotplug_event event,
962
- void *user_data)
963
- {
964
- g_assert_cmpint(event, ==, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
965
-
966
- (void) ctx;
967
- (void) device;
968
-
969
- *(int*) user_data += 1;
970
-
971
- return 0;
972
- }
973
-
974
- #ifdef UMOCKDEV_HOTPLUG
975
- static int LIBUSB_CALL
976
- hotplug_count_removal_cb(libusb_context *ctx,
977
- libusb_device *device,
978
- libusb_hotplug_event event,
979
- void *user_data)
980
- {
981
- g_assert_cmpint(event, ==, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
982
-
983
- (void) ctx;
984
- (void) device;
985
-
986
- *(int*) user_data += 1;
987
-
988
- return 0;
989
- }
990
- #endif
991
-
992
- static void
993
- test_hotplug_enumerate(UMockdevTestbedFixture * fixture, UNUSED_DATA)
994
- {
995
- libusb_hotplug_callback_handle handle_enumerate;
996
- libusb_hotplug_callback_handle handle_no_enumerate;
997
- int event_count_enumerate = 0;
998
- int event_count_no_enumerate = 0;
999
- struct timeval zero_tv = { 0 };
1000
- int r;
1001
-
1002
- r = libusb_hotplug_register_callback(fixture->ctx,
1003
- LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
1004
- LIBUSB_HOTPLUG_ENUMERATE,
1005
- LIBUSB_HOTPLUG_MATCH_ANY,
1006
- LIBUSB_HOTPLUG_MATCH_ANY,
1007
- LIBUSB_HOTPLUG_MATCH_ANY,
1008
- hotplug_count_arrival_cb,
1009
- &event_count_enumerate,
1010
- &handle_enumerate);
1011
- g_assert_cmpint(r, ==, 0);
1012
-
1013
- r = libusb_hotplug_register_callback(fixture->ctx,
1014
- LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
1015
- 0,
1016
- LIBUSB_HOTPLUG_MATCH_ANY,
1017
- LIBUSB_HOTPLUG_MATCH_ANY,
1018
- LIBUSB_HOTPLUG_MATCH_ANY,
1019
- hotplug_count_arrival_cb,
1020
- &event_count_no_enumerate,
1021
- &handle_no_enumerate);
1022
- g_assert_cmpint(r, ==, 0);
1023
-
1024
- g_assert_cmpint(event_count_enumerate, ==, 1);
1025
- g_assert_cmpint(event_count_no_enumerate, ==, 0);
1026
-
1027
- libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1028
-
1029
- g_assert_cmpint(event_count_enumerate, ==, 1);
1030
- g_assert_cmpint(event_count_no_enumerate, ==, 0);
1031
-
1032
- libusb_hotplug_deregister_callback(fixture->ctx, handle_enumerate);
1033
- libusb_hotplug_deregister_callback(fixture->ctx, handle_no_enumerate);
1034
-
1035
- libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1036
-
1037
- g_assert_cmpint(event_count_enumerate, ==, 1);
1038
- g_assert_cmpint(event_count_no_enumerate, ==, 0);
1039
- }
1040
-
1041
- static void
1042
- test_hotplug_add_remove(UMockdevTestbedFixture * fixture, UNUSED_DATA)
1043
- {
1044
- #ifdef UMOCKDEV_HOTPLUG
1045
- libusb_device **devs = NULL;
1046
- libusb_hotplug_callback_handle handle_add;
1047
- libusb_hotplug_callback_handle handle_remove;
1048
- int event_count_add = 0;
1049
- int event_count_remove = 0;
1050
- struct timeval zero_tv = { 0 };
1051
- int r;
1052
-
1053
- r = libusb_hotplug_register_callback(fixture->ctx,
1054
- LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
1055
- LIBUSB_HOTPLUG_ENUMERATE,
1056
- LIBUSB_HOTPLUG_MATCH_ANY,
1057
- LIBUSB_HOTPLUG_MATCH_ANY,
1058
- LIBUSB_HOTPLUG_MATCH_ANY,
1059
- hotplug_count_arrival_cb,
1060
- &event_count_add,
1061
- &handle_add);
1062
- g_assert_cmpint(r, ==, 0);
1063
-
1064
- r = libusb_hotplug_register_callback(fixture->ctx,
1065
- LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
1066
- LIBUSB_HOTPLUG_ENUMERATE,
1067
- LIBUSB_HOTPLUG_MATCH_ANY,
1068
- LIBUSB_HOTPLUG_MATCH_ANY,
1069
- LIBUSB_HOTPLUG_MATCH_ANY,
1070
- hotplug_count_removal_cb,
1071
- &event_count_remove,
1072
- &handle_remove);
1073
- g_assert_cmpint(r, ==, 0);
1074
-
1075
- /* No device, even going into the mainloop will not call cb. */
1076
- libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1077
- g_assert_cmpint(event_count_add, ==, 0);
1078
- g_assert_cmpint(event_count_remove, ==, 0);
1079
-
1080
- /* Add a device */
1081
- test_fixture_add_canon(fixture);
1082
-
1083
- /* Either the thread has picked it up already, or we do so now. */
1084
- g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 1);
1085
- libusb_free_device_list(devs, TRUE);
1086
-
1087
- /* The hotplug event is pending now, but has not yet fired. */
1088
- g_assert_cmpint(event_count_add, ==, 0);
1089
- g_assert_cmpint(event_count_remove, ==, 0);
1090
-
1091
- /* Fire hotplug event. */
1092
- libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1093
- g_assert_cmpint(event_count_add, ==, 1);
1094
- g_assert_cmpint(event_count_remove, ==, 0);
1095
-
1096
- umockdev_testbed_uevent(fixture->testbed, "/sys/devices/usb1", "remove");
1097
- //umockdev_testbed_remove_device(fixture->testbed, "/devices/usb1");
1098
-
1099
- /* Either the thread has picked it up already, or we do so now. */
1100
- g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 0);
1101
- libusb_free_device_list(devs, TRUE);
1102
-
1103
- /* The hotplug event is pending now, but has not yet fired. */
1104
- g_assert_cmpint(event_count_add, ==, 1);
1105
- g_assert_cmpint(event_count_remove, ==, 0);
1106
-
1107
- /* Fire hotplug event. */
1108
- libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1109
- g_assert_cmpint(event_count_add, ==, 1);
1110
- g_assert_cmpint(event_count_remove, ==, 1);
1111
-
1112
- libusb_hotplug_deregister_callback(fixture->ctx, handle_add);
1113
- libusb_hotplug_deregister_callback(fixture->ctx, handle_remove);
1114
- #else
1115
- (void) fixture;
1116
- g_test_skip("UMockdev is too old to test hotplug");
1117
- #endif
1118
- }
1119
-
1120
- int
1121
- main(int argc, char **argv)
1122
- {
1123
- g_test_init(&argc, &argv, NULL);
1124
-
1125
- g_test_add("/libusb/open-close", UMockdevTestbedFixture, NULL,
1126
- test_fixture_setup_with_canon,
1127
- test_open_close,
1128
- test_fixture_teardown);
1129
-
1130
- g_test_add("/libusb/implicit-default", UMockdevTestbedFixture, NULL,
1131
- test_fixture_setup_with_canon,
1132
- test_implicit_default,
1133
- test_fixture_teardown);
1134
-
1135
- g_test_add("/libusb/close-flying", UMockdevTestbedFixture, NULL,
1136
- test_fixture_setup_with_canon,
1137
- test_close_flying,
1138
- test_fixture_teardown);
1139
- g_test_add("/libusb/close-cancelled", UMockdevTestbedFixture, NULL,
1140
- test_fixture_setup_with_canon,
1141
- test_close_cancelled,
1142
- test_fixture_teardown);
1143
-
1144
- g_test_add("/libusb/ctx-destroy", UMockdevTestbedFixture, NULL,
1145
- test_fixture_setup_with_canon,
1146
- test_ctx_destroy,
1147
- test_fixture_teardown);
1148
-
1149
- g_test_add("/libusb/string-descriptor", UMockdevTestbedFixture, NULL,
1150
- test_fixture_setup_with_canon,
1151
- test_get_string_descriptor,
1152
- test_fixture_teardown);
1153
-
1154
- g_test_add("/libusb/timeout", UMockdevTestbedFixture, NULL,
1155
- test_fixture_setup_with_canon,
1156
- test_timeout,
1157
- test_fixture_teardown);
1158
-
1159
- g_test_add("/libusb/threaded-submit", UMockdevTestbedFixture, NULL,
1160
- test_fixture_setup_with_canon,
1161
- test_threaded_submit,
1162
- test_fixture_teardown);
1163
-
1164
- g_test_add("/libusb/hotplug/enumerate", UMockdevTestbedFixture, NULL,
1165
- test_fixture_setup_with_canon,
1166
- test_hotplug_enumerate,
1167
- test_fixture_teardown);
1168
-
1169
- g_test_add("/libusb/hotplug/add-remove", UMockdevTestbedFixture, NULL,
1170
- test_fixture_setup_empty,
1171
- test_hotplug_add_remove,
1172
- test_fixture_teardown);
1173
-
1174
- return g_test_run();
1175
- }