usb 2.17.0 → 2.18.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 +6 -0
- package/README.md +14 -0
- package/binding.gyp +2 -9
- package/dist/usb/bindings.d.ts +27 -2
- package/dist/usb/bindings.js.map +1 -1
- package/dist/usb/index.d.ts +0 -29
- package/dist/usb/index.js +4 -18
- package/dist/usb/index.js.map +1 -1
- package/libusb/.clang-tidy +5 -3
- package/libusb/.private/ci-build.sh +5 -1
- package/libusb/AUTHORS +14 -0
- package/libusb/ChangeLog +15 -2
- package/libusb/README +8 -5
- package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +4 -0
- package/libusb/configure.ac +12 -2
- package/libusb/examples/hotplugtest.c +19 -11
- package/libusb/examples/listdevs.c +41 -3
- package/libusb/examples/xusb.c +6 -1
- package/libusb/libusb/Makefile.am +4 -0
- package/libusb/libusb/core.c +175 -14
- package/libusb/libusb/descriptor.c +163 -14
- package/libusb/libusb/io.c +7 -3
- package/libusb/libusb/libusb-1.0.def +10 -0
- package/libusb/libusb/libusb.h +59 -9
- package/libusb/libusb/libusbi.h +89 -25
- package/libusb/libusb/os/darwin_usb.c +126 -46
- package/libusb/libusb/os/darwin_usb.h +10 -8
- package/libusb/libusb/os/emscripten_webusb.cpp +31 -10
- package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
- package/libusb/libusb/os/linux_usbfs.c +73 -25
- package/libusb/libusb/os/netbsd_usb.c +2 -0
- package/libusb/libusb/os/openbsd_usb.c +2 -0
- package/libusb/libusb/os/sunos_usb.c +2 -0
- package/libusb/libusb/os/threads_posix.c +3 -3
- package/libusb/libusb/os/threads_posix.h +8 -2
- package/libusb/libusb/os/threads_windows.h +2 -1
- package/libusb/libusb/os/windows_common.c +86 -1
- package/libusb/libusb/os/windows_common.h +20 -1
- package/libusb/libusb/os/windows_hotplug.c +321 -0
- package/libusb/libusb/os/windows_hotplug.h +28 -0
- package/libusb/libusb/os/windows_usbdk.c +16 -8
- package/libusb/libusb/os/windows_winusb.c +753 -41
- package/libusb/libusb/os/windows_winusb.h +11 -6
- package/libusb/libusb/version.h +1 -1
- package/libusb/libusb/version_nano.h +1 -1
- package/libusb/msvc/Base.props +1 -1
- package/libusb/msvc/Configuration.Base.props +2 -1
- package/libusb/msvc/Configuration.DynamicLibrary.props +12 -0
- package/libusb/msvc/ProjectConfigurations.Base.props +69 -16
- package/libusb/msvc/build_all.ps1 +2 -2
- package/libusb/msvc/config.h +4 -0
- package/libusb/msvc/getopt/bits/getopt_core.h +96 -0
- package/libusb/msvc/getopt/bits/getopt_ext.h +77 -0
- package/libusb/msvc/getopt/features.h +21 -0
- package/libusb/msvc/getopt/getopt.c +456 -705
- package/libusb/msvc/getopt/getopt.h +16 -158
- package/libusb/msvc/getopt/getopt1.c +40 -69
- package/libusb/msvc/getopt/getopt_int.h +118 -0
- package/libusb/msvc/getopt/gettext.h +7 -0
- package/libusb/msvc/getopt/unistd.h +5 -0
- package/libusb/msvc/getopt.vcxproj +11 -4
- package/libusb/msvc/libusb.sln +515 -268
- package/libusb/msvc/libusb_dll.vcxproj +2 -0
- package/libusb/msvc/libusb_static.vcxproj +2 -0
- package/libusb/msvc/xusb.vcxproj +1 -1
- package/libusb/tests/Makefile.am +10 -1
- package/libusb/tests/fuzz/corpus/bos/min.bos +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/min_valid_config.bin +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_a_endpoint_null.bin +0 -0
- package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_b_iad_oob.bin +0 -0
- package/libusb/tests/fuzz/fuzz_bos_descriptor.c +49 -0
- package/libusb/tests/fuzz/fuzz_descriptor_parsers.c +83 -0
- package/libusb/tests/stress_mt.c +2 -1
- package/libusb/tests/webusb-test-shim/index.js +6 -5
- package/libusb.gypi +5 -0
- package/package.json +1 -1
- 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/{hotplug/libusb.cc → hotplug.cc} +2 -3
- package/src/{hotplug/hotplug.h → hotplug.h} +2 -6
- package/src/node_usb.cc +3 -3
- package/test/usb.coffee +4 -4
- package/test/webusb.coffee +22 -12
- package/src/hotplug/windows.cc +0 -168
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
<ClCompile Include="..\libusb\os\events_windows.c" />
|
|
31
31
|
<ClCompile Include="..\libusb\hotplug.c" />
|
|
32
32
|
<ClCompile Include="..\libusb\io.c" />
|
|
33
|
+
<ClCompile Condition="'$(EnableWindowsHotplug)' == 'true'" Include="..\libusb\os\windows_hotplug.c" />
|
|
33
34
|
<ClCompile Include="..\libusb\strerror.c" />
|
|
34
35
|
<ClCompile Include="..\libusb\sync.c" />
|
|
35
36
|
<ClCompile Include="..\libusb\os\threads_windows.c" />
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
<ClCompile Include="..\libusb\os\windows_winusb.c" />
|
|
39
40
|
</ItemGroup>
|
|
40
41
|
<ItemGroup>
|
|
42
|
+
<ClInclude Condition="'$(EnableWindowsHotplug)' == 'true'" Include="..\libusb\os\windows_hotplug.h" />
|
|
41
43
|
<ClInclude Include=".\config.h" />
|
|
42
44
|
<ClInclude Include="..\libusb\os\events_windows.h" />
|
|
43
45
|
<ClInclude Include="..\libusb\libusb.h" />
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
<ClCompile Include="..\libusb\os\events_windows.c" />
|
|
25
25
|
<ClCompile Include="..\libusb\hotplug.c" />
|
|
26
26
|
<ClCompile Include="..\libusb\io.c" />
|
|
27
|
+
<ClCompile Condition="'$(EnableWindowsHotplug)' == 'true'" Include="..\libusb\os\windows_hotplug.c" />
|
|
27
28
|
<ClCompile Include="..\libusb\strerror.c" />
|
|
28
29
|
<ClCompile Include="..\libusb\sync.c" />
|
|
29
30
|
<ClCompile Include="..\libusb\os\threads_windows.c" />
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
<ClCompile Include="..\libusb\os\windows_winusb.c" />
|
|
33
34
|
</ItemGroup>
|
|
34
35
|
<ItemGroup>
|
|
36
|
+
<ClInclude Condition="'$(EnableWindowsHotplug)' == 'true'" Include="..\libusb\os\windows_hotplug.h" />
|
|
35
37
|
<ClInclude Include=".\config.h" />
|
|
36
38
|
<ClInclude Include="..\libusb\os\events_windows.h" />
|
|
37
39
|
<ClInclude Include="..\libusb\libusb.h" />
|
package/libusb/msvc/xusb.vcxproj
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<ItemDefinitionGroup>
|
|
18
18
|
<ClCompile>
|
|
19
19
|
<!--VS2013 complains about while(0)-->
|
|
20
|
-
<DisableSpecificWarnings Condition="'$(
|
|
20
|
+
<DisableSpecificWarnings Condition="'$(LibusbPlatformToolsetVersion)'<='120'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
21
21
|
</ClCompile>
|
|
22
22
|
</ItemDefinitionGroup>
|
|
23
23
|
<ItemGroup>
|
package/libusb/tests/Makefile.am
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
AM_CPPFLAGS = -I$(top_srcdir)/libusb
|
|
2
2
|
LDADD = ../libusb/libusb-1.0.la
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
if OS_HAIKU
|
|
5
|
+
# Haiku backend includes C++ objects and some toolchains do not ship
|
|
6
|
+
# static libstdc++. Keep tests dynamically linked to avoid static link failures.
|
|
7
|
+
test_static_link_flag =
|
|
8
|
+
else
|
|
9
|
+
test_static_link_flag = -static
|
|
10
|
+
endif
|
|
11
|
+
|
|
12
|
+
AM_LDFLAGS = $(test_static_link_flag)
|
|
4
13
|
|
|
5
14
|
stress_SOURCES = stress.c testlib.c
|
|
6
15
|
stress_mt_SOURCES = stress_mt.c
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#include <stdint.h>
|
|
2
|
+
#include <stddef.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
#include <libusb.h>
|
|
6
|
+
|
|
7
|
+
/* Fuzz the public BOS device-capability parsers.
|
|
8
|
+
We construct a valid BOS dev-cap header (3 bytes) + variable payload.
|
|
9
|
+
No hardware needed; ctx=NULL is fine. */
|
|
10
|
+
|
|
11
|
+
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|
12
|
+
if (!data) return 0;
|
|
13
|
+
|
|
14
|
+
/* bLength is 3 (header) + payload; must fit in one byte. */
|
|
15
|
+
uint8_t payload_len = (size > 252) ? 252 : (uint8_t)size; /* 255 - 3 = 252 */
|
|
16
|
+
size_t total_len = 3u + (size_t)payload_len;
|
|
17
|
+
|
|
18
|
+
/* Allocate header + payload for the flexible array member. */
|
|
19
|
+
struct libusb_bos_dev_capability_descriptor *devcap =
|
|
20
|
+
(struct libusb_bos_dev_capability_descriptor*)
|
|
21
|
+
malloc(sizeof(*devcap) + payload_len);
|
|
22
|
+
if (!devcap) return 0;
|
|
23
|
+
|
|
24
|
+
devcap->bLength = (uint8_t)total_len;
|
|
25
|
+
devcap->bDescriptorType = LIBUSB_DT_DEVICE_CAPABILITY; /* 0x10 */
|
|
26
|
+
/* Copy fuzz bytes into the variable-length payload. */
|
|
27
|
+
if (payload_len) memcpy(devcap->dev_capability_data, data, payload_len);
|
|
28
|
+
|
|
29
|
+
/* 1) USB 2.0 Extension dev-cap */
|
|
30
|
+
devcap->bDevCapabilityType = LIBUSB_BT_USB_2_0_EXTENSION;
|
|
31
|
+
struct libusb_usb_2_0_extension_descriptor *d20 = NULL;
|
|
32
|
+
(void)libusb_get_usb_2_0_extension_descriptor(NULL, devcap, &d20);
|
|
33
|
+
libusb_free_usb_2_0_extension_descriptor(d20);
|
|
34
|
+
|
|
35
|
+
/* 2) SuperSpeed USB Device Capability dev-cap */
|
|
36
|
+
devcap->bDevCapabilityType = LIBUSB_BT_SS_USB_DEVICE_CAPABILITY;
|
|
37
|
+
struct libusb_ss_usb_device_capability_descriptor *dss = NULL;
|
|
38
|
+
(void)libusb_get_ss_usb_device_capability_descriptor(NULL, devcap, &dss);
|
|
39
|
+
libusb_free_ss_usb_device_capability_descriptor(dss);
|
|
40
|
+
|
|
41
|
+
/* 3) Container ID dev-cap */
|
|
42
|
+
devcap->bDevCapabilityType = LIBUSB_BT_CONTAINER_ID;
|
|
43
|
+
struct libusb_container_id_descriptor *dcid = NULL;
|
|
44
|
+
(void)libusb_get_container_id_descriptor(NULL, devcap, &dcid);
|
|
45
|
+
libusb_free_container_id_descriptor(dcid);
|
|
46
|
+
|
|
47
|
+
free(devcap);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* Fuzz the static descriptor parsers in libusb/descriptor.c.
|
|
2
|
+
*
|
|
3
|
+
* The relevant entry points (parse_configuration, parse_interface,
|
|
4
|
+
* parse_endpoint, parse_iad_array) all have file-local linkage, so we
|
|
5
|
+
* compile them into this fuzzer's translation unit by including the source
|
|
6
|
+
* file directly. The libusb_get_*() public APIs that wrap them require a
|
|
7
|
+
* libusb_device with a backend, which is more setup than a fuzz target
|
|
8
|
+
* needs. The unity-include keeps the fuzzer focused on parser logic only.
|
|
9
|
+
*
|
|
10
|
+
* Three small symbol stubs satisfy references that descriptor.c makes into
|
|
11
|
+
* other libusb translation units; none of those code paths are reachable
|
|
12
|
+
* from the parsers we exercise here.
|
|
13
|
+
*
|
|
14
|
+
* Built as part of the OSS-Fuzz integration; not exercised by the autotools
|
|
15
|
+
* test suite.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include <stdint.h>
|
|
19
|
+
#include <stddef.h>
|
|
20
|
+
#include <stdlib.h>
|
|
21
|
+
#include <string.h>
|
|
22
|
+
|
|
23
|
+
/* ENABLE_LOGGING affects only printf-like macros we don't care about. */
|
|
24
|
+
#define ENABLE_LOGGING 0
|
|
25
|
+
|
|
26
|
+
#include "config.h"
|
|
27
|
+
#include "libusbi.h"
|
|
28
|
+
#include "../../libusb/descriptor.c"
|
|
29
|
+
|
|
30
|
+
/* Stubs for symbols that descriptor.c references but the parsers we fuzz
|
|
31
|
+
* never reach (logging sink, backend dispatch, control-transfer wrapper). */
|
|
32
|
+
const struct usbi_os_backend usbi_backend = {0};
|
|
33
|
+
void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
|
|
34
|
+
const char *function, const char *format, ...) {
|
|
35
|
+
(void)ctx; (void)level; (void)function; (void)format;
|
|
36
|
+
}
|
|
37
|
+
int libusb_control_transfer(libusb_device_handle *dev_handle,
|
|
38
|
+
uint8_t bmRequestType, uint8_t bRequest,
|
|
39
|
+
uint16_t wValue, uint16_t wIndex,
|
|
40
|
+
unsigned char *data, uint16_t wLength,
|
|
41
|
+
unsigned int timeout) {
|
|
42
|
+
(void)dev_handle; (void)bmRequestType; (void)bRequest; (void)wValue;
|
|
43
|
+
(void)wIndex; (void)data; (void)wLength; (void)timeout;
|
|
44
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|
48
|
+
/* The limit of 8192 is comfortably above practical cases and
|
|
49
|
+
* still keeping libFuzzer iterations fast and the corpus small */
|
|
50
|
+
if (size < LIBUSB_DT_CONFIG_SIZE || size > 8192)
|
|
51
|
+
return 0;
|
|
52
|
+
|
|
53
|
+
/* Every call gets a fresh exact-size copy so any byte read past the
|
|
54
|
+
* end is caught by ASan. The fuzzer must not observe state between
|
|
55
|
+
* iterations. */
|
|
56
|
+
uint8_t *buf;
|
|
57
|
+
|
|
58
|
+
/* (1) parse_configuration -> parse_interface -> parse_endpoint */
|
|
59
|
+
buf = malloc(size);
|
|
60
|
+
if (!buf) return 0;
|
|
61
|
+
memcpy(buf, data, size);
|
|
62
|
+
{
|
|
63
|
+
struct libusb_config_descriptor cfg;
|
|
64
|
+
memset(&cfg, 0, sizeof(cfg));
|
|
65
|
+
if (parse_configuration(NULL, &cfg, buf, (int)size) >= 0)
|
|
66
|
+
clear_configuration(&cfg);
|
|
67
|
+
}
|
|
68
|
+
free(buf);
|
|
69
|
+
|
|
70
|
+
/* (2) parse_iad_array */
|
|
71
|
+
buf = malloc(size);
|
|
72
|
+
if (!buf) return 0;
|
|
73
|
+
memcpy(buf, data, size);
|
|
74
|
+
{
|
|
75
|
+
struct libusb_interface_association_descriptor_array iad;
|
|
76
|
+
memset(&iad, 0, sizeof(iad));
|
|
77
|
+
if (parse_iad_array(NULL, &iad, buf, (int)size) == LIBUSB_SUCCESS)
|
|
78
|
+
free((void *)iad.iad);
|
|
79
|
+
}
|
|
80
|
+
free(buf);
|
|
81
|
+
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
package/libusb/tests/stress_mt.c
CHANGED
|
@@ -230,7 +230,8 @@ static int test_multi_init(int enumerate)
|
|
|
230
230
|
tinfo[t].number,
|
|
231
231
|
tinfo[t].iteration,
|
|
232
232
|
libusb_error_name(tinfo[t].err));
|
|
233
|
-
}
|
|
233
|
+
}
|
|
234
|
+
if (enumerate) {
|
|
234
235
|
if (t > 0 && tinfo[t].devcount != last_devcount) {
|
|
235
236
|
devcount_mismatch++;
|
|
236
237
|
printf("Device count mismatch: Thread %d discovered %ld devices instead of %ld\n",
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
const { WebUSB } = require('usb');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
// Node.js 21 introduced a global `navigator` object, so assign an empty one only if it's not present yet.
|
|
9
|
+
globalThis.navigator ??= {};
|
|
10
|
+
|
|
11
|
+
navigator.usb = new WebUSB({
|
|
12
|
+
allowAllDevices: true
|
|
13
|
+
});
|
package/libusb.gypi
CHANGED
|
@@ -129,6 +129,8 @@
|
|
|
129
129
|
'libusb/libusb/os/threads_windows.h',
|
|
130
130
|
'libusb/libusb/os/windows_common.c',
|
|
131
131
|
'libusb/libusb/os/windows_common.h',
|
|
132
|
+
'libusb/libusb/os/windows_hotplug.c',
|
|
133
|
+
'libusb/libusb/os/windows_hotplug.h',
|
|
132
134
|
'libusb/libusb/os/windows_usbdk.c',
|
|
133
135
|
'libusb/libusb/os/windows_usbdk.h',
|
|
134
136
|
'libusb/libusb/os/windows_winusb.c',
|
|
@@ -141,6 +143,9 @@
|
|
|
141
143
|
'include_dirs': [
|
|
142
144
|
'libusb/msvc',
|
|
143
145
|
],
|
|
146
|
+
'defines': [
|
|
147
|
+
'LIBUSB_WINDOWS_HOTPLUG=1',
|
|
148
|
+
],
|
|
144
149
|
'msvs_disabled_warnings': [ 4267 ],
|
|
145
150
|
'msvs_settings': {
|
|
146
151
|
'VCCLCompilerTool': {
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -14,10 +14,9 @@ int LIBUSB_CALL hotplug_callback(libusb_context* ctx, libusb_device* device, lib
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
class HotPlugManagerLibUsb: public HotPlugManager {
|
|
17
|
-
|
|
17
|
+
bool supportedHotplugEvents() {
|
|
18
18
|
int res = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
|
|
19
|
-
|
|
20
|
-
return res > 0 ? HOTPLUG_SUPPORTS_DEVICES : HOTPLUG_SUPPORTS_NONE;
|
|
19
|
+
return res > 0;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
void enableHotplug(const Napi::Env& env, ModuleData* instanceData) {
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
#ifndef _USB_HOTPLUG_H
|
|
2
2
|
#define _USB_HOTPLUG_H
|
|
3
3
|
|
|
4
|
-
#include "
|
|
5
|
-
|
|
6
|
-
#define HOTPLUG_SUPPORTS_NONE 0
|
|
7
|
-
#define HOTPLUG_SUPPORTS_DEVICES 1
|
|
8
|
-
#define HOTPLUG_SUPPORTS_IDS 2
|
|
4
|
+
#include "node_usb.h"
|
|
9
5
|
|
|
10
6
|
class HotPlugManager {
|
|
11
7
|
public:
|
|
12
8
|
static std::unique_ptr<HotPlugManager> create();
|
|
13
9
|
|
|
14
|
-
virtual
|
|
10
|
+
virtual bool supportedHotplugEvents() = 0;
|
|
15
11
|
|
|
16
12
|
virtual void enableHotplug(const Napi::Env& env, ModuleData* instanceData) = 0;
|
|
17
13
|
virtual void disableHotplug(const Napi::Env& env, ModuleData* instanceData) = 0;
|
package/src/node_usb.cc
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#include "node_usb.h"
|
|
2
2
|
#include "thread_name.h"
|
|
3
|
-
#include "hotplug
|
|
3
|
+
#include "hotplug.h"
|
|
4
4
|
|
|
5
5
|
Napi::Value SetDebugLevel(const Napi::CallbackInfo& info);
|
|
6
6
|
Napi::Value UseUsbDkBackend(const Napi::CallbackInfo& info);
|
|
@@ -130,8 +130,8 @@ Napi::Value SupportedHotplugEvents(const Napi::CallbackInfo& info) {
|
|
|
130
130
|
Napi::HandleScope scope(env);
|
|
131
131
|
ModuleData* instanceData = env.GetInstanceData<ModuleData>();
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
return Napi::
|
|
133
|
+
bool res = instanceData->hotplugManager->supportedHotplugEvents();
|
|
134
|
+
return Napi::Boolean::New(env, res);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
Napi::Value EnableHotplugEvents(const Napi::CallbackInfo& info) {
|
package/test/usb.coffee
CHANGED
|
@@ -164,8 +164,8 @@ describe 'Device', ->
|
|
|
164
164
|
done()
|
|
165
165
|
|
|
166
166
|
it 'times out', (done) ->
|
|
167
|
-
iface.endpoints[
|
|
168
|
-
iface.endpoints[
|
|
167
|
+
iface.endpoints[4].timeout = 20
|
|
168
|
+
iface.endpoints[4].transfer 64, (e, d) ->
|
|
169
169
|
assert.equal e.errno, usb.LIBUSB_TRANSFER_TIMED_OUT
|
|
170
170
|
done()
|
|
171
171
|
|
|
@@ -228,8 +228,8 @@ describe 'Device', ->
|
|
|
228
228
|
done()
|
|
229
229
|
|
|
230
230
|
it 'times out', (done) ->
|
|
231
|
-
iface.endpoints[
|
|
232
|
-
iface.endpoints[
|
|
231
|
+
iface.endpoints[5].timeout = 20
|
|
232
|
+
iface.endpoints[5].transfer [1,2,3,4], (e) ->
|
|
233
233
|
assert.equal e.errno, usb.LIBUSB_TRANSFER_TIMED_OUT
|
|
234
234
|
done()
|
|
235
235
|
|
package/test/webusb.coffee
CHANGED
|
@@ -182,7 +182,8 @@ describe 'Throwing Transfers', ->
|
|
|
182
182
|
|
|
183
183
|
describe 'Transfers', ->
|
|
184
184
|
device = null
|
|
185
|
-
|
|
185
|
+
b1 = Uint8Array.from([0x30...0x40]).buffer
|
|
186
|
+
b2 = Uint8Array.from([0x32...0x42]).buffer
|
|
186
187
|
|
|
187
188
|
before ->
|
|
188
189
|
device = await webusb.requestDevice({ filters: [{ vendorId: 0x59e3 }] });
|
|
@@ -191,37 +192,46 @@ describe 'Transfers', ->
|
|
|
191
192
|
|
|
192
193
|
it 'should control transfer OUT', ->
|
|
193
194
|
transferResult = await device.controlTransferOut({
|
|
194
|
-
requestType: '
|
|
195
|
-
recipient: '
|
|
195
|
+
requestType: 'vendor',
|
|
196
|
+
recipient: 'device',
|
|
196
197
|
request: 0x81,
|
|
197
198
|
value: 0,
|
|
198
199
|
index: 0
|
|
199
|
-
},
|
|
200
|
+
}, b1)
|
|
200
201
|
|
|
201
202
|
assert.equal(transferResult.status, 'ok')
|
|
202
|
-
assert.equal(transferResult.bytesWritten,
|
|
203
|
+
assert.equal(transferResult.bytesWritten, b1.byteLength)
|
|
203
204
|
|
|
204
205
|
it 'should control transfer IN', ->
|
|
205
206
|
transferResult = await device.controlTransferIn({
|
|
206
|
-
requestType: '
|
|
207
|
-
recipient: '
|
|
207
|
+
requestType: 'vendor',
|
|
208
|
+
recipient: 'device',
|
|
208
209
|
request: 0x81,
|
|
209
210
|
value: 0,
|
|
210
211
|
index: 0
|
|
211
212
|
}, 128)
|
|
212
213
|
|
|
213
214
|
assert.equal(transferResult.status, 'ok')
|
|
214
|
-
assert.equal(transferResult.data.
|
|
215
|
+
assert.equal(transferResult.data.byteLength, b1.byteLength)
|
|
216
|
+
resultBuffer = Buffer.from(transferResult.data.buffer, transferResult.data.byteOffset, transferResult.data.byteLength);
|
|
217
|
+
expectedBuffer = Buffer.from(b1, 0, b1.byteLength);
|
|
218
|
+
assert(resultBuffer.equals(expectedBuffer));
|
|
215
219
|
|
|
216
220
|
it 'should transfer OUT', ->
|
|
217
|
-
transferResult = await device.transferOut(
|
|
221
|
+
transferResult = await device.transferOut(4, b2)
|
|
222
|
+
|
|
218
223
|
assert.equal(transferResult.status, 'ok')
|
|
219
|
-
assert.equal(transferResult.bytesWritten,
|
|
224
|
+
assert.equal(transferResult.bytesWritten, b2.byteLength)
|
|
220
225
|
|
|
221
226
|
it 'should transfer IN', ->
|
|
222
|
-
transferResult = await device.transferIn(
|
|
227
|
+
transferResult = await device.transferIn(3, b2.byteLength)
|
|
228
|
+
|
|
223
229
|
assert.equal(transferResult.status, 'ok')
|
|
224
|
-
assert.equal(transferResult.data.byteLength,
|
|
230
|
+
assert.equal(transferResult.data.byteLength, b2.byteLength)
|
|
225
231
|
|
|
232
|
+
resultBuffer = Buffer.from(transferResult.data.buffer, transferResult.data.byteOffset, transferResult.data.byteLength);
|
|
233
|
+
expectedBuffer = Buffer.from(b2, 0, b2.byteLength);
|
|
234
|
+
assert(resultBuffer.equals(expectedBuffer));
|
|
235
|
+
|
|
226
236
|
after ->
|
|
227
237
|
device.close()
|
package/src/hotplug/windows.cc
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
#include "hotplug.h"
|
|
2
|
-
|
|
3
|
-
// Include Windows headers
|
|
4
|
-
#include <windows.h>
|
|
5
|
-
#include <initguid.h>
|
|
6
|
-
#include <Cfgmgr32.h>
|
|
7
|
-
#include <usbiodef.h>
|
|
8
|
-
|
|
9
|
-
#include <locale>
|
|
10
|
-
#include <codecvt>
|
|
11
|
-
#include <cwctype>
|
|
12
|
-
|
|
13
|
-
#define VID_TAG L"VID_"
|
|
14
|
-
#define PID_TAG L"PID_"
|
|
15
|
-
|
|
16
|
-
struct HotPlug {
|
|
17
|
-
int vid;
|
|
18
|
-
int pid;
|
|
19
|
-
CM_NOTIFY_ACTION event;
|
|
20
|
-
Napi::ObjectReference* hotplugThis;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
void extractVidPid(wchar_t *buf, int *vid, int *pid)
|
|
24
|
-
{
|
|
25
|
-
// Example input: \\?\USB#VID_0FD9&PID_0060#000000000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
|
|
26
|
-
|
|
27
|
-
*vid = 0;
|
|
28
|
-
*pid = 0;
|
|
29
|
-
|
|
30
|
-
if (buf == NULL)
|
|
31
|
-
{
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
auto string = std::wstring(buf);
|
|
36
|
-
std::transform(string.begin(), string.end(), string.begin(), std::towupper);
|
|
37
|
-
|
|
38
|
-
wchar_t* temp = new wchar_t[5];
|
|
39
|
-
temp[4] = L'\0';
|
|
40
|
-
|
|
41
|
-
const wchar_t *vidStr = wcsstr(string.data(), VID_TAG);
|
|
42
|
-
const wchar_t *pidStr = wcsstr(string.data(), PID_TAG);
|
|
43
|
-
|
|
44
|
-
if (vidStr != nullptr)
|
|
45
|
-
{
|
|
46
|
-
memcpy(temp, vidStr + wcslen(VID_TAG), 4 * sizeof(wchar_t));
|
|
47
|
-
*vid = wcstol(temp, NULL, 16);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (pidStr != nullptr)
|
|
51
|
-
{
|
|
52
|
-
memcpy(temp, pidStr + wcslen(PID_TAG), 4 * sizeof(wchar_t));
|
|
53
|
-
*pid = wcstol(temp, NULL, 16);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
DWORD WINAPI MyCMInterfaceNotification(HCMNOTIFICATION hNotify, PVOID Context, CM_NOTIFY_ACTION Action, PCM_NOTIFY_EVENT_DATA EventData, DWORD EventDataSize)
|
|
58
|
-
{
|
|
59
|
-
switch (Action)
|
|
60
|
-
{
|
|
61
|
-
case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL:
|
|
62
|
-
case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL:
|
|
63
|
-
{
|
|
64
|
-
ModuleData* instanceData = (ModuleData*)Context;
|
|
65
|
-
|
|
66
|
-
int vid = 0;
|
|
67
|
-
int pid = 0;
|
|
68
|
-
extractVidPid(EventData->u.DeviceInterface.SymbolicLink, &vid, &pid);
|
|
69
|
-
|
|
70
|
-
instanceData->hotplugQueue.post(new HotPlug {vid, pid, Action, &instanceData->hotplugThis});
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
default:
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
return ERROR_SUCCESS;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
class HotPlugManagerWindows : public HotPlugManager
|
|
80
|
-
{
|
|
81
|
-
public:
|
|
82
|
-
HotPlugManagerWindows()
|
|
83
|
-
: hcm(nullptr)
|
|
84
|
-
{
|
|
85
|
-
cmNotifyFilter = { 0 };
|
|
86
|
-
cmNotifyFilter.cbSize = sizeof(cmNotifyFilter);
|
|
87
|
-
cmNotifyFilter.Flags = 0;
|
|
88
|
-
cmNotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
|
|
89
|
-
cmNotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_USB_DEVICE;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
int supportedHotplugEvents()
|
|
93
|
-
{
|
|
94
|
-
return HOTPLUG_SUPPORTS_IDS;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
void enableHotplug(const Napi::Env &env, ModuleData *instanceData)
|
|
98
|
-
{
|
|
99
|
-
if (isRunning)
|
|
100
|
-
{
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
isRunning = true;
|
|
105
|
-
|
|
106
|
-
auto res = CM_Register_Notification(&cmNotifyFilter, (PVOID)instanceData, (PCM_NOTIFY_CALLBACK)&MyCMInterfaceNotification, &hcm);
|
|
107
|
-
if (res != CR_SUCCESS)
|
|
108
|
-
{
|
|
109
|
-
isRunning = false;
|
|
110
|
-
THROW_ERROR("RegisterNotification failed")
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
void disableHotplug(const Napi::Env &env, ModuleData *instanceData)
|
|
115
|
-
{
|
|
116
|
-
if (isRunning)
|
|
117
|
-
{
|
|
118
|
-
isRunning = false;
|
|
119
|
-
|
|
120
|
-
if (hcm) {
|
|
121
|
-
CM_Unregister_Notification(hcm);
|
|
122
|
-
hcm = nullptr;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private:
|
|
128
|
-
std::atomic<bool> isRunning = {false};
|
|
129
|
-
HCMNOTIFICATION hcm;
|
|
130
|
-
CM_NOTIFY_FILTER cmNotifyFilter;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
std::unique_ptr<HotPlugManager> HotPlugManager::create()
|
|
134
|
-
{
|
|
135
|
-
return std::make_unique<HotPlugManagerWindows>();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
void handleHotplug(HotPlug* info) {
|
|
139
|
-
Napi::ObjectReference* hotplugThis = info->hotplugThis;
|
|
140
|
-
Napi::Env env = hotplugThis->Env();
|
|
141
|
-
Napi::HandleScope scope(env);
|
|
142
|
-
|
|
143
|
-
int vid = info->vid;
|
|
144
|
-
int pid = info->pid;
|
|
145
|
-
Napi::Object v8VidPid = Napi::Object::New(env);
|
|
146
|
-
v8VidPid.Set("idVendor", Napi::Number::New(env, vid));
|
|
147
|
-
v8VidPid.Set("idProduct", Napi::Number::New(env, pid));
|
|
148
|
-
CM_NOTIFY_ACTION event = info->event;
|
|
149
|
-
delete info;
|
|
150
|
-
|
|
151
|
-
DEBUG_LOG("HandleHotplug %i %i %i", vid, pid, event);
|
|
152
|
-
|
|
153
|
-
Napi::String eventName;
|
|
154
|
-
if (CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL == event) {
|
|
155
|
-
DEBUG_LOG("Device arrived");
|
|
156
|
-
eventName = Napi::String::New(env, "attachIds");
|
|
157
|
-
|
|
158
|
-
} else if (CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL == event) {
|
|
159
|
-
DEBUG_LOG("Device left");
|
|
160
|
-
eventName = Napi::String::New(env, "detachIds");
|
|
161
|
-
|
|
162
|
-
} else {
|
|
163
|
-
DEBUG_LOG("Unhandled hotplug event %d\n", event);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
hotplugThis->Get("emit").As<Napi::Function>().MakeCallback(hotplugThis->Value(), { eventName, v8VidPid });
|
|
168
|
-
}
|