usb 2.12.1 → 2.13.0

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 (222) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/index.js +6 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/usb/bindings.js +1 -1
  6. package/dist/usb/bindings.js.map +1 -1
  7. package/dist/usb/capability.js.map +1 -1
  8. package/dist/usb/device.js.map +1 -1
  9. package/dist/usb/endpoint.d.ts +1 -0
  10. package/dist/usb/endpoint.js +2 -2
  11. package/dist/usb/endpoint.js.map +1 -1
  12. package/dist/usb/index.js.map +1 -1
  13. package/dist/usb/interface.js +2 -2
  14. package/dist/usb/interface.js.map +1 -1
  15. package/dist/webusb/index.d.ts +2 -2
  16. package/dist/webusb/index.js.map +1 -1
  17. package/dist/webusb/webusb-device.js +10 -10
  18. package/dist/webusb/webusb-device.js.map +1 -1
  19. package/libusb/.codespellrc +3 -0
  20. package/libusb/.private/appveyor_build.sh +5 -1
  21. package/libusb/.private/ci-build.sh +26 -1
  22. package/libusb/.private/ci-container-build.sh +2 -5
  23. package/libusb/.private/wbs.txt +5 -8
  24. package/libusb/AUTHORS +22 -0
  25. package/libusb/ChangeLog +19 -2
  26. package/libusb/HACKING +25 -0
  27. package/libusb/INSTALL_WIN.txt +11 -10
  28. package/libusb/NEWS +2 -2
  29. package/libusb/README +3 -2
  30. package/libusb/README.git +1 -1
  31. package/libusb/Xcode/common.xcconfig +8 -1
  32. package/libusb/Xcode/config.h +0 -6
  33. package/libusb/Xcode/debug.xcconfig +4 -1
  34. package/libusb/Xcode/libusb.xcconfig +1 -1
  35. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +60 -30
  36. package/libusb/Xcode/libusb_debug.xcconfig +1 -1
  37. package/libusb/Xcode/libusb_release.xcconfig +1 -1
  38. package/libusb/Xcode/release.xcconfig +1 -1
  39. package/libusb/appveyor.yml +33 -9
  40. package/libusb/configure.ac +68 -37
  41. package/libusb/examples/dpfp.c +2 -2
  42. package/libusb/examples/fxload.c +2 -2
  43. package/libusb/examples/hotplugtest.c +28 -13
  44. package/libusb/examples/listdevs.c +1 -1
  45. package/libusb/examples/sam3u_benchmark.c +1 -1
  46. package/libusb/examples/testlibusb.c +1 -1
  47. package/libusb/examples/xusb.c +74 -19
  48. package/libusb/libusb/Makefile.am +11 -1
  49. package/libusb/libusb/core.c +364 -186
  50. package/libusb/libusb/descriptor.c +276 -16
  51. package/libusb/libusb/hotplug.c +5 -4
  52. package/libusb/libusb/io.c +72 -61
  53. package/libusb/libusb/libusb-1.0.def +14 -1
  54. package/libusb/libusb/libusb.h +245 -76
  55. package/libusb/libusb/libusbi.h +35 -13
  56. package/libusb/libusb/os/darwin_usb.c +542 -279
  57. package/libusb/libusb/os/darwin_usb.h +44 -115
  58. package/libusb/libusb/os/emscripten_webusb.cpp +870 -0
  59. package/libusb/libusb/os/events_posix.c +40 -0
  60. package/libusb/libusb/os/events_posix.h +3 -0
  61. package/libusb/libusb/os/linux_usbfs.c +27 -16
  62. package/libusb/libusb/os/netbsd_usb.c +36 -36
  63. package/libusb/libusb/os/openbsd_usb.c +34 -34
  64. package/libusb/libusb/os/sunos_usb.c +25 -15
  65. package/libusb/libusb/os/threads_posix.c +1 -5
  66. package/libusb/libusb/os/windows_common.c +13 -5
  67. package/libusb/libusb/os/windows_common.h +8 -0
  68. package/libusb/libusb/os/windows_winusb.c +366 -174
  69. package/libusb/libusb/os/windows_winusb.h +13 -9
  70. package/libusb/libusb/strerror.c +5 -5
  71. package/libusb/libusb/sync.c +24 -19
  72. package/libusb/libusb/version.h +1 -1
  73. package/libusb/libusb/version_nano.h +1 -1
  74. package/libusb/msvc/Base.props +60 -0
  75. package/libusb/msvc/Configuration.Application.props +7 -0
  76. package/libusb/msvc/Configuration.Base.props +47 -0
  77. package/libusb/msvc/Configuration.DynamicLibrary.props +21 -0
  78. package/libusb/msvc/Configuration.StaticLibrary.props +7 -0
  79. package/libusb/msvc/ProjectConfigurations.Base.props +69 -0
  80. package/libusb/msvc/build_all.ps1 +17 -0
  81. package/libusb/msvc/config.h +2 -2
  82. package/libusb/msvc/dpfp.vcxproj +33 -0
  83. package/libusb/msvc/dpfp_threaded.vcxproj +38 -0
  84. package/libusb/msvc/fxload.vcxproj +46 -0
  85. package/libusb/msvc/getopt.vcxproj +33 -0
  86. package/libusb/msvc/hotplugtest.vcxproj +32 -0
  87. package/libusb/msvc/init_context.vcxproj +35 -0
  88. package/libusb/msvc/libusb.sln +542 -0
  89. package/libusb/msvc/libusb_dll.vcxproj +61 -0
  90. package/libusb/msvc/libusb_static.vcxproj +49 -0
  91. package/libusb/msvc/listdevs.vcxproj +32 -0
  92. package/libusb/msvc/sam3u_benchmark.vcxproj +33 -0
  93. package/libusb/msvc/set_option.vcxproj +35 -0
  94. package/libusb/msvc/stress.vcxproj +35 -0
  95. package/libusb/msvc/stress_mt.vcxproj +33 -0
  96. package/libusb/msvc/testlibusb.vcxproj +32 -0
  97. package/libusb/msvc/xusb.vcxproj +38 -0
  98. package/libusb/tests/Makefile.am +25 -3
  99. package/libusb/tests/init_context.c +153 -0
  100. package/libusb/tests/macos.c +130 -0
  101. package/libusb/tests/set_option.c +253 -0
  102. package/libusb/tests/stress.c +17 -14
  103. package/libusb/tests/stress_mt.c +265 -0
  104. package/libusb/tests/testlib.c +1 -1
  105. package/libusb/tests/umockdev.c +9 -9
  106. package/libusb/tests/webusb-test-shim/index.js +12 -0
  107. package/libusb/tests/webusb-test-shim/package-lock.json +50 -0
  108. package/libusb/tests/webusb-test-shim/package.json +10 -0
  109. package/package.json +7 -7
  110. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  111. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  112. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  113. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  114. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  115. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  116. package/prebuilds/linux-ia32/node.napi.node +0 -0
  117. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  118. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  119. package/prebuilds/win32-arm64/node.napi.node +0 -0
  120. package/prebuilds/win32-ia32/node.napi.node +0 -0
  121. package/prebuilds/win32-x64/node.napi.node +0 -0
  122. package/src/device.cc +15 -5
  123. package/libusb/msvc/dpfp_2013.vcxproj +0 -87
  124. package/libusb/msvc/dpfp_2013.vcxproj.filters +0 -26
  125. package/libusb/msvc/dpfp_2015.vcxproj +0 -87
  126. package/libusb/msvc/dpfp_2015.vcxproj.filters +0 -26
  127. package/libusb/msvc/dpfp_2017.vcxproj +0 -106
  128. package/libusb/msvc/dpfp_2017.vcxproj.filters +0 -26
  129. package/libusb/msvc/dpfp_2019.vcxproj +0 -106
  130. package/libusb/msvc/dpfp_2019.vcxproj.filters +0 -26
  131. package/libusb/msvc/dpfp_threaded_2013.vcxproj +0 -87
  132. package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +0 -26
  133. package/libusb/msvc/dpfp_threaded_2015.vcxproj +0 -87
  134. package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +0 -26
  135. package/libusb/msvc/dpfp_threaded_2017.vcxproj +0 -106
  136. package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +0 -26
  137. package/libusb/msvc/dpfp_threaded_2019.vcxproj +0 -106
  138. package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +0 -26
  139. package/libusb/msvc/fxload_2013.vcxproj +0 -94
  140. package/libusb/msvc/fxload_2013.vcxproj.filters +0 -35
  141. package/libusb/msvc/fxload_2015.vcxproj +0 -94
  142. package/libusb/msvc/fxload_2015.vcxproj.filters +0 -35
  143. package/libusb/msvc/fxload_2017.vcxproj +0 -113
  144. package/libusb/msvc/fxload_2017.vcxproj.filters +0 -35
  145. package/libusb/msvc/fxload_2019.vcxproj +0 -113
  146. package/libusb/msvc/fxload_2019.vcxproj.filters +0 -35
  147. package/libusb/msvc/getopt_2013.vcxproj +0 -72
  148. package/libusb/msvc/getopt_2013.vcxproj.filters +0 -26
  149. package/libusb/msvc/getopt_2015.vcxproj +0 -73
  150. package/libusb/msvc/getopt_2015.vcxproj.filters +0 -26
  151. package/libusb/msvc/getopt_2017.vcxproj +0 -92
  152. package/libusb/msvc/getopt_2017.vcxproj.filters +0 -26
  153. package/libusb/msvc/getopt_2019.vcxproj +0 -92
  154. package/libusb/msvc/getopt_2019.vcxproj.filters +0 -26
  155. package/libusb/msvc/hotplugtest_2013.vcxproj +0 -86
  156. package/libusb/msvc/hotplugtest_2013.vcxproj.filters +0 -23
  157. package/libusb/msvc/hotplugtest_2015.vcxproj +0 -86
  158. package/libusb/msvc/hotplugtest_2015.vcxproj.filters +0 -23
  159. package/libusb/msvc/hotplugtest_2017.vcxproj +0 -105
  160. package/libusb/msvc/hotplugtest_2017.vcxproj.filters +0 -23
  161. package/libusb/msvc/hotplugtest_2019.vcxproj +0 -105
  162. package/libusb/msvc/hotplugtest_2019.vcxproj.filters +0 -23
  163. package/libusb/msvc/libusb_2013.sln +0 -137
  164. package/libusb/msvc/libusb_2015.sln +0 -137
  165. package/libusb/msvc/libusb_2017.sln +0 -240
  166. package/libusb/msvc/libusb_2019.sln +0 -240
  167. package/libusb/msvc/libusb_dll_2013.vcxproj +0 -104
  168. package/libusb/msvc/libusb_dll_2013.vcxproj.filters +0 -94
  169. package/libusb/msvc/libusb_dll_2015.vcxproj +0 -105
  170. package/libusb/msvc/libusb_dll_2015.vcxproj.filters +0 -94
  171. package/libusb/msvc/libusb_dll_2017.vcxproj +0 -124
  172. package/libusb/msvc/libusb_dll_2017.vcxproj.filters +0 -94
  173. package/libusb/msvc/libusb_dll_2019.vcxproj +0 -124
  174. package/libusb/msvc/libusb_dll_2019.vcxproj.filters +0 -94
  175. package/libusb/msvc/libusb_static_2013.vcxproj +0 -94
  176. package/libusb/msvc/libusb_static_2013.vcxproj.filters +0 -80
  177. package/libusb/msvc/libusb_static_2015.vcxproj +0 -95
  178. package/libusb/msvc/libusb_static_2015.vcxproj.filters +0 -80
  179. package/libusb/msvc/libusb_static_2017.vcxproj +0 -114
  180. package/libusb/msvc/libusb_static_2017.vcxproj.filters +0 -80
  181. package/libusb/msvc/libusb_static_2019.vcxproj +0 -114
  182. package/libusb/msvc/libusb_static_2019.vcxproj.filters +0 -80
  183. package/libusb/msvc/listdevs_2013.vcxproj +0 -86
  184. package/libusb/msvc/listdevs_2013.vcxproj.filters +0 -23
  185. package/libusb/msvc/listdevs_2015.vcxproj +0 -86
  186. package/libusb/msvc/listdevs_2015.vcxproj.filters +0 -23
  187. package/libusb/msvc/listdevs_2017.vcxproj +0 -105
  188. package/libusb/msvc/listdevs_2017.vcxproj.filters +0 -23
  189. package/libusb/msvc/listdevs_2019.vcxproj +0 -105
  190. package/libusb/msvc/listdevs_2019.vcxproj.filters +0 -23
  191. package/libusb/msvc/sam3u_benchmark_2013.vcxproj +0 -87
  192. package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +0 -26
  193. package/libusb/msvc/sam3u_benchmark_2015.vcxproj +0 -87
  194. package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +0 -26
  195. package/libusb/msvc/sam3u_benchmark_2017.vcxproj +0 -106
  196. package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +0 -26
  197. package/libusb/msvc/sam3u_benchmark_2019.vcxproj +0 -106
  198. package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +0 -26
  199. package/libusb/msvc/stress_2013.vcxproj +0 -89
  200. package/libusb/msvc/stress_2013.vcxproj.filters +0 -32
  201. package/libusb/msvc/stress_2015.vcxproj +0 -89
  202. package/libusb/msvc/stress_2015.vcxproj.filters +0 -32
  203. package/libusb/msvc/stress_2017.vcxproj +0 -108
  204. package/libusb/msvc/stress_2017.vcxproj.filters +0 -32
  205. package/libusb/msvc/stress_2019.vcxproj +0 -108
  206. package/libusb/msvc/stress_2019.vcxproj.filters +0 -32
  207. package/libusb/msvc/testlibusb_2013.vcxproj +0 -86
  208. package/libusb/msvc/testlibusb_2013.vcxproj.filters +0 -23
  209. package/libusb/msvc/testlibusb_2015.vcxproj +0 -86
  210. package/libusb/msvc/testlibusb_2015.vcxproj.filters +0 -23
  211. package/libusb/msvc/testlibusb_2017.vcxproj +0 -105
  212. package/libusb/msvc/testlibusb_2017.vcxproj.filters +0 -23
  213. package/libusb/msvc/testlibusb_2019.vcxproj +0 -105
  214. package/libusb/msvc/testlibusb_2019.vcxproj.filters +0 -23
  215. package/libusb/msvc/xusb_2013.vcxproj +0 -86
  216. package/libusb/msvc/xusb_2013.vcxproj.filters +0 -23
  217. package/libusb/msvc/xusb_2015.vcxproj +0 -86
  218. package/libusb/msvc/xusb_2015.vcxproj.filters +0 -23
  219. package/libusb/msvc/xusb_2017.vcxproj +0 -105
  220. package/libusb/msvc/xusb_2017.vcxproj.filters +0 -23
  221. package/libusb/msvc/xusb_2019.vcxproj +0 -105
  222. package/libusb/msvc/xusb_2019.vcxproj.filters +0 -23
