usb 2.5.0 → 2.5.1
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 +8 -2
- package/dist/usb/index.d.ts +6 -2
- package/dist/usb/index.js +75 -58
- package/dist/usb/index.js.map +1 -1
- package/package.json +4 -5
- 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-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/hotplug/libusb.cc +4 -5
- package/src/hotplug/windows.cc +4 -3
- package/tsc/usb/index.ts +65 -42
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.5.1] - 2022-08-29
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- USB device plug/unplug detection on Windows when devce already attached - [`531`](https://github.com/node-usb/node-usb/pull/531) ([Rob Moran](https://github.com/thegecko))
|
|
7
|
+
- Removed dependency on yarn in package.json scripts - [`535`](https://github.com/node-usb/node-usb/pull/535) ([Rob Moran](https://github.com/thegecko))
|
|
8
|
+
|
|
3
9
|
## [2.5.0] - 2022-07-30
|
|
4
10
|
|
|
5
11
|
### Fixed
|
package/README.md
CHANGED
|
@@ -594,11 +594,17 @@ git submodule update --init
|
|
|
594
594
|
```
|
|
595
595
|
|
|
596
596
|
## Building
|
|
597
|
-
The package uses `
|
|
597
|
+
The package uses `prebuildify` to generate the native binaries using an `install` script and `TypeScript` for the binding code using the `compile` script. The package can be built as follows:
|
|
598
598
|
|
|
599
599
|
```bash
|
|
600
600
|
yarn
|
|
601
|
-
yarn
|
|
601
|
+
yarn compile
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
The native binaries can be rebuilt with:
|
|
605
|
+
|
|
606
|
+
```bash
|
|
607
|
+
yarn rebuild
|
|
602
608
|
```
|
|
603
609
|
|
|
604
610
|
__Note:__ On Linux, you'll need libudev to build libusb. On Ubuntu/Debian:
|
package/dist/usb/index.d.ts
CHANGED
|
@@ -4,14 +4,18 @@ interface EventListeners<T> {
|
|
|
4
4
|
newListener: keyof T;
|
|
5
5
|
removeListener: keyof T;
|
|
6
6
|
}
|
|
7
|
+
interface DeviceIds {
|
|
8
|
+
idVendor: number;
|
|
9
|
+
idProduct: number;
|
|
10
|
+
}
|
|
7
11
|
declare module './bindings' {
|
|
8
12
|
interface Device extends ExtendedDevice {
|
|
9
13
|
}
|
|
10
14
|
interface DeviceEvents extends EventListeners<DeviceEvents> {
|
|
11
15
|
attach: Device;
|
|
12
16
|
detach: Device;
|
|
13
|
-
attachIds:
|
|
14
|
-
detachIds:
|
|
17
|
+
attachIds: DeviceIds;
|
|
18
|
+
detachIds: DeviceIds;
|
|
15
19
|
}
|
|
16
20
|
function addListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
|
|
17
21
|
function removeListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
|
package/dist/usb/index.js
CHANGED
|
@@ -21,50 +21,52 @@ Object.setPrototypeOf(usb, events_1.EventEmitter.prototype);
|
|
|
21
21
|
Object.getOwnPropertyNames(device_1.ExtendedDevice.prototype).forEach(function (name) {
|
|
22
22
|
Object.defineProperty(usb.Device.prototype, name, Object.getOwnPropertyDescriptor(device_1.ExtendedDevice.prototype, name) || Object.create(null));
|
|
23
23
|
});
|
|
24
|
-
//
|
|
25
|
-
var pollTimeout = 500;
|
|
24
|
+
// Hotplug support
|
|
26
25
|
var hotplugSupported = usb._supportedHotplugEvents();
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
var
|
|
26
|
+
// Devices delta support for non-libusb hotplug events
|
|
27
|
+
// This methd needs to be used for attach/detach IDs (hotplugSupportType === 2) rather than a lookup because vid/pid are not unique
|
|
28
|
+
var hotPlugDevices = new Set();
|
|
29
|
+
var emitHotplugEvents = function () {
|
|
30
30
|
var e_1, _a, e_2, _b;
|
|
31
31
|
// Collect current devices
|
|
32
32
|
var devices = new Set(usb.getDeviceList());
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
usb.emit('attach', device);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
43
|
-
finally {
|
|
44
|
-
try {
|
|
45
|
-
if (devices_1_1 && !devices_1_1.done && (_a = devices_1.return)) _a.call(devices_1);
|
|
33
|
+
try {
|
|
34
|
+
// Find attached devices
|
|
35
|
+
for (var devices_1 = __values(devices), devices_1_1 = devices_1.next(); !devices_1_1.done; devices_1_1 = devices_1.next()) {
|
|
36
|
+
var device = devices_1_1.value;
|
|
37
|
+
if (!hotPlugDevices.has(device)) {
|
|
38
|
+
usb.emit('attach', device);
|
|
46
39
|
}
|
|
47
|
-
finally { if (e_1) throw e_1.error; }
|
|
48
40
|
}
|
|
41
|
+
}
|
|
42
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
43
|
+
finally {
|
|
49
44
|
try {
|
|
50
|
-
|
|
51
|
-
for (var pollDevices_1 = __values(pollDevices), pollDevices_1_1 = pollDevices_1.next(); !pollDevices_1_1.done; pollDevices_1_1 = pollDevices_1.next()) {
|
|
52
|
-
var device = pollDevices_1_1.value;
|
|
53
|
-
if (!devices.has(device))
|
|
54
|
-
usb.emit('detach', device);
|
|
55
|
-
}
|
|
45
|
+
if (devices_1_1 && !devices_1_1.done && (_a = devices_1.return)) _a.call(devices_1);
|
|
56
46
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
finally { if (e_1) throw e_1.error; }
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
// Find detached devices
|
|
51
|
+
for (var hotPlugDevices_1 = __values(hotPlugDevices), hotPlugDevices_1_1 = hotPlugDevices_1.next(); !hotPlugDevices_1_1.done; hotPlugDevices_1_1 = hotPlugDevices_1.next()) {
|
|
52
|
+
var device = hotPlugDevices_1_1.value;
|
|
53
|
+
if (!devices.has(device)) {
|
|
54
|
+
usb.emit('detach', device);
|
|
61
55
|
}
|
|
62
|
-
finally { if (e_2) throw e_2.error; }
|
|
63
56
|
}
|
|
64
57
|
}
|
|
65
|
-
|
|
58
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
59
|
+
finally {
|
|
60
|
+
try {
|
|
61
|
+
if (hotPlugDevices_1_1 && !hotPlugDevices_1_1.done && (_b = hotPlugDevices_1.return)) _b.call(hotPlugDevices_1);
|
|
62
|
+
}
|
|
63
|
+
finally { if (e_2) throw e_2.error; }
|
|
64
|
+
}
|
|
65
|
+
hotPlugDevices = devices;
|
|
66
66
|
};
|
|
67
|
-
|
|
67
|
+
// Polling mechanism for checking device changes where hotplug detection is not available
|
|
68
|
+
var pollingHotplug = false;
|
|
69
|
+
var pollHotplug = function (start) {
|
|
68
70
|
if (start === void 0) { start = false; }
|
|
69
71
|
if (start) {
|
|
70
72
|
pollingHotplug = true;
|
|
@@ -72,33 +74,53 @@ var pollHotplugLoop = function (start) {
|
|
|
72
74
|
else if (!pollingHotplug) {
|
|
73
75
|
return;
|
|
74
76
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
},
|
|
77
|
+
else {
|
|
78
|
+
emitHotplugEvents();
|
|
79
|
+
}
|
|
80
|
+
setTimeout(function () { return pollHotplug(); }, 500);
|
|
81
|
+
};
|
|
82
|
+
// Hotplug control
|
|
83
|
+
var startHotplug = function () {
|
|
84
|
+
if (hotplugSupported !== 1) {
|
|
85
|
+
// Collect initial devices when not using libusb
|
|
86
|
+
hotPlugDevices = new Set(usb.getDeviceList());
|
|
87
|
+
}
|
|
88
|
+
if (hotplugSupported) {
|
|
89
|
+
// Use hotplug event emitters
|
|
90
|
+
usb._enableHotplugEvents();
|
|
91
|
+
if (hotplugSupported === 2) {
|
|
92
|
+
// Use hotplug ID events to trigger a change check
|
|
93
|
+
usb.on('attachIds', emitHotplugEvents);
|
|
94
|
+
usb.on('detachIds', emitHotplugEvents);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// Fallback to using polling to check for changes
|
|
99
|
+
pollHotplug(true);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var stopHotplug = function () {
|
|
103
|
+
if (hotplugSupported) {
|
|
104
|
+
// Disable hotplug events
|
|
105
|
+
usb._disableHotplugEvents();
|
|
106
|
+
if (hotplugSupported === 2) {
|
|
107
|
+
// Remove hotplug ID event listeners
|
|
108
|
+
usb.off('attachIds', emitHotplugEvents);
|
|
109
|
+
usb.off('detachIds', emitHotplugEvents);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Stop polling
|
|
114
|
+
pollingHotplug = false;
|
|
115
|
+
}
|
|
79
116
|
};
|
|
80
|
-
var hotplugModeIsIdsOnly = hotplugSupported === 2;
|
|
81
|
-
if (hotplugModeIsIdsOnly) {
|
|
82
|
-
// The hotplug backend doesnt emit 'attach' or 'detach', so we need to do some conversion
|
|
83
|
-
var hotplugEventConversion = function () {
|
|
84
|
-
// Future: This might want a debounce, to avoid doing multiple polls when attaching a usb hub or something
|
|
85
|
-
pollHotplugOnce(false);
|
|
86
|
-
};
|
|
87
|
-
usb.on('attachIds', hotplugEventConversion);
|
|
88
|
-
usb.on('detachIds', hotplugEventConversion);
|
|
89
|
-
}
|
|
90
117
|
usb.on('newListener', function (event) {
|
|
91
118
|
if (event !== 'attach' && event !== 'detach') {
|
|
92
119
|
return;
|
|
93
120
|
}
|
|
94
121
|
var listenerCount = usb.listenerCount('attach') + usb.listenerCount('detach');
|
|
95
122
|
if (listenerCount === 0) {
|
|
96
|
-
|
|
97
|
-
usb._enableHotplugEvents();
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
pollHotplugLoop(true);
|
|
101
|
-
}
|
|
123
|
+
startHotplug();
|
|
102
124
|
}
|
|
103
125
|
});
|
|
104
126
|
usb.on('removeListener', function (event) {
|
|
@@ -107,12 +129,7 @@ usb.on('removeListener', function (event) {
|
|
|
107
129
|
}
|
|
108
130
|
var listenerCount = usb.listenerCount('attach') + usb.listenerCount('detach');
|
|
109
131
|
if (listenerCount === 0) {
|
|
110
|
-
|
|
111
|
-
usb._disableHotplugEvents();
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
pollingHotplug = false;
|
|
115
|
-
}
|
|
132
|
+
stopHotplug();
|
|
116
133
|
}
|
|
117
134
|
});
|
|
118
135
|
module.exports = usb;
|
package/dist/usb/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../tsc/usb/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iCAAsC;AACtC,mCAA0C;AAC1C,gCAAkC;AAElC,IAAI,GAAG,CAAC,UAAU,EAAE;IAChB,+BAA+B;IAC/B,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;CAChD;AAED,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,qBAAY,CAAC,SAAS,CAAC,CAAC;AAEnD,MAAM,CAAC,mBAAmB,CAAC,uBAAc,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,UAAA,IAAI;IAC7D,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,wBAAwB,CAAC,uBAAc,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9I,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../tsc/usb/index.ts"],"names":[],"mappings":"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"}
|
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.5.
|
|
5
|
+
"version": "2.5.1",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=10.20.0 <11.x || >=12.17.0 <13.0 || >=14.0.0"
|
|
@@ -36,12 +36,11 @@
|
|
|
36
36
|
"hardware"
|
|
37
37
|
],
|
|
38
38
|
"scripts": {
|
|
39
|
-
"prepare": "yarn compile",
|
|
40
39
|
"install": "node-gyp-build",
|
|
41
40
|
"rebuild": "node-gyp rebuild",
|
|
42
|
-
"clean": "git clean -
|
|
43
|
-
"compile": "tsc
|
|
44
|
-
"
|
|
41
|
+
"clean": "git clean -fx ./build ./prebuilds ./dist ./docs ./node_modules",
|
|
42
|
+
"compile": "tsc",
|
|
43
|
+
"postcompile": "eslint . --ext .ts",
|
|
45
44
|
"watch": "tsc -w --preserveWatchOutput",
|
|
46
45
|
"test": "mocha --require coffeescript/register --grep Module test/*",
|
|
47
46
|
"full-test": "mocha --require coffeescript/register test/*.coffee",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/hotplug/libusb.cc
CHANGED
|
@@ -61,12 +61,11 @@ void handleHotplug(HotPlug* info) {
|
|
|
61
61
|
Napi::Object v8dev = Device::get(env, dev);
|
|
62
62
|
libusb_unref_device(dev);
|
|
63
63
|
|
|
64
|
-
Napi::
|
|
65
|
-
Napi::Value v8Pid = env.Null();
|
|
64
|
+
Napi::Object v8VidPid = Napi::Object::New(env);
|
|
66
65
|
auto deviceDescriptor = v8dev.Get("deviceDescriptor");
|
|
67
66
|
if (deviceDescriptor.IsObject()) {
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
v8VidPid.Set("idVendor", deviceDescriptor.As<Napi::Object>().Get("idVendor"));
|
|
68
|
+
v8VidPid.Set("idProduct", deviceDescriptor.As<Napi::Object>().Get("idProduct"));
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
Napi::String eventName;
|
|
@@ -87,5 +86,5 @@ void handleHotplug(HotPlug* info) {
|
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
hotplugThis->Get("emit").As<Napi::Function>().MakeCallback(hotplugThis->Value(), { eventName, v8dev });
|
|
90
|
-
hotplugThis->Get("emit").As<Napi::Function>().MakeCallback(hotplugThis->Value(), { changeEventName,
|
|
89
|
+
hotplugThis->Get("emit").As<Napi::Function>().MakeCallback(hotplugThis->Value(), { changeEventName, v8VidPid });
|
|
91
90
|
}
|
package/src/hotplug/windows.cc
CHANGED
|
@@ -135,8 +135,9 @@ void handleHotplug(HotPlug* info) {
|
|
|
135
135
|
|
|
136
136
|
int vid = info->vid;
|
|
137
137
|
int pid = info->pid;
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
Napi::Object v8VidPid = Napi::Object::New(env);
|
|
139
|
+
v8VidPid.Set("idVendor", Napi::Number::New(env, vid));
|
|
140
|
+
v8VidPid.Set("idProduct", Napi::Number::New(env, pid));
|
|
140
141
|
CM_NOTIFY_ACTION event = info->event;
|
|
141
142
|
delete info;
|
|
142
143
|
|
|
@@ -156,5 +157,5 @@ void handleHotplug(HotPlug* info) {
|
|
|
156
157
|
return;
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
hotplugThis->Get("emit").As<Napi::Function>().MakeCallback(hotplugThis->Value(), { eventName,
|
|
160
|
+
hotplugThis->Get("emit").As<Napi::Function>().MakeCallback(hotplugThis->Value(), { eventName, v8VidPid });
|
|
160
161
|
}
|
package/tsc/usb/index.ts
CHANGED
|
@@ -18,6 +18,11 @@ interface EventListeners<T> {
|
|
|
18
18
|
removeListener: keyof T;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
interface DeviceIds {
|
|
22
|
+
idVendor: number;
|
|
23
|
+
idProduct: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
declare module './bindings' {
|
|
22
27
|
|
|
23
28
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
@@ -26,8 +31,8 @@ declare module './bindings' {
|
|
|
26
31
|
interface DeviceEvents extends EventListeners<DeviceEvents> {
|
|
27
32
|
attach: Device;
|
|
28
33
|
detach: Device;
|
|
29
|
-
attachIds:
|
|
30
|
-
detachIds:
|
|
34
|
+
attachIds: DeviceIds;
|
|
35
|
+
detachIds: DeviceIds;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
function addListener<K extends keyof DeviceEvents>(event: K, listener: (arg: DeviceEvents[K]) => void): void;
|
|
@@ -42,58 +47,84 @@ declare module './bindings' {
|
|
|
42
47
|
function listenerCount<K extends keyof DeviceEvents>(event: K): number;
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
//
|
|
46
|
-
const pollTimeout = 500;
|
|
50
|
+
// Hotplug support
|
|
47
51
|
const hotplugSupported = usb._supportedHotplugEvents();
|
|
48
|
-
let pollingHotplug = false;
|
|
49
|
-
let pollDevices = new Set<usb.Device>();
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
// Devices delta support for non-libusb hotplug events
|
|
54
|
+
// This methd needs to be used for attach/detach IDs (hotplugSupportType === 2) rather than a lookup because vid/pid are not unique
|
|
55
|
+
let hotPlugDevices = new Set<usb.Device>();
|
|
56
|
+
const emitHotplugEvents = () => {
|
|
52
57
|
// Collect current devices
|
|
53
58
|
const devices = new Set(usb.getDeviceList());
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
usb.emit('attach', device);
|
|
60
|
+
// Find attached devices
|
|
61
|
+
for (const device of devices) {
|
|
62
|
+
if (!hotPlugDevices.has(device)) {
|
|
63
|
+
usb.emit('attach', device);
|
|
60
64
|
}
|
|
65
|
+
}
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
// Find detached devices
|
|
68
|
+
for (const device of hotPlugDevices) {
|
|
69
|
+
if (!devices.has(device)) {
|
|
70
|
+
usb.emit('detach', device);
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
hotPlugDevices = devices;
|
|
70
75
|
};
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
// Polling mechanism for checking device changes where hotplug detection is not available
|
|
78
|
+
let pollingHotplug = false;
|
|
79
|
+
const pollHotplug = (start = false) => {
|
|
73
80
|
if (start) {
|
|
74
81
|
pollingHotplug = true;
|
|
75
82
|
} else if (!pollingHotplug) {
|
|
76
83
|
return;
|
|
84
|
+
} else {
|
|
85
|
+
emitHotplugEvents();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
setTimeout(() => pollHotplug(), 500);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Hotplug control
|
|
92
|
+
const startHotplug = () => {
|
|
93
|
+
if (hotplugSupported !== 1) {
|
|
94
|
+
// Collect initial devices when not using libusb
|
|
95
|
+
hotPlugDevices = new Set(usb.getDeviceList());
|
|
77
96
|
}
|
|
78
97
|
|
|
79
|
-
|
|
98
|
+
if (hotplugSupported) {
|
|
99
|
+
// Use hotplug event emitters
|
|
100
|
+
usb._enableHotplugEvents();
|
|
80
101
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
102
|
+
if (hotplugSupported === 2) {
|
|
103
|
+
// Use hotplug ID events to trigger a change check
|
|
104
|
+
usb.on('attachIds', emitHotplugEvents);
|
|
105
|
+
usb.on('detachIds', emitHotplugEvents);
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
// Fallback to using polling to check for changes
|
|
109
|
+
pollHotplug(true);
|
|
110
|
+
}
|
|
84
111
|
};
|
|
85
112
|
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// Future: This might want a debounce, to avoid doing multiple polls when attaching a usb hub or something
|
|
91
|
-
pollHotplugOnce(false);
|
|
92
|
-
};
|
|
113
|
+
const stopHotplug = () => {
|
|
114
|
+
if (hotplugSupported) {
|
|
115
|
+
// Disable hotplug events
|
|
116
|
+
usb._disableHotplugEvents();
|
|
93
117
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
118
|
+
if (hotplugSupported === 2) {
|
|
119
|
+
// Remove hotplug ID event listeners
|
|
120
|
+
usb.off('attachIds', emitHotplugEvents);
|
|
121
|
+
usb.off('detachIds', emitHotplugEvents);
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
// Stop polling
|
|
125
|
+
pollingHotplug = false;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
97
128
|
|
|
98
129
|
usb.on('newListener', event => {
|
|
99
130
|
if (event !== 'attach' && event !== 'detach') {
|
|
@@ -101,11 +132,7 @@ usb.on('newListener', event => {
|
|
|
101
132
|
}
|
|
102
133
|
const listenerCount = usb.listenerCount('attach') + usb.listenerCount('detach');
|
|
103
134
|
if (listenerCount === 0) {
|
|
104
|
-
|
|
105
|
-
usb._enableHotplugEvents();
|
|
106
|
-
} else {
|
|
107
|
-
pollHotplugLoop(true);
|
|
108
|
-
}
|
|
135
|
+
startHotplug();
|
|
109
136
|
}
|
|
110
137
|
});
|
|
111
138
|
|
|
@@ -115,11 +142,7 @@ usb.on('removeListener', event => {
|
|
|
115
142
|
}
|
|
116
143
|
const listenerCount = usb.listenerCount('attach') + usb.listenerCount('detach');
|
|
117
144
|
if (listenerCount === 0) {
|
|
118
|
-
|
|
119
|
-
usb._disableHotplugEvents();
|
|
120
|
-
} else {
|
|
121
|
-
pollingHotplug = false;
|
|
122
|
-
}
|
|
145
|
+
stopHotplug();
|
|
123
146
|
}
|
|
124
147
|
});
|
|
125
148
|
|