usb 2.0.0-alpha.2 → 2.1.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 (258) hide show
  1. package/.gitmodules +1 -1
  2. package/CHANGELOG.md +100 -0
  3. package/README.md +573 -0
  4. package/binding.gyp +12 -2
  5. package/dist/index.d.ts +4 -4
  6. package/dist/index.js +14 -8
  7. package/dist/index.js.map +1 -1
  8. package/dist/usb/bindings.d.ts +13 -0
  9. package/dist/usb/bindings.js +2 -1
  10. package/dist/usb/bindings.js.map +1 -1
  11. package/dist/usb/index.js +86 -2
  12. package/dist/usb/index.js.map +1 -1
  13. package/dist/usb/interface.js.map +1 -1
  14. package/dist/webusb/index.d.ts +32 -19
  15. package/dist/webusb/index.js +163 -67
  16. package/dist/webusb/index.js.map +1 -1
  17. package/dist/webusb/webusb-device.d.ts +1 -1
  18. package/dist/webusb/webusb-device.js +27 -15
  19. package/dist/webusb/webusb-device.js.map +1 -1
  20. package/libusb/.private/pre-commit.sh +7 -1
  21. package/libusb/.travis.yml +49 -0
  22. package/libusb/AUTHORS +44 -3
  23. package/libusb/Brewfile +4 -0
  24. package/libusb/ChangeLog +74 -2
  25. package/libusb/README.md +32 -0
  26. package/libusb/TODO +1 -1
  27. package/libusb/Xcode/common.xcconfig +12 -0
  28. package/libusb/Xcode/config.h +25 -0
  29. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
  30. package/libusb/android/README +4 -2
  31. package/libusb/android/config.h +75 -0
  32. package/libusb/appveyor.yml +41 -0
  33. package/libusb/appveyor_cygwin.bat +11 -0
  34. package/libusb/appveyor_minGW.bat +19 -0
  35. package/libusb/autogen.sh +1 -1
  36. package/libusb/bootstrap.sh +3 -16
  37. package/libusb/configure.ac +108 -80
  38. package/libusb/doc/doxygen.cfg.in +1785 -739
  39. package/libusb/examples/Makefile.am +1 -1
  40. package/libusb/examples/dpfp.c +3 -1
  41. package/libusb/examples/dpfp_threaded.c +23 -10
  42. package/libusb/examples/ezusb.c +3 -3
  43. package/libusb/examples/ezusb.h +2 -2
  44. package/libusb/examples/fxload.c +31 -9
  45. package/libusb/examples/hotplugtest.c +35 -7
  46. package/libusb/examples/listdevs.c +3 -1
  47. package/libusb/examples/sam3u_benchmark.c +3 -3
  48. package/libusb/examples/testlibusb.c +277 -0
  49. package/libusb/examples/xusb.c +40 -34
  50. package/libusb/libusb/Makefile.am +49 -23
  51. package/libusb/libusb/core.c +855 -457
  52. package/libusb/libusb/descriptor.c +72 -78
  53. package/libusb/libusb/hotplug.c +122 -76
  54. package/libusb/libusb/hotplug.h +42 -25
  55. package/libusb/libusb/io.c +625 -390
  56. package/libusb/libusb/libusb-1.0.def +12 -0
  57. package/libusb/libusb/libusb.h +218 -150
  58. package/libusb/libusb/libusbi.h +346 -176
  59. package/libusb/libusb/os/darwin_usb.c +604 -319
  60. package/libusb/libusb/os/darwin_usb.h +61 -20
  61. package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
  62. package/libusb/libusb/os/haiku_usb.h +113 -0
  63. package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
  64. package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
  65. package/libusb/libusb/os/haiku_usb_raw.h +188 -0
  66. package/libusb/libusb/os/linux_netlink.c +186 -146
  67. package/libusb/libusb/os/linux_udev.c +36 -14
  68. package/libusb/libusb/os/linux_usbfs.c +426 -225
  69. package/libusb/libusb/os/linux_usbfs.h +5 -3
  70. package/libusb/libusb/os/netbsd_usb.c +21 -77
  71. package/libusb/libusb/os/openbsd_usb.c +32 -115
  72. package/libusb/libusb/os/poll_posix.c +38 -5
  73. package/libusb/libusb/os/poll_posix.h +3 -0
  74. package/libusb/libusb/os/poll_windows.c +277 -626
  75. package/libusb/libusb/os/poll_windows.h +11 -44
  76. package/libusb/libusb/os/sunos_usb.c +1695 -0
  77. package/libusb/libusb/os/sunos_usb.h +80 -0
  78. package/libusb/libusb/os/threads_posix.c +24 -26
  79. package/libusb/libusb/os/threads_posix.h +73 -21
  80. package/libusb/libusb/os/threads_windows.c +71 -157
  81. package/libusb/libusb/os/threads_windows.h +68 -44
  82. package/libusb/libusb/os/wince_usb.c +276 -420
  83. package/libusb/libusb/os/wince_usb.h +23 -28
  84. package/libusb/libusb/os/windows_common.h +78 -58
  85. package/libusb/libusb/os/windows_nt_common.c +1010 -0
  86. package/libusb/libusb/os/windows_nt_common.h +110 -0
  87. package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
  88. package/libusb/libusb/os/windows_usbdk.c +830 -0
  89. package/libusb/libusb/os/windows_usbdk.h +103 -0
  90. package/libusb/libusb/os/windows_winusb.c +4391 -0
  91. package/libusb/libusb/os/windows_winusb.h +783 -0
  92. package/libusb/libusb/strerror.c +41 -7
  93. package/libusb/libusb/sync.c +41 -13
  94. package/libusb/libusb/version.h +1 -1
  95. package/libusb/libusb/version_nano.h +1 -1
  96. package/libusb/libusb-1.0.pc.in +1 -1
  97. package/libusb/msvc/appveyor.bat +27 -0
  98. package/libusb/msvc/config.h +5 -4
  99. package/libusb/msvc/ddk_build.cmd +87 -43
  100. package/libusb/msvc/fxload_2010.vcxproj +24 -104
  101. package/libusb/msvc/fxload_2012.vcxproj +24 -107
  102. package/libusb/msvc/fxload_2013.vcxproj +24 -107
  103. package/libusb/msvc/fxload_2015.vcxproj +91 -0
  104. package/libusb/msvc/fxload_2017.vcxproj +114 -0
  105. package/libusb/msvc/fxload_sources +1 -1
  106. package/libusb/msvc/getopt_2010.vcxproj +16 -75
  107. package/libusb/msvc/getopt_2012.vcxproj +16 -79
  108. package/libusb/msvc/getopt_2013.vcxproj +16 -79
  109. package/libusb/msvc/getopt_2015.vcxproj +73 -0
  110. package/libusb/msvc/getopt_2017.vcxproj +98 -0
  111. package/libusb/msvc/getopt_sources +6 -2
  112. package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
  113. package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
  114. package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
  115. package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
  116. package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
  117. package/libusb/msvc/hotplugtest_sources +1 -1
  118. package/libusb/msvc/libusb_2005.sln +20 -20
  119. package/libusb/msvc/libusb_2010.sln +57 -46
  120. package/libusb/msvc/libusb_2012.sln +57 -46
  121. package/libusb/msvc/libusb_2013.sln +57 -50
  122. package/libusb/msvc/libusb_2015.sln +59 -52
  123. package/libusb/msvc/libusb_2017.sln +186 -0
  124. package/libusb/msvc/libusb_dll.dsp +2 -2
  125. package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
  126. package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
  127. package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
  128. package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
  129. package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
  130. package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
  131. package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
  132. package/libusb/msvc/libusb_sources +10 -5
  133. package/libusb/msvc/libusb_static.dsp +2 -2
  134. package/libusb/msvc/libusb_static_2005.vcproj +32 -4
  135. package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
  136. package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
  137. package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
  138. package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
  139. package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
  140. package/libusb/msvc/libusb_static_wince.vcproj +20 -26
  141. package/libusb/msvc/libusb_wince.sln +88 -88
  142. package/libusb/msvc/listdevs_2010.vcxproj +16 -99
  143. package/libusb/msvc/listdevs_2012.vcxproj +16 -102
  144. package/libusb/msvc/listdevs_2013.vcxproj +16 -102
  145. package/libusb/msvc/listdevs_2015.vcxproj +83 -0
  146. package/libusb/msvc/listdevs_2017.vcxproj +106 -0
  147. package/libusb/msvc/listdevs_sources +2 -1
  148. package/libusb/msvc/stress_2010.vcxproj +20 -101
  149. package/libusb/msvc/stress_2012.vcxproj +20 -104
  150. package/libusb/msvc/stress_2013.vcxproj +20 -104
  151. package/libusb/msvc/stress_2015.vcxproj +87 -0
  152. package/libusb/msvc/stress_2017.vcxproj +110 -0
  153. package/libusb/msvc/stress_sources +21 -0
  154. package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
  155. package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
  156. package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
  157. package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
  158. package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
  159. package/libusb/msvc/testlibusb_sources +20 -0
  160. package/libusb/msvc/xusb_2010.vcxproj +17 -98
  161. package/libusb/msvc/xusb_2012.vcxproj +17 -101
  162. package/libusb/msvc/xusb_2013.vcxproj +17 -101
  163. package/libusb/msvc/xusb_2015.vcxproj +83 -0
  164. package/libusb/msvc/xusb_2017.vcxproj +106 -0
  165. package/libusb/msvc/xusb_sources +1 -1
  166. package/libusb/tests/stress.c +2 -2
  167. package/libusb/tests/testlib.c +0 -4
  168. package/libusb/travis-autogen.sh +39 -0
  169. package/libusb.gypi +21 -2
  170. package/package.json +18 -13
  171. package/prebuilds/android-arm/node.napi.node +0 -0
  172. package/prebuilds/android-arm64/node.napi.node +0 -0
  173. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  174. package/prebuilds/linux-arm/node.napi.node +0 -0
  175. package/prebuilds/linux-arm64/node.napi.node +0 -0
  176. package/prebuilds/linux-ia32/node.napi.node +0 -0
  177. package/prebuilds/linux-x64/node.napi.node +0 -0
  178. package/prebuilds/win32-ia32/node.napi.node +0 -0
  179. package/prebuilds/win32-x64/node.napi.node +0 -0
  180. package/src/device.cc +7 -7
  181. package/src/node_usb.cc +43 -1
  182. package/src/node_usb.h +1 -0
  183. package/src/uv_async_queue.h +33 -25
  184. package/test/usb.coffee +6 -0
  185. package/tsc/index.ts +13 -7
  186. package/tsc/usb/bindings.ts +19 -1
  187. package/tsc/usb/index.ts +67 -19
  188. package/tsc/usb/interface.ts +2 -2
  189. package/tsc/webusb/index.ts +197 -74
  190. package/tsc/webusb/webusb-device.ts +30 -17
  191. package/.github/workflows/prebuild.yml +0 -48
  192. package/Readme.md +0 -339
  193. package/dist/webusb/typed-event-target.d.ts +0 -11
  194. package/dist/webusb/typed-event-target.js +0 -21
  195. package/dist/webusb/typed-event-target.js.map +0 -1
  196. package/docs/assets/css/main.css +0 -2660
  197. package/docs/assets/images/icons.png +0 -0
  198. package/docs/assets/images/icons@2x.png +0 -0
  199. package/docs/assets/images/widgets.png +0 -0
  200. package/docs/assets/images/widgets@2x.png +0 -0
  201. package/docs/assets/js/main.js +0 -248
  202. package/docs/assets/js/search.js +0 -1
  203. package/docs/classes/usb_bindings.device.html +0 -1338
  204. package/docs/classes/usb_bindings.libusbexception.html +0 -234
  205. package/docs/classes/usb_bindings.transfer.html +0 -344
  206. package/docs/classes/usb_capability.capability.html +0 -297
  207. package/docs/classes/usb_device.extendeddevice.html +0 -766
  208. package/docs/classes/usb_endpoint.endpoint.html +0 -472
  209. package/docs/classes/usb_endpoint.inendpoint.html +0 -766
  210. package/docs/classes/usb_endpoint.outendpoint.html +0 -582
  211. package/docs/classes/usb_interface.interface.html +0 -648
  212. package/docs/classes/webusb.webusb-1.html +0 -615
  213. package/docs/classes/webusb_mutex.mutex.html +0 -270
  214. package/docs/classes/webusb_typed_event_target.typedeventtarget.html +0 -443
  215. package/docs/classes/webusb_webusb_device.webusbdevice.html +0 -904
  216. package/docs/index.html +0 -500
  217. package/docs/interfaces/usb.deviceevents.html +0 -242
  218. package/docs/interfaces/usb_descriptors.bosdescriptor.html +0 -293
  219. package/docs/interfaces/usb_descriptors.capabilitydescriptor.html +0 -274
  220. package/docs/interfaces/usb_descriptors.configdescriptor.html +0 -388
  221. package/docs/interfaces/usb_descriptors.devicedescriptor.html +0 -464
  222. package/docs/interfaces/usb_descriptors.endpointdescriptor.html +0 -370
  223. package/docs/interfaces/usb_descriptors.interfacedescriptor.html +0 -407
  224. package/docs/interfaces/webusb.usboptions.html +0 -226
  225. package/docs/modules/index.html +0 -304
  226. package/docs/modules/usb.html +0 -173
  227. package/docs/modules/usb_bindings.html +0 -2248
  228. package/docs/modules/usb_capability.html +0 -156
  229. package/docs/modules/usb_descriptors.html +0 -176
  230. package/docs/modules/usb_device.html +0 -156
  231. package/docs/modules/usb_endpoint.html +0 -164
  232. package/docs/modules/usb_interface.html +0 -156
  233. package/docs/modules/webusb.html +0 -165
  234. package/docs/modules/webusb_mutex.html +0 -156
  235. package/docs/modules/webusb_typed_event_target.html +0 -156
  236. package/docs/modules/webusb_webusb_device.html +0 -156
  237. package/docs/modules.html +0 -156
  238. package/libusb/INSTALL +0 -234
  239. package/libusb/README +0 -28
  240. package/libusb/libusb/os/windows_usb.c +0 -5347
  241. package/libusb/libusb/os/windows_usb.h +0 -971
  242. package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
  243. package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
  244. package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
  245. package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
  246. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
  247. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
  248. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
  249. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
  250. package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
  251. package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
  252. package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
  253. package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
  254. package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
  255. package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
  256. package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
  257. package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
  258. package/tsc/webusb/typed-event-target.ts +0 -23