@@ -0,0 +1,253 @@
1
+ /* -*- Mode: C; indent-tabs-mode:nil -*- */
2
+ /*
3
+ * Unit tests for libusb_set_option
4
+ * Copyright © 2023 Nathan Hjelm <hjelmn@cs.unm.edu>
5
+ * Copyright © 2023 Google, LLC. All rights reserved.
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
+ #include "config.h"
23
+
24
+ #include <stdlib.h>
25
+ #include <stdio.h>
26
+ #include <inttypes.h>
27
+ #include "libusbi.h"
28
+ #include "libusb_testlib.h"
29
+
30
+ #if defined(_WIN32) && !defined(__CYGWIN__)
31
+ #include <winbase.h>
32
+
33
+ #if defined(ENABLE_LOGGING)
34
+ static int unsetenv(const char *env) {
35
+ return _putenv_s(env, "");
36
+ }
37
+
38
+ static int setenv(const char *env, const char *value, int overwrite) {
39
+ if (getenv(env) && !overwrite)
40
+ return 0;
41
+ return _putenv_s(env, value);
42
+ }
43
+ #endif
44
+ #endif
45
+
46
+ #define LIBUSB_TEST_CLEAN_EXIT(code) \
47
+ do { \
48
+ if (test_ctx != NULL) { \
49
+ libusb_exit(test_ctx); \
50
+ } \
51
+ unsetenv("LIBUSB_DEBUG"); \
52
+ return (code); \
53
+ } while (0)
54
+
55
+ /**
56
+ * Fail the test if the expression does not evaluate to LIBUSB_SUCCESS.
57
+ */
58
+ #define LIBUSB_TEST_RETURN_ON_ERROR(expr) \
59
+ do { \
60
+ int _result = (expr); \
61
+ if (LIBUSB_SUCCESS != _result) { \
62
+ libusb_testlib_logf("Not success (%s) at %s:%d", #expr, \
63
+ __FILE__, __LINE__); \
64
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \
65
+ } \
66
+ } while (0)
67
+
68
+ /**
69
+ * Use relational operator to compare two values and fail the test if the
70
+ * comparison is false. Intended to compare integer or pointer types.
71
+ *
72
+ * Example: LIBUSB_EXPECT(==, 0, 1) -> fail, LIBUSB_EXPECT(==, 0, 0) -> ok.
73
+ */
74
+ #define LIBUSB_EXPECT(operator, lhs, rhs) \
75
+ do { \
76
+ int64_t _lhs = (int64_t)(intptr_t)(lhs), _rhs = (int64_t)(intptr_t)(rhs); \
77
+ if (!(_lhs operator _rhs)) { \
78
+ libusb_testlib_logf("Expected %s (%" PRId64 ") " #operator \
79
+ " %s (%" PRId64 ") at %s:%d", #lhs, \
80
+ (int64_t)(intptr_t)_lhs, #rhs, \
81
+ (int64_t)(intptr_t)_rhs, __FILE__, \
82
+ __LINE__); \
83
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_FAILURE); \
84
+ } \
85
+ } while (0)
86
+
87
+
88
+ static libusb_testlib_result test_set_log_level_basic(void) {
89
+ #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
90
+ libusb_context *test_ctx = NULL;
91
+
92
+ /* unset LIBUSB_DEBUG if it is set */
93
+ unsetenv("LIBUSB_DEBUG");
94
+
95
+ /* test basic functionality */
96
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
97
+ /*num_options=*/0));
98
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx,
99
+ LIBUSB_OPTION_LOG_LEVEL,
100
+ LIBUSB_LOG_LEVEL_ERROR));
101
+ LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR);
102
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx,
103
+ LIBUSB_OPTION_LOG_LEVEL,
104
+ LIBUSB_LOG_LEVEL_NONE));
105
+ LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_NONE);
106
+
107
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS);
108
+ #else
109
+ return TEST_STATUS_SKIP;
110
+ #endif
111
+ }
112
+
113
+ static libusb_testlib_result test_set_log_level_default(void) {
114
+ #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
115
+ libusb_context *test_ctx = NULL;
116
+
117
+ /* set the default debug level */
118
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL,
119
+ LIBUSB_LOG_LEVEL_ERROR));
120
+
121
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
122
+ /*num_options=*/0));
123
+ /* check that debug level came from the default */
124
+ LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_ERROR);
125
+
126
+ /* try to override the old log level. since this was set from the default it
127
+ * should be possible to change it */
128
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx,
129
+ LIBUSB_OPTION_LOG_LEVEL,
130
+ LIBUSB_LOG_LEVEL_NONE));
131
+ LIBUSB_EXPECT(==, test_ctx->debug, LIBUSB_LOG_LEVEL_NONE);
132
+
133
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS);
134
+ #else
135
+ return TEST_STATUS_SKIP;
136
+ #endif
137
+ }
138
+
139
+ static libusb_testlib_result test_set_log_level_env(void) {
140
+ #if defined(ENABLE_LOGGING)
141
+ libusb_context *test_ctx = NULL;
142
+
143
+ /* check that libusb_set_option does not change the log level when it was set
144
+ * from the environment. */
145
+ setenv("LIBUSB_DEBUG", "4", /*overwrite=*/0);
146
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
147
+ /*num_options=*/0));
148
+ #ifndef ENABLE_DEBUG_LOGGING
149
+ LIBUSB_EXPECT(==, test_ctx->debug, 4);
150
+ #endif
151
+
152
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx,
153
+ LIBUSB_OPTION_LOG_LEVEL,
154
+ LIBUSB_LOG_LEVEL_ERROR));
155
+ /* environment variable should always override LIBUSB_OPTION_LOG_LEVEL if set */
156
+ #ifndef ENABLE_DEBUG_LOGGING
157
+ LIBUSB_EXPECT(==, test_ctx->debug, 4);
158
+ #endif
159
+
160
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS);
161
+ #else
162
+ return TEST_STATUS_SKIP;
163
+ #endif
164
+ }
165
+
166
+
167
+ static libusb_testlib_result test_no_discovery(void)
168
+ {
169
+ #if defined(__linux__)
170
+ libusb_context *test_ctx;
171
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
172
+ /*num_options=*/0));
173
+ libusb_device **device_list = NULL;
174
+ ssize_t num_devices = libusb_get_device_list(test_ctx, &device_list);
175
+ libusb_free_device_list(device_list, /*unref_devices=*/1);
176
+ libusb_exit(test_ctx);
177
+ test_ctx = NULL;
178
+
179
+ if (num_devices == 0) {
180
+ libusb_testlib_logf("Warning: no devices found, the test will only verify that setting LIBUSB_OPTION_NO_DEVICE_DISCOVERY succeeds.");
181
+ }
182
+
183
+ LIBUSB_EXPECT(>=, num_devices, 0);
184
+
185
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY));
186
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
187
+ /*num_options=*/0));
188
+ device_list = NULL;
189
+ num_devices = libusb_get_device_list(test_ctx, &device_list);
190
+ libusb_free_device_list(device_list, /*unref_devices=*/1);
191
+
192
+ LIBUSB_EXPECT(==, num_devices, 0);
193
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS);
194
+ #else
195
+ return TEST_STATUS_SKIP;
196
+ #endif
197
+ }
198
+
199
+ #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
200
+ static void LIBUSB_CALL test_log_cb(libusb_context *ctx, enum libusb_log_level level,
201
+ const char *str) {
202
+ UNUSED(ctx);
203
+ UNUSED(level);
204
+ UNUSED(str);
205
+ }
206
+ #endif
207
+
208
+
209
+ static libusb_testlib_result test_set_log_cb(void)
210
+ {
211
+ #if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
212
+ libusb_context *test_ctx = NULL;
213
+
214
+ /* set the log callback on the context */
215
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
216
+ /*num_options=*/0));
217
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(test_ctx, LIBUSB_OPTION_LOG_CB,
218
+ test_log_cb));
219
+
220
+ /* check that debug level came from the default */
221
+ LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb);
222
+
223
+ libusb_exit(test_ctx);
224
+ test_ctx = NULL;
225
+
226
+ /* set the log callback for all future contexts */
227
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_set_option(/*ctx=*/NULL, LIBUSB_OPTION_LOG_CB,
228
+ test_log_cb));
229
+ LIBUSB_TEST_RETURN_ON_ERROR(libusb_init_context(&test_ctx, /*options=*/NULL,
230
+ /*num_options=*/0));
231
+ LIBUSB_EXPECT(==, test_ctx->log_handler, test_log_cb);
232
+
233
+
234
+ LIBUSB_TEST_CLEAN_EXIT(TEST_STATUS_SUCCESS);
235
+ #else
236
+ return TEST_STATUS_SKIP;
237
+ #endif
238
+ }
239
+
240
+ static const libusb_testlib_test tests[] = {
241
+ { "test_set_log_level_basic", &test_set_log_level_basic },
242
+ { "test_set_log_level_env", &test_set_log_level_env },
243
+ { "test_no_discovery", &test_no_discovery },
244
+ /* since default options can't be unset, run this one last */
245
+ { "test_set_log_level_default", &test_set_log_level_default },
246
+ { "test_set_log_cb", &test_set_log_cb },
247
+ LIBUSB_NULL_TEST
248
+ };
249
+
250
+ int main(int argc, char *argv[])
251
+ {
252
+ return libusb_testlib_run_tests(argc, argv, tests);
253
+ }
@@ -32,7 +32,7 @@ static libusb_testlib_result test_init_and_exit(void)
32
32
  libusb_context *ctx = NULL;
