usb 1.8.1-libusb.4 → 1.9.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 ADDED
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ ## [1.9.0] - 2021-11-08
4
+
5
+ ### Changed
6
+ - Changed libusb dependency to upstream v1.0.23 - [`453`](https://github.com/node-usb/node-usb/pull/453) ([Rob Moran](https://github.com/thegecko))
7
+
8
+ ## [1.8.1] - 2021-11-08
9
+
10
+ ### Added
11
+ - Added functionality to ref/unref the hotplug events - [`455`](https://github.com/node-usb/node-usb/pull/455) ([Guilherme Francescon](https://github.com/gfcittolin))
12
+ - Added CHANGELOG - [`454`](https://github.com/node-usb/node-usb/pull/454) ([Rob Moran](https://github.com/thegecko))
13
+
14
+ ### Fixed
15
+ - Fixed delay when exiting program - [`455`](https://github.com/node-usb/node-usb/pull/455) ([Rob Moran](https://github.com/thegecko))
16
+
17
+ ## [1.8.0] - 2021-10-14
18
+
19
+ ### Added
20
+ - Added prebuildify and GitHub action for native binaries - [`450`](https://github.com/node-usb/node-usb/pull/450) ([Rob Moran](https://github.com/thegecko))
21
+
22
+ ### Fixed
23
+ - Fixed crash after wake on Windows when using Electron - [`451`](https://github.com/node-usb/node-usb/pull/451) ([Rob Moran](https://github.com/thegecko))
24
+ - Fixed invalid initial refs - [`445`](https://github.com/node-usb/node-usb/pull/445) ([Alba Mendez](https://github.com/mildsunrise))
25
+
26
+ ### Changed
27
+ - Changed GitHub organisation to [node-usb](https://github.com/node-usb) - [`447`](https://github.com/node-usb/node-usb/pull/447) ([Rob Moran](https://github.com/thegecko))
28
+
29
+ ## [1.7.2] - 2021-08-30
30
+
31
+ ### Fixed
32
+ - Fixed crash when exiting on MacOS with Electron 9 - [`440`](https://github.com/node-usb/node-usb/pull/440) ([Daniel Main](https://github.com/danielmain))
33
+
34
+ ### Changed
35
+ - **Breaking:** Changed minimum Node.js version to `10` - [`428`](https://github.com/node-usb/node-usb/pull/428) ([Rob Moran](https://github.com/thegecko))
36
+
37
+ ## [1.7.1] - 2021-05-08
38
+
39
+ ### Fixed
40
+ - Fixed compiler warnings - [`419`](https://github.com/node-usb/node-usb/pull/419) ([Joel Purra](https://github.com/joelpurra))
41
+
42
+ ## [1.7.0] - 2021-04-10
43
+
44
+ ### Changed
45
+ - Changed native support to use Node Addon API - [`399`](https://github.com/node-usb/node-usb/pull/399) ([Georg Vienna](https://github.com/geovie))
46
+
47
+ ## [1.6.5] - 2021-02-14
48
+
49
+ ### Changed
50
+ - Changed prebuild for Electron 12 beta to nightly - [`410`](https://github.com/node-usb/node-usb/pull/410) ([Piotr Rogowski](https://github.com/karniv00l))
51
+
52
+ ### Removed
53
+ - Removed `portNumbers` test on arm64 - [`408`](https://github.com/node-usb/node-usb/pull/408) ([Rob Moran](https://github.com/thegecko))
54
+
55
+ ## [1.6.4] - 2021-01-30
56
+
57
+ ### Added
58
+ - Added prebuild for Electron 10 and 12 beta - [`407`](https://github.com/node-usb/node-usb/pull/407) ([Rob Moran](https://github.com/thegecko))
59
+ - Added prebuild for Electron 9 - [`362`](https://github.com/node-usb/node-usb/pull/362) (Luke Whyte)
60
+
61
+ ### Changed
62
+ - Changed to GitHub Actions for prebuild workflow - [`404`](https://github.com/node-usb/node-usb/pull/404) ([Rob Moran](https://github.com/thegecko))
63
+ - Changed Node.js 13 prebuild target to Node.js 14 - [`374`](https://github.com/node-usb/node-usb/pull/374) ([Micah Zoltu](https://github.com/MicahZoltu))
@@ -304,6 +304,12 @@ Attaches a callback to plugging in a `device`.
304
304
  ### usb.on('detach', function(device) { ... });
305
305
  Attaches a callback to unplugging a `device`.
306
306
 
307
+ ### usb.refHotplugEvents();
308
+ Restore (re-reference) the hotplug events unreferenced by `unrefHotplugEvents()`
309
+
310
+ ### usb.unrefHotplugEvents();
311
+ Listening to events will prevent the process to exit. By calling this function, hotplug events will be unreferenced by the event loop, allowing the process to exit even when listening for the `attach` and `detach` events.
312
+
307
313
 
308
314
  Development and testing
309
315
  =======================
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "usb",
3
3
  "description": "Library to access USB devices",
4
- "version": "1.8.1-libusb.4",
4
+ "version": "1.9.0",
5
5
  "engines": {
6
6
  "node": ">=10.16.0"
7
7
  },
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "devDependencies": {
57
57
  "coffeescript": "~2.4.1",
58
- "mocha": "^8.3.2",
58
+ "mocha": "^9.1.3",
59
59
  "node-gyp": "^7.1.2",
60
60
  "prebuildify": "^4.2.1",
61
61
  "prebuildify-ci": "^1.0.5",
Binary file
Binary file
Binary file
package/src/device.cc CHANGED
@@ -21,6 +21,8 @@ Device::Device(const Napi::CallbackInfo & info) : Napi::ObjectWrap<Device>(info)
21
21
  byPtr.insert(std::make_pair(device, this));
22
22
  #ifndef USE_POLL
23
23
  completionQueue.start(info.Env());
24
+ // Unref threadsafe function immediately to avoid delay in program exit
25
+ completionQueue.unref(info.Env());
24
26
  #endif
25
27
  DEBUG_LOG("Created device %p", this);
26
28
  Constructor(info);
@@ -28,9 +30,6 @@ Device::Device(const Napi::CallbackInfo & info) : Napi::ObjectWrap<Device>(info)
28
30
 
29
31
  Device::~Device(){
30
32
  DEBUG_LOG("Freed device %p", this);
31
- #ifndef USE_POLL
32
- completionQueue.stop();
33
- #endif
34
33
  byPtr.erase(device);
35
34
  libusb_close(device_handle);
36
35
  libusb_unref_device(device);
package/src/node_usb.cc CHANGED
@@ -4,8 +4,11 @@
4
4
 
5
5
  Napi::Value SetDebugLevel(const Napi::CallbackInfo& info);
6
6
  Napi::Value GetDeviceList(const Napi::CallbackInfo& info);
7
+ Napi::Value GetLibusbCapability(const Napi::CallbackInfo& info);
7
8
  Napi::Value EnableHotplugEvents(const Napi::CallbackInfo& info);
8
9
  Napi::Value DisableHotplugEvents(const Napi::CallbackInfo& info);
10
+ Napi::Value RefHotplugEvents(const Napi::CallbackInfo& info);
11
+ Napi::Value UnrefHotplugEvents(const Napi::CallbackInfo& info);
9
12
  void initConstants(Napi::Object target);
10
13
 
11
14
  libusb_context* usb_context;
@@ -16,6 +19,7 @@ struct HotPlug {
16
19
 
17
20
  #ifdef USE_POLL
18
21
  #include <poll.h>
22
+ #include <uv.h>
19
23
  #include <sys/time.h>
20
24
 
21
25
  std::map<int, uv_poll_t*> pollByFD;
@@ -94,8 +98,11 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
94
98
 
95
99
  exports.Set("setDebugLevel", Napi::Function::New(env, SetDebugLevel));
96
100
  exports.Set("getDeviceList", Napi::Function::New(env, GetDeviceList));
101
+ exports.Set("_getLibusbCapability", Napi::Function::New(env, GetLibusbCapability));
97
102
  exports.Set("_enableHotplugEvents", Napi::Function::New(env, EnableHotplugEvents));
98
103
  exports.Set("_disableHotplugEvents", Napi::Function::New(env, DisableHotplugEvents));
104
+ exports.Set("refHotplugEvents", Napi::Function::New(env, RefHotplugEvents));
105
+ exports.Set("unrefHotplugEvents", Napi::Function::New(env, UnrefHotplugEvents));
99
106
  return exports;
100
107
  }
101
108
 
@@ -128,6 +135,17 @@ Napi::Value GetDeviceList(const Napi::CallbackInfo& info) {
128
135
  return arr;
129
136
  }
130
137
 
138
+ Napi::Value GetLibusbCapability(const Napi::CallbackInfo& info) {
139
+ Napi::Env env = info.Env();
140
+
141
+ if (info.Length() != 1 || !info[0].IsNumber()) {
142
+ THROW_BAD_ARGS("Usb::GetLibusbCapability argument is invalid!")
143
+ }
144
+
145
+ int res = libusb_has_capability(info[0].As<Napi::Number>().Int32Value());
146
+ return Napi::Number::New(env, res);
147
+ }
148
+
131
149
  Napi::ObjectReference hotplugThis;
132
150
 
133
151
  void handleHotplug(HotPlug* info){
@@ -199,10 +217,27 @@ Napi::Value DisableHotplugEvents(const Napi::CallbackInfo& info) {
199
217
  return env.Undefined();
200
218
  }
201
219
 
220
+ Napi::Value RefHotplugEvents(const Napi::CallbackInfo& info) {
221
+ Napi::Env env = info.Env();
222
+ Napi::HandleScope scope(env);
223
+ if (hotplugEnabled) {
224
+ hotplugQueue.ref(env);
225
+ }
226
+ return env.Undefined();
227
+ }
228
+
229
+ Napi::Value UnrefHotplugEvents(const Napi::CallbackInfo& info) {
230
+ Napi::Env env = info.Env();
231
+ Napi::HandleScope scope(env);
232
+ if (hotplugEnabled) {
233
+ hotplugQueue.unref(env);
234
+ }
235
+ return env.Undefined();
236
+ }
237
+
202
238
  #define DEFINE_CONSTANT(OBJ, VALUE) \
203
239
  OBJ.DefineProperty(Napi::PropertyDescriptor::Value(#VALUE, Napi::Number::New(OBJ.Env(), VALUE), static_cast<napi_property_attributes>(napi_enumerable | napi_configurable)));
204
240
 
205
-
206
241
  void initConstants(Napi::Object target){
207
242
  DEFINE_CONSTANT(target, LIBUSB_CLASS_PER_INTERFACE);
208
243
  DEFINE_CONSTANT(target, LIBUSB_CLASS_AUDIO);
@@ -282,6 +317,12 @@ void initConstants(Napi::Object target){
282
317
  DEFINE_CONSTANT(target, LIBUSB_CONTROL_SETUP_SIZE);
283
318
  DEFINE_CONSTANT(target, LIBUSB_DT_BOS_SIZE);
284
319
 
320
+ // libusb_capability
321
+ DEFINE_CONSTANT(target, LIBUSB_CAP_HAS_CAPABILITY);
322
+ DEFINE_CONSTANT(target, LIBUSB_CAP_HAS_HOTPLUG);
323
+ DEFINE_CONSTANT(target, LIBUSB_CAP_HAS_HID_ACCESS);
324
+ DEFINE_CONSTANT(target, LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
325
+
285
326
  // libusb_error
286
327
  // Input/output error
287
328
  DEFINE_CONSTANT(target, LIBUSB_ERROR_IO);
@@ -3,31 +3,39 @@
3
3
 
4
4
  template <class T>
5
5
  class UVQueue{
6
- public:
7
- typedef void (*fptr)(T);
8
-
9
- Napi::ThreadSafeFunction tsfn;
10
-
11
- UVQueue(fptr cb): callback(cb) {}
12
-
13
- void start(Napi::Env env) {
14
- Napi::Function empty_func = Napi::Function::New(env, [](const Napi::CallbackInfo& cb) {});
15
- tsfn = Napi::ThreadSafeFunction::New(env, empty_func, "libusb", 0, 1);
16
- }
17
-
18
- void stop() {
19
- tsfn.Release();
20
- }
21
-
22
- void post(T value){
23
- auto cb = callback;
24
- tsfn.BlockingCall( value, [cb](Napi::Env _env, Napi::Function _jsCallback, T val) {
25
- cb(val);
26
- });
27
- }
28
-
29
- private:
30
- fptr callback;
6
+ public:
7
+ typedef void (*fptr)(T);
8
+
9
+ Napi::ThreadSafeFunction tsfn;
10
+
11
+ UVQueue(fptr cb): callback(cb) {}
12
+
13
+ void start(Napi::Env env) {
14
+ Napi::Function empty_func = Napi::Function::New(env, [](const Napi::CallbackInfo& cb) {});
15
+ tsfn = Napi::ThreadSafeFunction::New(env, empty_func, "libusb", 0, 1);
16
+ }
17
+
18
+ void stop() {
19
+ tsfn.Release();
20
+ }
21
+
22
+ void ref(Napi::Env env) {
23
+ tsfn.Ref(env);
24
+ }
25
+
26
+ void unref(Napi::Env env) {
27
+ tsfn.Unref(env);
28
+ }
29
+
30
+ void post(T value){
31
+ auto cb = callback;
32
+ tsfn.BlockingCall( value, [cb](Napi::Env _env, Napi::Function _jsCallback, T val) {
33
+ cb(val);
34
+ });
35
+ }
36
+
37
+ private:
38
+ fptr callback;
31
39
  };
32
40
 
33
41
  #endif
package/usb.js CHANGED
@@ -1,9 +1,6 @@
1
1
  var usb = exports = module.exports = require('node-gyp-build')(__dirname);
2
2
  var events = require('events');
3
3
  var util = require('util');
4
- var os = require('os');
5
-
6
- var isWindows = os.platform() === 'win32';
7
4
 
8
5
  var isBuffer = function(obj) {
9
6
  return obj && obj instanceof Uint8Array
@@ -17,6 +14,8 @@ if (usb.INIT_ERROR) {
17
14
  usb.getDeviceList = function () { return []; };
18
15
  usb._enableHotplugEvents = function () { };
19
16
  usb._disableHotplugEvents = function () { };
17
+ usb.refHotplugEvents = function () { };
18
+ usb.unrefHotplugEvents = function () { };
20
19
  }
21
20
 
22
21
  Object.keys(events.EventEmitter.prototype).forEach(function (key) {
@@ -511,35 +510,16 @@ OutEndpoint.prototype.transferWithZLP = function (buf, cb) {
511
510
  }
512
511
  }
513
512
 
514
- var hotplugListeners = 0;
515
- exports.on('newListener', function(name) {
516
- if (name !== 'attach' && name !== 'detach') return;
517
- if (++hotplugListeners === 1) {
518
- if (isWindows) {
519
- exports._pollHotplug(true);
520
- } else {
521
- usb._enableHotplugEvents();
522
- }
523
- }
524
- });
525
-
526
- exports.on('removeListener', function(name) {
527
- if (name !== 'attach' && name !== 'detach') return;
528
- if (--hotplugListeners === 0) {
529
- if (isWindows) {
530
- exports._pollingHotplug = false;
531
- } else {
532
- usb._disableHotplugEvents();
533
- }
534
- }
535
- });
536
-
537
513
  // Polling mechanism for discovering device changes until this is fixed:
538
514
  // https://github.com/libusb/libusb/issues/86
539
- exports._pollHotplug = function(start) {
515
+ exports._pollTimeout = 500;
516
+ var hotplugSupported = usb._getLibusbCapability(usb.LIBUSB_CAP_HAS_HOTPLUG) > 0;
517
+ var pollingHotplug = false;
518
+ var pollDevices = [];
519
+ function pollHotplug(start) {
540
520
  if (start) {
541
- exports._pollingHotplug = true;
542
- } else if (!exports._pollingHotplug) {
521
+ pollingHotplug = true;
522
+ } else if (!pollingHotplug) {
543
523
  return;
544
524
  }
545
525
 
@@ -548,14 +528,14 @@ exports._pollHotplug = function(start) {
548
528
  if (!start) {
549
529
  // Find attached devices
550
530
  for (var device of devices) {
551
- var found = exports._windowsDevices.find(item => item.deviceAddress === device.deviceAddress);
531
+ var found = pollDevices.find(item => item.deviceAddress === device.deviceAddress);
552
532
  if (!found) {
553
533
  usb.emit('attach', device);
554
534
  }
555
535
  }
556
536
 
557
537
  // Find detached devices
558
- for (var device of exports._windowsDevices) {
538
+ for (var device of pollDevices) {
559
539
  var found = devices.find(item => item.deviceAddress === device.deviceAddress);
560
540
  if (!found) {
561
541
  usb.emit('detach', device);
@@ -563,8 +543,31 @@ exports._pollHotplug = function(start) {
563
543
  }
564
544
  }
565
545
 
566
- exports._windowsDevices = devices;
546
+ pollDevices = devices;
567
547
  setTimeout(() => {
568
- exports._pollHotplug();
569
- }, 500);
548
+ pollHotplug();
549
+ }, exports._pollTimeout);
570
550
  }
551
+
552
+ var hotplugListeners = 0;
553
+ exports.on('newListener', function(name) {
554
+ if (name !== 'attach' && name !== 'detach') return;
555
+ if (++hotplugListeners === 1) {
556
+ if (hotplugSupported) {
557
+ usb._enableHotplugEvents();
558
+ } else {
559
+ pollHotplug(true);
560
+ }
561
+ }
562
+ });
563
+
564
+ exports.on('removeListener', function(name) {
565
+ if (name !== 'attach' && name !== 'detach') return;
566
+ if (--hotplugListeners === 0) {
567
+ if (hotplugSupported) {
568
+ usb._disableHotplugEvents();
569
+ } else {
570
+ pollingHotplug = false;
571
+ }
572
+ }
573
+ });