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.
- package/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/usb/bindings.js +1 -1
- package/dist/usb/bindings.js.map +1 -1
- package/dist/usb/capability.js.map +1 -1
- package/dist/usb/device.js.map +1 -1
- package/dist/usb/endpoint.d.ts +1 -0
- package/dist/usb/endpoint.js +2 -2
- package/dist/usb/endpoint.js.map +1 -1
- package/dist/usb/index.js.map +1 -1
- package/dist/usb/interface.js +2 -2
- package/dist/usb/interface.js.map +1 -1
- package/dist/webusb/index.d.ts +2 -2
- package/dist/webusb/index.js.map +1 -1
- package/dist/webusb/webusb-device.js +10 -10
- package/dist/webusb/webusb-device.js.map +1 -1
- package/libusb/.codespellrc +3 -0
- package/libusb/.private/appveyor_build.sh +5 -1
- package/libusb/.private/ci-build.sh +26 -1
- package/libusb/.private/ci-container-build.sh +2 -5
- package/libusb/.private/wbs.txt +5 -8
- package/libusb/AUTHORS +22 -0
- package/libusb/ChangeLog +19 -2
- package/libusb/HACKING +25 -0
- package/libusb/INSTALL_WIN.txt +11 -10
- package/libusb/NEWS +2 -2
- package/libusb/README +3 -2
- package/libusb/README.git +1 -1
- package/libusb/Xcode/common.xcconfig +8 -1
- package/libusb/Xcode/config.h +0 -6
- package/libusb/Xcode/debug.xcconfig +4 -1
- package/libusb/Xcode/libusb.xcconfig +1 -1
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +60 -30
- package/libusb/Xcode/libusb_debug.xcconfig +1 -1
- package/libusb/Xcode/libusb_release.xcconfig +1 -1
- package/libusb/Xcode/release.xcconfig +1 -1
- package/libusb/appveyor.yml +33 -9
- package/libusb/configure.ac +68 -37
- package/libusb/examples/dpfp.c +2 -2
- package/libusb/examples/fxload.c +2 -2
- package/libusb/examples/hotplugtest.c +28 -13
- package/libusb/examples/listdevs.c +1 -1
- package/libusb/examples/sam3u_benchmark.c +1 -1
- package/libusb/examples/testlibusb.c +1 -1
- package/libusb/examples/xusb.c +74 -19
- package/libusb/libusb/Makefile.am +11 -1
- package/libusb/libusb/core.c +364 -186
- package/libusb/libusb/descriptor.c +276 -16
- package/libusb/libusb/hotplug.c +5 -4
- package/libusb/libusb/io.c +72 -61
- package/libusb/libusb/libusb-1.0.def +14 -1
- package/libusb/libusb/libusb.h +245 -76
- package/libusb/libusb/libusbi.h +35 -13
- package/libusb/libusb/os/darwin_usb.c +542 -279
- package/libusb/libusb/os/darwin_usb.h +44 -115
- package/libusb/libusb/os/emscripten_webusb.cpp +870 -0
- package/libusb/libusb/os/events_posix.c +40 -0
- package/libusb/libusb/os/events_posix.h +3 -0
- package/libusb/libusb/os/linux_usbfs.c +27 -16
- package/libusb/libusb/os/netbsd_usb.c +36 -36
- package/libusb/libusb/os/openbsd_usb.c +34 -34
- package/libusb/libusb/os/sunos_usb.c +25 -15
- package/libusb/libusb/os/threads_posix.c +1 -5
- package/libusb/libusb/os/windows_common.c +13 -5
- package/libusb/libusb/os/windows_common.h +8 -0
- package/libusb/libusb/os/windows_winusb.c +366 -174
- package/libusb/libusb/os/windows_winusb.h +13 -9
- package/libusb/libusb/strerror.c +5 -5
- package/libusb/libusb/sync.c +24 -19
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/Base.props +60 -0
- package/libusb/msvc/Configuration.Application.props +7 -0
- package/libusb/msvc/Configuration.Base.props +47 -0
- package/libusb/msvc/Configuration.DynamicLibrary.props +21 -0
- package/libusb/msvc/Configuration.StaticLibrary.props +7 -0
- package/libusb/msvc/ProjectConfigurations.Base.props +69 -0
- package/libusb/msvc/build_all.ps1 +17 -0
- package/libusb/msvc/config.h +2 -2
- package/libusb/msvc/dpfp.vcxproj +33 -0
- package/libusb/msvc/dpfp_threaded.vcxproj +38 -0
- package/libusb/msvc/fxload.vcxproj +46 -0
- package/libusb/msvc/getopt.vcxproj +33 -0
- package/libusb/msvc/hotplugtest.vcxproj +32 -0
- package/libusb/msvc/init_context.vcxproj +35 -0
- package/libusb/msvc/libusb.sln +542 -0
- package/libusb/msvc/libusb_dll.vcxproj +61 -0
- package/libusb/msvc/libusb_static.vcxproj +49 -0
- package/libusb/msvc/listdevs.vcxproj +32 -0
- package/libusb/msvc/sam3u_benchmark.vcxproj +33 -0
- package/libusb/msvc/set_option.vcxproj +35 -0
- package/libusb/msvc/stress.vcxproj +35 -0
- package/libusb/msvc/stress_mt.vcxproj +33 -0
- package/libusb/msvc/testlibusb.vcxproj +32 -0
- package/libusb/msvc/xusb.vcxproj +38 -0
- package/libusb/tests/Makefile.am +25 -3
- package/libusb/tests/init_context.c +153 -0
- package/libusb/tests/macos.c +130 -0
- package/libusb/tests/set_option.c +253 -0
- package/libusb/tests/stress.c +17 -14
- package/libusb/tests/stress_mt.c +265 -0
- package/libusb/tests/testlib.c +1 -1
- package/libusb/tests/umockdev.c +9 -9
- package/libusb/tests/webusb-test-shim/index.js +12 -0
- package/libusb/tests/webusb-test-shim/package-lock.json +50 -0
- package/libusb/tests/webusb-test-shim/package.json +10 -0
- package/package.json +7 -7
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-ia32/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-arm64/node.napi.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/device.cc +15 -5
- package/libusb/msvc/dpfp_2013.vcxproj +0 -87
- package/libusb/msvc/dpfp_2013.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_2015.vcxproj +0 -87
- package/libusb/msvc/dpfp_2015.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_2017.vcxproj +0 -106
- package/libusb/msvc/dpfp_2017.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_2019.vcxproj +0 -106
- package/libusb/msvc/dpfp_2019.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2013.vcxproj +0 -87
- package/libusb/msvc/dpfp_threaded_2013.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2015.vcxproj +0 -87
- package/libusb/msvc/dpfp_threaded_2015.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2017.vcxproj +0 -106
- package/libusb/msvc/dpfp_threaded_2017.vcxproj.filters +0 -26
- package/libusb/msvc/dpfp_threaded_2019.vcxproj +0 -106
- package/libusb/msvc/dpfp_threaded_2019.vcxproj.filters +0 -26
- package/libusb/msvc/fxload_2013.vcxproj +0 -94
- package/libusb/msvc/fxload_2013.vcxproj.filters +0 -35
- package/libusb/msvc/fxload_2015.vcxproj +0 -94
- package/libusb/msvc/fxload_2015.vcxproj.filters +0 -35
- package/libusb/msvc/fxload_2017.vcxproj +0 -113
- package/libusb/msvc/fxload_2017.vcxproj.filters +0 -35
- package/libusb/msvc/fxload_2019.vcxproj +0 -113
- package/libusb/msvc/fxload_2019.vcxproj.filters +0 -35
- package/libusb/msvc/getopt_2013.vcxproj +0 -72
- package/libusb/msvc/getopt_2013.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2015.vcxproj +0 -73
- package/libusb/msvc/getopt_2015.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2017.vcxproj +0 -92
- package/libusb/msvc/getopt_2017.vcxproj.filters +0 -26
- package/libusb/msvc/getopt_2019.vcxproj +0 -92
- package/libusb/msvc/getopt_2019.vcxproj.filters +0 -26
- package/libusb/msvc/hotplugtest_2013.vcxproj +0 -86
- package/libusb/msvc/hotplugtest_2013.vcxproj.filters +0 -23
- package/libusb/msvc/hotplugtest_2015.vcxproj +0 -86
- package/libusb/msvc/hotplugtest_2015.vcxproj.filters +0 -23
- package/libusb/msvc/hotplugtest_2017.vcxproj +0 -105
- package/libusb/msvc/hotplugtest_2017.vcxproj.filters +0 -23
- package/libusb/msvc/hotplugtest_2019.vcxproj +0 -105
- package/libusb/msvc/hotplugtest_2019.vcxproj.filters +0 -23
- package/libusb/msvc/libusb_2013.sln +0 -137
- package/libusb/msvc/libusb_2015.sln +0 -137
- package/libusb/msvc/libusb_2017.sln +0 -240
- package/libusb/msvc/libusb_2019.sln +0 -240
- package/libusb/msvc/libusb_dll_2013.vcxproj +0 -104
- package/libusb/msvc/libusb_dll_2013.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_dll_2015.vcxproj +0 -105
- package/libusb/msvc/libusb_dll_2015.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_dll_2017.vcxproj +0 -124
- package/libusb/msvc/libusb_dll_2017.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_dll_2019.vcxproj +0 -124
- package/libusb/msvc/libusb_dll_2019.vcxproj.filters +0 -94
- package/libusb/msvc/libusb_static_2013.vcxproj +0 -94
- package/libusb/msvc/libusb_static_2013.vcxproj.filters +0 -80
- package/libusb/msvc/libusb_static_2015.vcxproj +0 -95
- package/libusb/msvc/libusb_static_2015.vcxproj.filters +0 -80
- package/libusb/msvc/libusb_static_2017.vcxproj +0 -114
- package/libusb/msvc/libusb_static_2017.vcxproj.filters +0 -80
- package/libusb/msvc/libusb_static_2019.vcxproj +0 -114
- package/libusb/msvc/libusb_static_2019.vcxproj.filters +0 -80
- package/libusb/msvc/listdevs_2013.vcxproj +0 -86
- package/libusb/msvc/listdevs_2013.vcxproj.filters +0 -23
- package/libusb/msvc/listdevs_2015.vcxproj +0 -86
- package/libusb/msvc/listdevs_2015.vcxproj.filters +0 -23
- package/libusb/msvc/listdevs_2017.vcxproj +0 -105
- package/libusb/msvc/listdevs_2017.vcxproj.filters +0 -23
- package/libusb/msvc/listdevs_2019.vcxproj +0 -105
- package/libusb/msvc/listdevs_2019.vcxproj.filters +0 -23
- package/libusb/msvc/sam3u_benchmark_2013.vcxproj +0 -87
- package/libusb/msvc/sam3u_benchmark_2013.vcxproj.filters +0 -26
- package/libusb/msvc/sam3u_benchmark_2015.vcxproj +0 -87
- package/libusb/msvc/sam3u_benchmark_2015.vcxproj.filters +0 -26
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj +0 -106
- package/libusb/msvc/sam3u_benchmark_2017.vcxproj.filters +0 -26
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj +0 -106
- package/libusb/msvc/sam3u_benchmark_2019.vcxproj.filters +0 -26
- package/libusb/msvc/stress_2013.vcxproj +0 -89
- package/libusb/msvc/stress_2013.vcxproj.filters +0 -32
- package/libusb/msvc/stress_2015.vcxproj +0 -89
- package/libusb/msvc/stress_2015.vcxproj.filters +0 -32
- package/libusb/msvc/stress_2017.vcxproj +0 -108
- package/libusb/msvc/stress_2017.vcxproj.filters +0 -32
- package/libusb/msvc/stress_2019.vcxproj +0 -108
- package/libusb/msvc/stress_2019.vcxproj.filters +0 -32
- package/libusb/msvc/testlibusb_2013.vcxproj +0 -86
- package/libusb/msvc/testlibusb_2013.vcxproj.filters +0 -23
- package/libusb/msvc/testlibusb_2015.vcxproj +0 -86
- package/libusb/msvc/testlibusb_2015.vcxproj.filters +0 -23
- package/libusb/msvc/testlibusb_2017.vcxproj +0 -105
- package/libusb/msvc/testlibusb_2017.vcxproj.filters +0 -23
- package/libusb/msvc/testlibusb_2019.vcxproj +0 -105
- package/libusb/msvc/testlibusb_2019.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2013.vcxproj +0 -86
- package/libusb/msvc/xusb_2013.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2015.vcxproj +0 -86
- package/libusb/msvc/xusb_2015.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2017.vcxproj +0 -105
- package/libusb/msvc/xusb_2017.vcxproj.filters +0 -23
- package/libusb/msvc/xusb_2019.vcxproj +0 -105
- 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
|
+
}
|
package/libusb/tests/stress.c
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
+
}
|
package/libusb/tests/testlib.c
CHANGED
package/libusb/tests/umockdev.c
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
433
|
+
libusb_init_context(/*ctx=*/&fixture->ctx, /*options=*/NULL, /*num_options=*/0);
|
|
434
434
|
|
|
435
|
-
/*
|
|
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
|
-
|
|
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
|
+
};
|