33
33
  int r;
34
34
 
35
- r = libusb_init(&ctx);
35
+ r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0);
36
36
  if (r != LIBUSB_SUCCESS) {
37
37
  libusb_testlib_logf(
38
38
  "Failed to init libusb on iteration %d: %d",
@@ -51,7 +51,7 @@ static libusb_testlib_result test_get_device_list(void)
51
51
  libusb_context *ctx;
52
52
  int r;
53
53
 
54
- r = libusb_init(&ctx);
54
+ r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0);
55
55
  if (r != LIBUSB_SUCCESS) {
56
56
  libusb_testlib_logf("Failed to init libusb: %d", r);
57
57
  return TEST_STATUS_FAILURE;
@@ -63,7 +63,7 @@ static libusb_testlib_result test_get_device_list(void)
63
63
  if (list_size < 0 || !device_list) {
64
64
  libusb_testlib_logf(
65
65
  "Failed to get device list on iteration %d: %ld (%p)",
66
- i, (long)-list_size, device_list);
66
+ i, (long) -list_size, (void *) device_list);
67
67
  libusb_exit(ctx);
68
68
  return TEST_STATUS_FAILURE;
69
69
  }
@@ -83,7 +83,7 @@ static libusb_testlib_result test_many_device_lists(void)
83
83
  libusb_device **device_lists[LIST_COUNT];
84
84
  int r;
85
85
 
86
- r = libusb_init(&ctx);
86
+ r = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0);
87
87
  if (r != LIBUSB_SUCCESS) {
88
88
  libusb_testlib_logf("Failed to init libusb: %d", r);
89
89
  return TEST_STATUS_FAILURE;
@@ -97,7 +97,7 @@ static libusb_testlib_result test_many_device_lists(void)
97
97
  if (list_size < 0 || !device_lists[i]) {
98
98
  libusb_testlib_logf(
99
99
  "Failed to get device list on iteration %d: %ld (%p)",
100
- i, (long)-list_size, device_lists[i]);
100
+ i, (long) -list_size, (void *) device_lists[i]);
101
101
  result = TEST_STATUS_FAILURE;
102
102
  break;
103
103
  }
