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.
Files changed (94) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +14 -0
  3. package/binding.gyp +2 -9
  4. package/dist/usb/bindings.d.ts +27 -2
  5. package/dist/usb/bindings.js.map +1 -1
  6. package/dist/usb/index.d.ts +0 -29
  7. package/dist/usb/index.js +4 -18
  8. package/dist/usb/index.js.map +1 -1
  9. package/libusb/.clang-tidy +5 -3
  10. package/libusb/.private/ci-build.sh +5 -1
  11. package/libusb/AUTHORS +14 -0
  12. package/libusb/ChangeLog +15 -2
  13. package/libusb/README +8 -5
  14. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +4 -0
  15. package/libusb/configure.ac +12 -2
  16. package/libusb/examples/hotplugtest.c +19 -11
  17. package/libusb/examples/listdevs.c +41 -3
  18. package/libusb/examples/xusb.c +6 -1
  19. package/libusb/libusb/Makefile.am +4 -0
  20. package/libusb/libusb/core.c +175 -14
  21. package/libusb/libusb/descriptor.c +163 -14
  22. package/libusb/libusb/io.c +7 -3
  23. package/libusb/libusb/libusb-1.0.def +10 -0
  24. package/libusb/libusb/libusb.h +59 -9
  25. package/libusb/libusb/libusbi.h +89 -25
  26. package/libusb/libusb/os/darwin_usb.c +126 -46
  27. package/libusb/libusb/os/darwin_usb.h +10 -8
  28. package/libusb/libusb/os/emscripten_webusb.cpp +31 -10
  29. package/libusb/libusb/os/haiku_usb_raw.cpp +4 -0
  30. package/libusb/libusb/os/linux_usbfs.c +73 -25
  31. package/libusb/libusb/os/netbsd_usb.c +2 -0
  32. package/libusb/libusb/os/openbsd_usb.c +2 -0
  33. package/libusb/libusb/os/sunos_usb.c +2 -0
  34. package/libusb/libusb/os/threads_posix.c +3 -3
  35. package/libusb/libusb/os/threads_posix.h +8 -2
  36. package/libusb/libusb/os/threads_windows.h +2 -1
  37. package/libusb/libusb/os/windows_common.c +86 -1
  38. package/libusb/libusb/os/windows_common.h +20 -1
  39. package/libusb/libusb/os/windows_hotplug.c +321 -0
  40. package/libusb/libusb/os/windows_hotplug.h +28 -0
  41. package/libusb/libusb/os/windows_usbdk.c +16 -8
  42. package/libusb/libusb/os/windows_winusb.c +753 -41
  43. package/libusb/libusb/os/windows_winusb.h +11 -6
  44. package/libusb/libusb/version.h +1 -1
  45. package/libusb/libusb/version_nano.h +1 -1
  46. package/libusb/msvc/Base.props +1 -1
  47. package/libusb/msvc/Configuration.Base.props +2 -1
  48. package/libusb/msvc/Configuration.DynamicLibrary.props +12 -0
  49. package/libusb/msvc/ProjectConfigurations.Base.props +69 -16
  50. package/libusb/msvc/build_all.ps1 +2 -2
  51. package/libusb/msvc/config.h +4 -0
  52. package/libusb/msvc/getopt/bits/getopt_core.h +96 -0
  53. package/libusb/msvc/getopt/bits/getopt_ext.h +77 -0
  54. package/libusb/msvc/getopt/features.h +21 -0
  55. package/libusb/msvc/getopt/getopt.c +456 -705
  56. package/libusb/msvc/getopt/getopt.h +16 -158
  57. package/libusb/msvc/getopt/getopt1.c +40 -69
  58. package/libusb/msvc/getopt/getopt_int.h +118 -0
  59. package/libusb/msvc/getopt/gettext.h +7 -0
  60. package/libusb/msvc/getopt/unistd.h +5 -0
  61. package/libusb/msvc/getopt.vcxproj +11 -4
  62. package/libusb/msvc/libusb.sln +515 -268
  63. package/libusb/msvc/libusb_dll.vcxproj +2 -0
  64. package/libusb/msvc/libusb_static.vcxproj +2 -0
  65. package/libusb/msvc/xusb.vcxproj +1 -1
  66. package/libusb/tests/Makefile.am +10 -1
  67. package/libusb/tests/fuzz/corpus/bos/min.bos +0 -0
  68. package/libusb/tests/fuzz/corpus/descriptor_parsers/min_valid_config.bin +0 -0
  69. package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_a_endpoint_null.bin +0 -0
  70. package/libusb/tests/fuzz/corpus/descriptor_parsers/regression_bug_b_iad_oob.bin +0 -0
  71. package/libusb/tests/fuzz/fuzz_bos_descriptor.c +49 -0
  72. package/libusb/tests/fuzz/fuzz_descriptor_parsers.c +83 -0
  73. package/libusb/tests/stress_mt.c +2 -1
  74. package/libusb/tests/webusb-test-shim/index.js +6 -5
  75. package/libusb.gypi +5 -0
  76. package/package.json +1 -1
  77. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  78. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  79. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  80. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  81. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  82. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  83. package/prebuilds/linux-ia32/node.napi.node +0 -0
  84. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  85. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  86. package/prebuilds/win32-arm64/node.napi.node +0 -0
  87. package/prebuilds/win32-ia32/node.napi.node +0 -0
  88. package/prebuilds/win32-x64/node.napi.node +0 -0
  89. package/src/{hotplug/libusb.cc → hotplug.cc} +2 -3
  90. package/src/{hotplug/hotplug.h → hotplug.h} +2 -6
  91. package/src/node_usb.cc +3 -3
  92. package/test/usb.coffee +4 -4
  93. package/test/webusb.coffee +22 -12
  94. 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" />
