1 | import EventEmitter from "events";
|
2 | import { usb } from "usb";
|
3 | import debounce from "lodash/debounce";
|
4 | import { getDevices } from "@ledgerhq/hw-transport-node-hid-noevents";
|
5 | import { log } from "@ledgerhq/logs";
|
6 | export default (delay, listenDevicesPollingSkip) => {
|
7 | const events = new EventEmitter();
|
8 | events.setMaxListeners(0);
|
9 | let listDevices = getDevices();
|
10 | const flatDevice = d => d.path;
|
11 | const getFlatDevices = () => [...new Set(getDevices().map(d => flatDevice(d)))];
|
12 | const getDeviceByPaths = paths => listDevices.find(d => paths.includes(flatDevice(d)));
|
13 | let lastDevices = getFlatDevices();
|
14 | const poll = () => {
|
15 | if (!listenDevicesPollingSkip()) {
|
16 | log("hid-listen", "Polling for added or removed devices");
|
17 | let changeFound = false;
|
18 | const currentDevices = getFlatDevices();
|
19 | const newDevices = currentDevices.filter(d => !lastDevices.includes(d));
|
20 | if (newDevices.length > 0) {
|
21 | log("hid-listen", "New device found:", newDevices);
|
22 | listDevices = getDevices();
|
23 | events.emit("add", getDeviceByPaths(newDevices));
|
24 | changeFound = true;
|
25 | }
|
26 | else {
|
27 | log("hid-listen", "No new device found");
|
28 | }
|
29 | const removeDevices = lastDevices.filter(d => !currentDevices.includes(d));
|
30 | if (removeDevices.length > 0) {
|
31 | log("hid-listen", "Removed device found:", removeDevices);
|
32 | events.emit("remove", getDeviceByPaths(removeDevices));
|
33 | listDevices = listDevices.filter(d => !removeDevices.includes(flatDevice(d)));
|
34 | changeFound = true;
|
35 | }
|
36 | else {
|
37 | log("hid-listen", "No removed device found");
|
38 | }
|
39 | if (changeFound) {
|
40 | lastDevices = currentDevices;
|
41 | }
|
42 | }
|
43 | else {
|
44 | log("hid-listen", "Polling skipped, re-debouncing");
|
45 | debouncedPoll();
|
46 | }
|
47 | };
|
48 | const debouncedPoll = debounce(poll, delay);
|
49 | const attachDetected = device => {
|
50 | log("hid-listen", "Device add detected:", device);
|
51 | debouncedPoll();
|
52 | };
|
53 | usb.on("attach", attachDetected);
|
54 | log("hid-listen", "attach listener added");
|
55 | const detachDetected = device => {
|
56 | log("hid-listen", "Device removal detected:", device);
|
57 | debouncedPoll();
|
58 | };
|
59 | usb.on("detach", detachDetected);
|
60 | log("hid-listen", "detach listener added");
|
61 | return {
|
62 | stop: () => {
|
63 | log("hid-listen", "Stop received, removing listeners and cancelling pending debounced polls");
|
64 | debouncedPoll.cancel();
|
65 | usb.removeListener("attach", attachDetected);
|
66 | usb.removeListener("detach", detachDetected);
|
67 | },
|
68 | events,
|
69 | };
|
70 | };
|
71 |
|
\ | No newline at end of file |