@@ -123,22 +123,25 @@ static libusb_testlib_result test_default_context_change(void)
123
123
  libusb_context *ctx = NULL;
124
124
  int r;
125
125
 
126
+
127
+ /* Enable debug output on new context, to be sure to use the context */
128
+ struct libusb_init_option options[] = {
129
+ {
130
+ .option = LIBUSB_OPTION_LOG_LEVEL,
131
+ .value = {.ival = LIBUSB_LOG_LEVEL_DEBUG},
132
+ },
133
+ };
134
+ int num_options = 1;
135
+
126
136
  /* First create a new context */
127
- r = libusb_init(&ctx);
137
+ r = libusb_init_context(&ctx, options, num_options);
128
138
  if (r != LIBUSB_SUCCESS) {
129
139
  libusb_testlib_logf("Failed to init libusb: %d", r);
130
140
  return TEST_STATUS_FAILURE;
131
141
  }
132
142
 
133
- /* Enable debug output on new context, to be sure to use the context */
134
- libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
135
-
136
- /* Enable debug output on the default context. This should work even before
137
- * the context has been created. */
138
- libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
139
-
140
143
  /* Now create a reference to the default context */
141
- r = libusb_init(NULL);
144
+ r = libusb_init_context(/*ctx=*/NULL, options, num_options);
142
145
  if (r != LIBUSB_SUCCESS) {
143
146
  libusb_testlib_logf("Failed to init libusb: %d", r);
144
147
  libusb_exit(ctx);
@@ -0,0 +1,265 @@
1
+ /*
2
+ * libusb multi-thread test program
3
+ * Copyright 2022-2023 Tormod Volden
4
+ *
5
+ * This program is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+ #include <config.h>
21
+
22
+ #include <libusb.h>
23
+ #include <stdio.h>
24
+ #include <stdbool.h>
25
+
26
+ #if defined(PLATFORM_POSIX)
27
+
28
+ #include <pthread.h>
29
+ typedef pthread_t thread_t;
30
+ typedef void * thread_return_t;
31
+ #define THREAD_RETURN_VALUE NULL
32
+ #define THREAD_CALL_TYPE
33
+
34
+ static inline int thread_create(thread_t *thread,
35
+ thread_return_t (*thread_entry)(void *arg), void *arg)
36
+ {
37
+ return pthread_create(thread, NULL, thread_entry, arg) == 0 ? 0 : -1;
38
+ }
39
+
40
+ static inline void thread_join(thread_t thread)
41
+ {
42
+ (void)pthread_join(thread, NULL);
43
+ }
44
+
45
+ #include <stdatomic.h>
46
+
47
+ #elif defined(PLATFORM_WINDOWS)
48
+
49
+ typedef HANDLE thread_t;
50
+ #define THREAD_RETURN_VALUE 0
51
+ #define THREAD_CALL_TYPE __stdcall
52
+
53
+ #if defined(__CYGWIN__)
54
+ typedef DWORD thread_return_t;
55
+ #else
56
+ #include <process.h>
57
+ typedef unsigned thread_return_t;
58
+ #endif
59
+
60
+ static inline int thread_create(thread_t *thread,
61
+ thread_return_t (__stdcall *thread_entry)(void *arg), void *arg)
62
+ {
63
+ #if defined(__CYGWIN__)
64
+ *thread = CreateThread(NULL, 0, thread_entry, arg, 0, NULL);
65
+ #else
66
+ *thread = (HANDLE)_beginthreadex(NULL, 0, thread_entry, arg, 0, NULL);
67
+ #endif
68
+ return *thread != NULL ? 0 : -1;
69
+ }
70
+
71
+ static inline void thread_join(thread_t thread)
72
+ {
73
+ (void)WaitForSingleObject(thread, INFINITE);
74
+ (void)CloseHandle(thread);
75
+ }
76
+
77
+ typedef volatile LONG atomic_bool;
78
+
79
+ #define atomic_exchange InterlockedExchange
80
+ #endif /* PLATFORM_WINDOWS */
81
+
82
+ /* Test that creates and destroys contexts repeatedly */
83
+
84
+ #define NTHREADS 8
85
+ #define ITERS 64
86
+ #define MAX_DEVCOUNT 128
87
+
88
+ struct thread_info {
89
+ int number;
90
+ int enumerate;
91
+ ssize_t devcount;
92
+ int err;
93
+ int iteration;
94
+ } tinfo[NTHREADS];
95
+
96
+ atomic_bool no_access[MAX_DEVCOUNT];
97
+
98
+ /* Function called by backend during device initialization to convert
99
+ * multi-byte fields in the device descriptor to host-endian format.
100
+ * Copied from libusbi.h as we want test to be realistic and not depend on internals.
101
+ */
102
+ static inline void usbi_localize_device_descriptor(struct libusb_device_descriptor *desc)
103
+ {
104
+ desc->bcdUSB = libusb_le16_to_cpu(desc->bcdUSB);
105
+ desc->idVendor = libusb_le16_to_cpu(desc->idVendor);
106
+ desc->idProduct = libusb_le16_to_cpu(desc->idProduct);
107
+ desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice);
108
+ }
109
+
110
+ static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg)
111
+ {
112
+ struct thread_info *ti = (struct thread_info *) arg;
113
+
114
+ for (ti->iteration = 0; ti->iteration < ITERS && !ti->err; ti->iteration++) {
115
+ libusb_context *ctx = NULL;
116
+
117
+ if ((ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0)) != 0) {
118
+ break;
119
+ }
120
+ if (ti->enumerate) {
121
+ libusb_device **devs;
122
+ ti->devcount = libusb_get_device_list(ctx, &devs);
123
+ if (ti->devcount < 0) {
124
+ ti->err = (int)ti->devcount;
125
+ break;
126
+ }
127
+ for (int i = 0; i < ti->devcount && ti->err == 0; i++) {
128
+ libusb_device *dev = devs[i];
129
+ struct libusb_device_descriptor desc;
130
+ if ((ti->err = libusb_get_device_descriptor(dev, &desc)) != 0) {
131
+ break;
132
+ }
133
+ if (no_access[i]) {
134
+ continue;
135
+ }
136
+ libusb_device_handle *dev_handle;
137
+ int open_err = libusb_open(dev, &dev_handle);
138
+ if (open_err == LIBUSB_ERROR_ACCESS
139
+ #if defined(PLATFORM_WINDOWS)
140
+ || open_err == LIBUSB_ERROR_NOT_SUPPORTED
141
+ || open_err == LIBUSB_ERROR_NOT_FOUND
142
+ #endif
143
+ ) {
144
+ /* Use atomic swap to ensure we print warning only once across all threads.
145
+ This is a warning and not a hard error because it should be fine to run tests
146
+ even if we don't have access to some devices. */
147
+ if (!atomic_exchange(&no_access[i], true)) {
148
+ fprintf(stderr, "No access to device %04x:%04x, skipping transfer tests.\n", desc.idVendor, desc.idProduct);
149
+ }
150
+ continue;
151
+ }
152
+ if (open_err != 0) {
153
+ ti->err = open_err;
154
+ break;
155
+ }
156
+ /* Request raw descriptor via control transfer.
157
+ This tests opening, transferring and closing from multiple threads in parallel. */
158
+ struct libusb_device_descriptor raw_desc;
159
+ int raw_desc_len = libusb_get_descriptor(dev_handle, LIBUSB_DT_DEVICE, 0, (unsigned char *)&raw_desc, sizeof(raw_desc));
160
+ if (raw_desc_len < 0) {
161
+ ti->err = raw_desc_len;
162
+ goto close;
163
+ }
164
+ if (raw_desc_len != sizeof(raw_desc)) {
165
+ fprintf(stderr, "Thread %d: device %d: unexpected raw descriptor length %d\n",
166
+ ti->number, i, raw_desc_len);
167
+ ti->err = LIBUSB_ERROR_OTHER;
168
+ goto close;
169
+ }
170
+ usbi_localize_device_descriptor(&raw_desc);
171
+ #define ASSERT_EQ(field) if (raw_desc.field != desc.field) { \
172
+ fprintf(stderr, "Thread %d: device %d: mismatch in field " #field ": %d != %d\n", \
173
+ ti->number, i, raw_desc.field, desc.field); \
174
+ ti->err = LIBUSB_ERROR_OTHER; \
175
+ goto close; \
176
+ }
177
+ ASSERT_EQ(bLength);
178
+ ASSERT_EQ(bDescriptorType);
179
+ #if !defined(PLATFORM_WINDOWS)
180
+ /* these are hardcoded by the winusbx HID backend */
181
+ ASSERT_EQ(bcdUSB);
182
+ ASSERT_EQ(bDeviceClass);
183
+ ASSERT_EQ(bDeviceSubClass);
184
+ ASSERT_EQ(bDeviceProtocol);
185
+ ASSERT_EQ(bMaxPacketSize0);
186
+ ASSERT_EQ(bcdDevice);
187
+ #endif
188
+ ASSERT_EQ(idVendor);
189
+ ASSERT_EQ(idProduct);
190
+ ASSERT_EQ(iManufacturer);
191
+ ASSERT_EQ(iProduct);
192
+ ASSERT_EQ(iSerialNumber);
193
+ ASSERT_EQ(bNumConfigurations);
194
+ close:
195
+ libusb_close(dev_handle);
196
+ }
197
+ libusb_free_device_list(devs, 1);
198
+ }
199
+
200
+ libusb_exit(ctx);
201
+ }
202
+ return (thread_return_t) THREAD_RETURN_VALUE;
203
+ }
204
+
205
+ static int test_multi_init(int enumerate)
206
+ {
207
+ thread_t threadId[NTHREADS];
208
+ int errs = 0;
209
+ int t, i;
210
+ ssize_t last_devcount = 0;
211
+ int devcount_mismatch = 0;
212
+ int access_failures = 0;
213
+
214
+ printf("Starting %d threads\n", NTHREADS);
215
+ for (t = 0; t < NTHREADS; t++) {
216
+ tinfo[t].err = 0;
217
+ tinfo[t].number = t;
218
+ tinfo[t].enumerate = enumerate;
219
+ thread_create(&threadId[t], &init_and_exit, (void *) &tinfo[t]);
220
+ }
221
+
222
+ for (t = 0; t < NTHREADS; t++) {
223
+ thread_join(threadId[t]);
224
+ if (tinfo[t].err) {
225
+ errs++;
226
+ fprintf(stderr,
227
+ "Thread %d failed (iteration %d): %s\n",
228
+ tinfo[t].number,
229
+ tinfo[t].iteration,
230
+ libusb_error_name(tinfo[t].err));
231
+ } else if (enumerate) {
232
+ if (t > 0 && tinfo[t].devcount != last_devcount) {
233
+ devcount_mismatch++;
234
+ printf("Device count mismatch: Thread %d discovered %ld devices instead of %ld\n",
235
+ tinfo[t].number,
236
+ (long int) tinfo[t].devcount,
237
+ (long int) last_devcount);
238
+ }
239
+ last_devcount = tinfo[t].devcount;
240
+ }
241
+ }
242
+
243
+ for (i = 0; i < MAX_DEVCOUNT; i++)
244
+ if (no_access[i])
245
+ access_failures++;
246
+
247
+ if (enumerate && !devcount_mismatch)
248
+ printf("All threads discovered %ld devices (%i not opened)\n",
249
+ (long int) last_devcount, access_failures);
250
+
251
+ return errs + devcount_mismatch;
252
+ }
253
+
254
+ int main(void)
255
+ {
256
+ int errs = 0;
257
+
258
+ printf("Running multithreaded init/exit test...\n");
259
+ errs += test_multi_init(0);
260
+ printf("Running multithreaded init/exit test with enumeration...\n");
261
+ errs += test_multi_init(1);
262
+ printf("All done, %d errors\n", errs);
263
+
264
+ return errs != 0;
265
+ }
@@ -180,5 +180,5 @@ int libusb_testlib_run_tests(int argc, char *argv[],
180
180
  libusb_testlib_logf("Error in %d tests", error_count);
181
181
  libusb_testlib_logf("Skipped %d tests", skip_count);
182
182
 
183
- return pass_count != run_count;
183
+ return fail_count + error_count;
184
184
  }