@@ -1,54 +1,159 @@
1
1
  import * as usb from '../usb';
2
+ import { EventEmitter } from 'events';
2
3
  import { WebUSBDevice } from './webusb-device';
3
- import { TypedEventTarget } from './typed-event-target';
4
4
 
5
5
  /**
6
6
  * USB Options
7
7
  */
8
8
  export interface USBOptions {
9
9
  /**
10
- * A `device found` callback function to allow the user to select a device
10
+ * Optional `device found` callback function to allow the user to select a device
11
11
  */
12
- devicesFound?: (devices: Array<USBDevice>) => Promise<USBDevice | void>;
13
- }
12
+ devicesFound?: (devices: USBDevice[]) => Promise<USBDevice | void>;
14
13
 
15
- /**
16
- * @hidden
17
- */
18
- interface Device {
19
- vendorId?: number;
20
- productId?: number;
21
- serialNumber?: string;
22
- }
14
+ /**
15
+ * Optional array of preconfigured allowed devices
16
+ */
17
+ allowedDevices?: USBDeviceFilter[];
23
18
 
24
- /**
25
- * @hidden
26
- */
27
- export type USBEvents = {
28
19
  /**
29
- * USBDevice connected event
20
+ * Optional flag to automatically allow all devices
30
21
  */
31
- connect: USBConnectionEvent;
22
+ allowAllDevices?: boolean;
23
+
32
24
  /**
33
- * USBDevice disconnected event
25
+ * Optional timeout (in milliseconds) to use for the device control transfers
34
26
  */
35
- disconnect: USBConnectionEvent;
27
+ deviceTimeout?: number;
28
+ }
29
+
30
+ /**
31
+ * Convenience method to get the WebUSB interface available
32
+ */
33
+ export const getWebUsb = (): USB => {
34
+ if (navigator && navigator.usb) {
35
+ return navigator.usb;
36
+ }
37
+
38
+ return new WebUSB();
36
39
  };