@@ -17,7 +17,7 @@
17
17
  <ItemDefinitionGroup>
18
18
  <ClCompile>
19
19
  <!--VS2013 complains about while(0)-->
20
- <DisableSpecificWarnings Condition="'$(PlatformToolsetVersion)'&lt;='120'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
20
+ <DisableSpecificWarnings Condition="'$(LibusbPlatformToolsetVersion)'&lt;='120'">4127;%(DisableSpecificWarnings)</DisableSpecificWarnings>
21
21
  </ClCompile>
22
22
  </ItemDefinitionGroup>
23
23
  <ItemGroup>
@@ -1,6 +1,15 @@
1
1
  AM_CPPFLAGS = -I$(top_srcdir)/libusb
2
2
  LDADD = ../libusb/libusb-1.0.la
3
- AM_LDFLAGS = -static
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
@@ -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
+ }
@@ -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
- } else if (enumerate) {
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
- globalThis.navigator = {
9
- usb: new WebUSB({
10
- allowAllDevices: true
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
@@ -2,7 +2,7 @@
2
2
  "name": "usb",
3
3
  "description": "Library to access USB devices",
4
4
  "license": "MIT",
5
- "version": "2.17.0",
5
+ "version": "2.18.0",
6
6
  "main": "dist/index.js",
7
7
  "engines": {
8
8
  "node": ">=12.22.0 <13.0 || >=14.17.0"
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
- int supportedHotplugEvents() {
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 "../node_usb.h"
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 int supportedHotplugEvents() = 0;
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/hotplug.h"
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
- int res = instanceData->hotplugManager->supportedHotplugEvents();
134
- return Napi::Number::New(env, res);
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[2].timeout = 20
168
- iface.endpoints[2].transfer 64, (e, d) ->
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[3].timeout = 20
232
- iface.endpoints[3].transfer [1,2,3,4], (e) ->
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
 
@@ -182,7 +182,8 @@ describe 'Throwing Transfers', ->
182
182
 
183
183
  describe 'Transfers', ->
184
184
  device = null
185
- b = Uint8Array.from([0x30...0x40]).buffer
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: 'device',
195
- recipient: 'vendor',
195
+ requestType: 'vendor',
196
+ recipient: 'device',
196
197
  request: 0x81,
197
198
  value: 0,
198
199
  index: 0
199
- }, b)
200
+ }, b1)
200
201
 
201
202
  assert.equal(transferResult.status, 'ok')
202
- assert.equal(transferResult.bytesWritten, b.byteLength)
203
+ assert.equal(transferResult.bytesWritten, b1.byteLength)
203
204
 
204
205
  it 'should control transfer IN', ->
205
206
  transferResult = await device.controlTransferIn({
206
- requestType: 'device',
207
- recipient: 'vendor',
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.buffer.toString(), b.toString())
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(2, b)
221
+ transferResult = await device.transferOut(4, b2)
222
+
218
223
  assert.equal(transferResult.status, 'ok')
219
- assert.equal(transferResult.bytesWritten, b.byteLength)
224
+ assert.equal(transferResult.bytesWritten, b2.byteLength)
220
225
 
221
226
  it 'should transfer IN', ->
222
- transferResult = await device.transferIn(1, 64)
227
+ transferResult = await device.transferIn(3, b2.byteLength)
228
+
223
229
  assert.equal(transferResult.status, 'ok')
224
- assert.equal(transferResult.data.byteLength, 64)
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()
@@ -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
- }