@@ -33,7 +33,7 @@
33
33
  #define UNUSED_DATA __attribute__ ((unused)) gconstpointer unused_data
34
34
 
35
35
  /* avoid leak reports inside assertions; leaking stuff on assertion failures does not matter in tests */
36
- #if !defined(__clang__)
36
+ #if !defined(__clang__) && __GNUC__ > 9
37
37
  #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
38
38
  #pragma GCC diagnostic ignored "-Wanalyzer-file-leak"
39
39
  #endif
@@ -89,7 +89,7 @@ typedef struct {
89
89
  GList *flying_urbs;
90
90
  GList *discarded_urbs;
91
91
 
92
- /* GMutex confuses tsan unecessarily */
92
+ /* GMutex confuses TSan unnecessarily */
93
93
  pthread_mutex_t mutex;
94
94
  } UMockdevTestbedFixture;
95
95
 
@@ -245,7 +245,7 @@ handle_ioctl_cb (UMockdevIoctlBase *handler, UMockdevIoctlClient *client, UMockd
245
245
  ioctl_arg = umockdev_ioctl_client_get_arg (client);
246
246
 
247
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
248
+ * However, to make TSan work, we still stick to the API that resolves
249
249
  * the data into a local copy! */
250
250
 
251
251
  switch (request) {
@@ -430,9 +430,9 @@ test_fixture_setup_libusb(UMockdevTestbedFixture * fixture, int devcount)
430
430
  {
431
431
  libusb_device **devs = NULL;
432
432
 
433
- libusb_init (&fixture->ctx);
433
+ libusb_init_context(/*ctx=*/&fixture->ctx, /*options=*/NULL, /*num_options=*/0);
434
434
 
435
- /* Supress global log messages completely
435
+ /* Suppress global log messages completely
436
436
  * (though, in some tests it might be interesting to check there are no real ones).
437
437
  */
438
438
  libusb_set_log_cb (NULL, log_handler_null, LIBUSB_LOG_CB_GLOBAL);
@@ -573,7 +573,7 @@ test_implicit_default(UMockdevTestbedFixture * fixture, UNUSED_DATA)
573
573
  libusb_free_device_list(devs, TRUE);
574
574
  clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
575
575
 
576
- libusb_init(NULL);
576
+ libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0);
577
577
  g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
578
578
  libusb_exit(NULL);
579
579
 
@@ -876,7 +876,7 @@ transfer_submit_all_retry(TestThreadedSubmit *data)
876
876
  return NULL;
877
877
  }
878
878
 
879
- static void
879
+ static void LIBUSB_CALL
880
880
  test_threaded_submit_transfer_cb(struct libusb_transfer *transfer)
881
881
  {
882
882
  TestThreadedSubmit *data = transfer->user_data;
@@ -955,7 +955,7 @@ test_threaded_submit(UMockdevTestbedFixture * fixture, UNUSED_DATA)
955
955
  g_free (c);
956
956
  }
957
957
 
958
- static int
958
+ static int LIBUSB_CALL
959
959
  hotplug_count_arrival_cb(libusb_context *ctx,
960
960
  libusb_device *device,
961
961
  libusb_hotplug_event event,
@@ -972,7 +972,7 @@ hotplug_count_arrival_cb(libusb_context *ctx,
972
972
  }
973
973
 
974
974
  #ifdef UMOCKDEV_HOTPLUG
975
- static int
975
+ static int LIBUSB_CALL
976
976
  hotplug_count_removal_cb(libusb_context *ctx,
977
977
  libusb_device *device,
978
978
  libusb_hotplug_event event,
@@ -0,0 +1,12 @@
1
+ // It's not yet possible to automate actual Chrome's device selection, so
2
+ // for now run automated tests via Node.js WebUSB implementation.
3
+ //
4
+ // It might differ from browser one, but should be enough to catch most obvious issues.
5
+
6
+ const { WebUSB } = require('usb');
7
+
8
+ globalThis.navigator = {
9
+ usb: new WebUSB({
10
+ allowAllDevices: true
11
+ })
12
+ };