37
40
 
38
- export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
41
+ export class WebUSB implements USB {
39
42
 
40
- private allowedDevices: Array<Device> = [];
43
+ protected emitter = new EventEmitter();
44
+ protected knownDevices: Map<string, USBDevice> = new Map();
45
+ protected allowedDevices: USBDeviceFilter[];
41
46
 
42
47
  constructor(private options: USBOptions = {}) {
43
- super();
48
+ this.allowedDevices = options.allowedDevices || [];
49
+
50
+ const deviceConnectCallback = async (device: usb.Device) => {
51
+ const webDevice = await WebUSBDevice.createInstance(device);
52
+
53
+ // When connected, emit an event if it is an allowed device
54
+ if (webDevice && this.isAllowedDevice(webDevice)) {
55
+ const deviceId = this.getDeviceId(device);
56
+ if (deviceId) {
57
+ this.knownDevices.set(deviceId, webDevice);
58
+ }
59
+
60
+ const event = {
61
+ type: 'connect',
62
+ device: webDevice
63
+ };
64
+
65
+ this.emitter.emit('connect', event);
66
+ }
67
+ };
68
+
69
+ const deviceDisconnectCallback = async (device: usb.Device) => {
70
+ const deviceId = this.getDeviceId(device);
71
+
72
+ // When disconnected, emit an event if the device was a known allowed device
73
+ if (deviceId !== undefined && this.knownDevices.has(deviceId)) {
74
+ const webDevice = this.knownDevices.get(deviceId);
75
+
76
+ if (webDevice && this.isAllowedDevice(webDevice)) {
77
+ const event = {
78
+ type: 'disconnect',
79
+ device: webDevice
80
+ };
81
+
82
+ this.emitter.emit('disconnect', event);
83
+ }
84
+ }
85
+ };
86
+
87
+ this.emitter.on('newListener', event => {
88
+ const listenerCount = this.emitter.listenerCount(event);
89
+
90
+ if (listenerCount !== 0) {
91
+ return;
92
+ }
93
+
94
+ if (event === 'connect') {
95
+ usb.addListener('attach', deviceConnectCallback);
96
+ } else if (event === 'disconnect') {
97
+ usb.addListener('detach', deviceDisconnectCallback);
98
+ }
99
+ });
100
+
101
+ this.emitter.on('removeListener', event => {
102
+ const listenerCount = this.emitter.listenerCount(event);
103
+
104
+ if (listenerCount !== 0) {
105
+ return;
106
+ }
107
+
108
+ if (event === 'connect') {
109
+ usb.removeListener('attach', deviceConnectCallback);
110
+ } else if (event === 'disconnect') {
111
+ usb.removeListener('detach', deviceDisconnectCallback);
112
+ }
113
+ });
114
+ }
115
+
116
+ private _onconnect: ((ev: USBConnectionEvent) => void) | undefined;
117
+ public set onconnect(fn: (ev: USBConnectionEvent) => void) {
118
+ if (this._onconnect) {
119
+ this.removeEventListener('connect', this._onconnect);
120
+ this._onconnect = undefined;
121
+ }
122
+
123
+ if (fn) {
124
+ this._onconnect = fn;
125
+ this.addEventListener('connect', this._onconnect);
126
+ }
127
+ }
128
+
129
+ private _ondisconnect: ((ev: USBConnectionEvent) => void) | undefined;
130
+ public set ondisconnect(fn: (ev: USBConnectionEvent) => void) {
131
+ if (this._ondisconnect) {
132
+ this.removeEventListener('disconnect', this._ondisconnect);
133
+ this._ondisconnect = undefined;
134
+ }
135
+
136
+ if (fn) {
137
+ this._ondisconnect = fn;
138
+ this.addEventListener('disconnect', this._ondisconnect);
139
+ }
44
140
  }
45
141
 
46
- public set onconnect(listener: (event: USBConnectionEvent) => void) {
47
- this.addEventListener('connect', listener);
142
+ public addEventListener(type: 'connect' | 'disconnect', listener: (this: this, ev: USBConnectionEvent) => void): void;
143
+ public addEventListener(type: 'connect' | 'disconnect', listener: EventListener): void;
144
+ public addEventListener(type: string, listener: (ev: USBConnectionEvent) => void): void {
145
+ this.emitter.addListener(type, listener);
48
146
  }
49
147
 
50
- public set ondisconnect(listener: (event: USBConnectionEvent) => void) {
51
- this.addEventListener('disconnect', listener);
148
+ public removeEventListener(type: 'connect' | 'disconnect', callback: (this: this, ev: USBConnectionEvent) => void): void;
149
+ public removeEventListener(type: 'connect' | 'disconnect', callback: EventListener): void;
150
+ public removeEventListener(type: string, callback: (this: this, ev: USBConnectionEvent) => void): void {
151
+ this.emitter.removeListener(type, callback);
152
+ }
153
+
154
+ public dispatchEvent(_event: Event): boolean {
155
+ // Don't dispatch from here
156
+ return false;
52
157
  }
53
158
 
54
159
  /**
@@ -105,7 +210,7 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
105
210
  throw new Error('selected device not found');
106
211
  }
107
212
 
108
- if (!this.replaceAllowedDevice(device)) {
213
+ if (!this.isAllowedDevice(device)) {
109
214
  this.allowedDevices.push({
110
215
  vendorId: device.vendorId,
111
216
  productId: device.productId,
@@ -114,7 +219,7 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
114
219
  }
115
220
 
116
221
  return device;
117
- } catch(error) {
222
+ } catch (error) {
118
223
  throw new Error(`requestDevice error: ${error}`);
119
224
  }
120
225
  }
@@ -124,47 +229,54 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
124
229
  * @returns Promise containing an array of devices
125
230
  */
126
231
  public async getDevices(): Promise<USBDevice[]> {
127
- // Create pre-filters
128
- const preFilters = this.allowedDevices.map(device => ({
129
- vendorId: device.vendorId || undefined,
130
- productId: device.productId || undefined,
131
- serialNumber: device.serialNumber || undefined
132
- }));
232
+ let preFilters: USBDeviceFilter[] | undefined;
233
+
234
+ if (!this.options.allowAllDevices) {
235
+ // Create pre-filters
236
+ preFilters = this.allowedDevices.map(device => ({
237
+ vendorId: device.vendorId || undefined,
238
+ productId: device.productId || undefined,
239
+ serialNumber: device.serialNumber || undefined
240
+ }));
241
+ }
133
242
 
134
243
  // Refresh devices and filter for allowed ones
135
- let devices = await this.loadDevices(preFilters);
136
- devices = devices.filter(device => {
137
- for (const i in this.allowedDevices) {
138
- if (this.isSameDevice(device, this.allowedDevices[i])) {
139
- return true;
140
- }
141
- }
142
-
143
- return false;
144
- });
145
-
146
- return devices;
244
+ const devices = await this.loadDevices(preFilters);
245
+ return devices.filter(device => this.isAllowedDevice(device));
147
246
  }
148
247
 
149
- private async loadDevices(preFilters?: Array<Device>): Promise<USBDevice[]> {
248
+ private async loadDevices(preFilters?: USBDeviceFilter[]): Promise<USBDevice[]> {
150
249
  let devices = usb.getDeviceList();
151
250
 
152
- if (preFilters) {
153
- // Pre-filter devices
154
- devices = this.preFilterDevices(devices, preFilters);
155
- }
251
+ // Pre-filter devices
252
+ devices = this.preFilterDevices(devices, preFilters);
156
253
 
157
254
  const webDevices: USBDevice[] = [];
158
255
 
159
256
  for (const device of devices) {
257
+ if (this.options.deviceTimeout) {
258
+ device.timeout = this.options.deviceTimeout;
259
+ }
260
+
160
261
  const webDevice = await WebUSBDevice.createInstance(device);
161
- webDevices.push(webDevice);
262
+ if (webDevice) {
263
+ webDevices.push(webDevice);
264
+
265
+ const deviceId = this.getDeviceId(device);
266
+ if (deviceId) {
267
+ this.knownDevices.set(deviceId, webDevice);
268
+ }
269
+ }
162
270
  }
163
271
 
164
272
  return webDevices;
165
273
  }
166
274
 
167
- private preFilterDevices(devices: Array<usb.Device>, preFilters: Array<Device>): Array<usb.Device> {
275
+ private preFilterDevices(devices: usb.Device[], preFilters?: USBDeviceFilter[]): usb.Device[] {
276
+ if (!preFilters || !preFilters.length) {
277
+ return devices;
278
+ }
279
+
168
280
  // Just pre-filter on vid/pid
169
281
  return devices.filter(device => preFilters.some(filter => {
170
282
  // Vendor
@@ -178,28 +290,11 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
178
290
  }));
179
291
  }
180
292
 
181
- private isSameDevice(device1: Device, device2: Device): boolean {
182
- return (device1.productId === device2.productId
183
- && device1.vendorId === device2.vendorId
184
- && device1.serialNumber === device2.serialNumber);
185
- }
186
-
187
- private replaceAllowedDevice(device: USBDevice): boolean {
188
- for (const i in this.allowedDevices) {
189
- if (this.isSameDevice(device, this.allowedDevices[i])) {
190
- this.allowedDevices[i] = {
191
- vendorId: device.vendorId,
192
- productId: device.productId,
193
- serialNumber: device.serialNumber
194
- };
195
- return true;
196
- }
293
+ private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean {
294
+ if (!options.filters || !options.filters.length) {
295
+ return true;
197
296
  }
198
297
 
199
- return false;
200
- }
201
-
202
- private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean {
203
298
  return options.filters.some(filter => {
204
299
  // Vendor
205
300
  if (filter.vendorId && filter.vendorId !== device.vendorId) return false;
@@ -248,4 +343,32 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
248
343
  return true;
249
344
  });
250
345
  }
346
+
347
+ private getDeviceId(device: usb.Device): string | undefined {
348
+ if (device.busNumber === undefined || device.deviceAddress === undefined) {
349
+ return undefined;
350
+ }
351
+
352
+ return `${device.busNumber}.${device.deviceAddress}`;
353
+ }
354
+
355
+ private isAllowedDevice(device: USBDeviceFilter): boolean {
356
+ if (this.options.allowAllDevices) {
357
+ return true;
358
+ }
359
+
360
+ const isSameDevice = (device1: USBDeviceFilter, device2: USBDeviceFilter): boolean => {
361
+ return (device1.productId === device2.productId
362
+ && device1.vendorId === device2.vendorId
363
+ && device1.serialNumber === device2.serialNumber);
364
+ };
365
+
366
+ for (const i in this.allowedDevices) {
367
+ if (isSameDevice(device, this.allowedDevices[i])) {
368
+ return true;
369
+ }
370
+ }
371
+
372
+ return false;
373
+ }
251
374
  }
@@ -12,10 +12,14 @@ const ENDPOINT_HALT = 0x00;
12
12
  * Wrapper to make a node-usb device look like a webusb device
13
13
  */
14
14
  export class WebUSBDevice implements USBDevice {
15
- public static async createInstance(device: usb.Device): Promise<WebUSBDevice> {
16
- const instance = new WebUSBDevice(device);
17
- await instance.initialize();
18
- return instance;
15
+ public static async createInstance(device: usb.Device): Promise<WebUSBDevice | undefined> {
16
+ try {
17
+ const instance = new WebUSBDevice(device);
18
+ await instance.initialize();
19
+ return instance;
20
+ } catch {
21
+ return undefined;
22
+ }
19
23
  }
20
24
 
21
25
  public readonly usbVersionMajor: number;
@@ -98,9 +102,9 @@ export class WebUSBDevice implements USBDevice {
98
102
  // Re-create the USBInterface to set the claimed attribute
99
103
  this.configuration.interfaces[this.configuration.interfaces.indexOf(iface)] = {
100
104
  interfaceNumber: iface.interfaceNumber,
101
- alternate : iface.alternate,
102
- alternates : iface.alternates,
103
- claimed : false
105
+ alternate: iface.alternate,
106
+ alternates: iface.alternates,
107
+ claimed: false
104
108
  };
105
109
  }
106
110
  }
@@ -128,7 +132,7 @@ export class WebUSBDevice implements USBDevice {
128
132
  return;
129
133
  }
130
134
 
131
- const config = this.configurations.find(configuration => configuration.configurationValue === configurationValue);
135
+ const config = this.configurations.find(configuration => configuration.configurationValue === configurationValue);
132
136
  if (!config) {
133
137
  throw new Error('selectConfiguration error: configuration not found');
134
138
  }
@@ -171,9 +175,9 @@ export class WebUSBDevice implements USBDevice {
171
175
  // Re-create the USBInterface to set the claimed attribute
172
176
  this.configuration.interfaces[this.configuration.interfaces.indexOf(iface)] = {
173
177
  interfaceNumber,
174
- alternate : iface.alternate,
175
- alternates : iface.alternates,
176
- claimed : true
178
+ alternate: iface.alternate,
179
+ alternates: iface.alternates,
180
+ claimed: true
177
181
  };
178
182
  } catch (error) {
179
183
  throw new Error(`claimInterface error: ${error}`);
@@ -194,9 +198,9 @@ export class WebUSBDevice implements USBDevice {
194
198
  // Re-create the USBInterface to set the claimed attribute
195
199
  this.configuration.interfaces[this.configuration.interfaces.indexOf(iface)] = {
196
200
  interfaceNumber,
197
- alternate : iface.alternate,
198
- alternates : iface.alternates,
199
- claimed : false
201
+ alternate: iface.alternate,
202
+ alternates: iface.alternates,
203
+ claimed: false
200
204
  };
201
205
  }
202
206
  }
@@ -275,7 +279,7 @@ export class WebUSBDevice implements USBDevice {
275
279
  const type = this.controlTransferParamsToType(setup, usb.LIBUSB_ENDPOINT_OUT);
276
280
  const controlTransfer = promisify(this.device.controlTransfer).bind(this.device);
277
281
  const buffer = data ? Buffer.from(data) : Buffer.alloc(0);
278
- const bytesWritten = <number> await controlTransfer(type, setup.request, setup.value, setup.index, buffer);
282
+ const bytesWritten = <number>await controlTransfer(type, setup.request, setup.value, setup.index, buffer);
279
283
 
280
284
  return {
281
285
  bytesWritten,
@@ -387,13 +391,22 @@ export class WebUSBDevice implements USBDevice {
387
391
  private async initialize(): Promise<void> {
388
392
  try {
389
393
  await this.deviceMutex.lock();
390
- this.device.open();
394
+
395
+ if (!this.opened) {
396
+ this.device.open();
397
+ }
398
+
391
399
  this.manufacturerName = await this.getStringDescriptor(this.device.deviceDescriptor.iManufacturer);
392
400
  this.productName = await this.getStringDescriptor(this.device.deviceDescriptor.iProduct);
393
401
  this.serialNumber = await this.getStringDescriptor(this.device.deviceDescriptor.iSerialNumber);
394
402
  this.configurations = await this.getConfigurations();
403
+ } catch (error) {
404
+ throw new Error(`initialize error: ${error}`);
395
405
  } finally {
396
- this.device.close();
406
+ if (this.opened) {
407
+ this.device.close();
408
+ }
409
+
397
410
  this.deviceMutex.unlock();
398
411
  }
399
412
  }
@@ -1,48 +0,0 @@
1
- name: prebuild
2
-
3
- on:
4
- push:
5
- branches:
6
- - master
7
- tags:
8
- - '*'
9
- pull_request:
10
- branches:
11
- - master
12
- workflow_dispatch:
13
-
14
- jobs:
15
- prebuild:
16
- strategy:
17
- matrix:
18
- config:
19
- - { os: macos-latest, arch: x64 }
20
- - { os: ubuntu-18.04, arch: x64 }
21
- - { os: windows-latest, arch: x64 }
22
- - { os: windows-latest, arch: ia32 }
23
- runs-on: ${{ matrix.config.os }}
24
- steps:
25
- - if: matrix.config.os == 'ubuntu-18.04'
26
- run: |
27
- sudo apt-get update
28
- sudo apt-get install libudev-dev
29
- - uses: actions/setup-node@v2
30
- with:
31
- node-version: 14.x
32
- - uses: actions/checkout@v2
33
- with:
34
- submodules: recursive
35
- - run: yarn
36
- - run: yarn run prebuild -- -a ${{ matrix.config.arch }}
37
- - if: startsWith(github.ref, 'refs/tags/')
38
- shell: bash
39
- env:
40
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
- run: |
42
- assets=()
43
- for asset in ./prebuilds/*; do
44
- assets+=("-a" "$asset")
45
- done
46
- tag_name="${GITHUB_REF##*/}"
47
- hub release create -m "$tag_name" "$tag_name" || true
48
- hub release edit "${assets[@]}" -m "" "$tag_name"