usb 2.0.0-alpha.1 → 2.0.3

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 (262) hide show
  1. package/.gitattributes +1 -0
  2. package/.gitmodules +1 -1
  3. package/CHANGELOG.md +91 -0
  4. package/README.md +570 -0
  5. package/binding.gyp +2 -2
  6. package/dist/index.d.ts +16 -5
  7. package/dist/index.js +135 -5
  8. package/dist/index.js.map +1 -1
  9. package/dist/usb/bindings.d.ts +13 -0
  10. package/dist/usb/bindings.js +2 -1
  11. package/dist/usb/bindings.js.map +1 -1
  12. package/dist/usb/index.d.ts +0 -2
  13. package/dist/usb/index.js +75 -112
  14. package/dist/usb/index.js.map +1 -1
  15. package/dist/usb/interface.js.map +1 -1
  16. package/dist/webusb/index.d.ts +28 -19
  17. package/dist/webusb/index.js +152 -66
  18. package/dist/webusb/index.js.map +1 -1
  19. package/dist/webusb/webusb-device.d.ts +1 -1
  20. package/dist/webusb/webusb-device.js +15 -6
  21. package/dist/webusb/webusb-device.js.map +1 -1
  22. package/libusb/.private/pre-commit.sh +7 -1
  23. package/libusb/.travis.yml +49 -0
  24. package/libusb/AUTHORS +44 -3
  25. package/libusb/Brewfile +4 -0
  26. package/libusb/ChangeLog +74 -2
  27. package/libusb/README.md +32 -0
  28. package/libusb/TODO +1 -1
  29. package/libusb/Xcode/common.xcconfig +12 -0
  30. package/libusb/Xcode/config.h +0 -3
  31. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
  32. package/libusb/android/README +4 -2
  33. package/libusb/android/config.h +0 -6
  34. package/libusb/appveyor.yml +41 -0
  35. package/libusb/appveyor_cygwin.bat +11 -0
  36. package/libusb/appveyor_minGW.bat +19 -0
  37. package/libusb/autogen.sh +1 -1
  38. package/libusb/bootstrap.sh +3 -16
  39. package/libusb/configure.ac +108 -80
  40. package/libusb/doc/doxygen.cfg.in +1785 -739
  41. package/libusb/examples/Makefile.am +1 -1
  42. package/libusb/examples/dpfp.c +3 -1
  43. package/libusb/examples/dpfp_threaded.c +23 -10
  44. package/libusb/examples/ezusb.c +3 -3
  45. package/libusb/examples/ezusb.h +2 -2
  46. package/libusb/examples/fxload.c +31 -9
  47. package/libusb/examples/hotplugtest.c +35 -7
  48. package/libusb/examples/listdevs.c +3 -1
  49. package/libusb/examples/sam3u_benchmark.c +3 -3
  50. package/libusb/examples/testlibusb.c +277 -0
  51. package/libusb/examples/xusb.c +40 -34
  52. package/libusb/libusb/Makefile.am +49 -23
  53. package/libusb/libusb/core.c +855 -457
  54. package/libusb/libusb/descriptor.c +72 -78
  55. package/libusb/libusb/hotplug.c +122 -76
  56. package/libusb/libusb/hotplug.h +42 -25
  57. package/libusb/libusb/io.c +625 -390
  58. package/libusb/libusb/libusb-1.0.def +12 -0
  59. package/libusb/libusb/libusb.h +218 -150
  60. package/libusb/libusb/libusbi.h +346 -176
  61. package/libusb/libusb/os/darwin_usb.c +604 -319
  62. package/libusb/libusb/os/darwin_usb.h +61 -20
  63. package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
  64. package/libusb/libusb/os/haiku_usb.h +113 -0
  65. package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
  66. package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
  67. package/libusb/libusb/os/haiku_usb_raw.h +188 -0
  68. package/libusb/libusb/os/linux_netlink.c +186 -146
  69. package/libusb/libusb/os/linux_udev.c +36 -14
  70. package/libusb/libusb/os/linux_usbfs.c +426 -225
  71. package/libusb/libusb/os/linux_usbfs.h +5 -3
  72. package/libusb/libusb/os/netbsd_usb.c +21 -77
  73. package/libusb/libusb/os/openbsd_usb.c +32 -115
  74. package/libusb/libusb/os/poll_posix.c +38 -5
  75. package/libusb/libusb/os/poll_posix.h +3 -0
  76. package/libusb/libusb/os/poll_windows.c +277 -626
  77. package/libusb/libusb/os/poll_windows.h +11 -44
  78. package/libusb/libusb/os/sunos_usb.c +1695 -0
  79. package/libusb/libusb/os/sunos_usb.h +80 -0
  80. package/libusb/libusb/os/threads_posix.c +24 -26
  81. package/libusb/libusb/os/threads_posix.h +73 -21
  82. package/libusb/libusb/os/threads_windows.c +71 -157
  83. package/libusb/libusb/os/threads_windows.h +68 -44
  84. package/libusb/libusb/os/wince_usb.c +276 -420
  85. package/libusb/libusb/os/wince_usb.h +23 -28
  86. package/libusb/libusb/os/windows_common.h +78 -58
  87. package/libusb/libusb/os/windows_nt_common.c +1010 -0
  88. package/libusb/libusb/os/windows_nt_common.h +110 -0
  89. package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
  90. package/libusb/libusb/os/windows_usbdk.c +830 -0
  91. package/libusb/libusb/os/windows_usbdk.h +103 -0
  92. package/libusb/libusb/os/windows_winusb.c +4391 -0
  93. package/libusb/libusb/os/windows_winusb.h +783 -0
  94. package/libusb/libusb/strerror.c +41 -7
  95. package/libusb/libusb/sync.c +41 -13
  96. package/libusb/libusb/version.h +1 -1
  97. package/libusb/libusb/version_nano.h +1 -1
  98. package/libusb/libusb-1.0.pc.in +1 -1
  99. package/libusb/msvc/appveyor.bat +27 -0
  100. package/libusb/msvc/config.h +5 -4
  101. package/libusb/msvc/ddk_build.cmd +87 -43
  102. package/libusb/msvc/fxload_2010.vcxproj +24 -104
  103. package/libusb/msvc/fxload_2012.vcxproj +24 -107
  104. package/libusb/msvc/fxload_2013.vcxproj +24 -107
  105. package/libusb/msvc/fxload_2015.vcxproj +91 -0
  106. package/libusb/msvc/fxload_2017.vcxproj +114 -0
  107. package/libusb/msvc/fxload_sources +1 -1
  108. package/libusb/msvc/getopt_2010.vcxproj +16 -75
  109. package/libusb/msvc/getopt_2012.vcxproj +16 -79
  110. package/libusb/msvc/getopt_2013.vcxproj +16 -79
  111. package/libusb/msvc/getopt_2015.vcxproj +73 -0
  112. package/libusb/msvc/getopt_2017.vcxproj +98 -0
  113. package/libusb/msvc/getopt_sources +6 -2
  114. package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
  115. package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
  116. package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
  117. package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
  118. package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
  119. package/libusb/msvc/hotplugtest_sources +1 -1
  120. package/libusb/msvc/libusb_2005.sln +20 -20
  121. package/libusb/msvc/libusb_2010.sln +57 -46
  122. package/libusb/msvc/libusb_2012.sln +57 -46
  123. package/libusb/msvc/libusb_2013.sln +57 -50
  124. package/libusb/msvc/libusb_2015.sln +59 -52
  125. package/libusb/msvc/libusb_2017.sln +186 -0
  126. package/libusb/msvc/libusb_dll.dsp +2 -2
  127. package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
  128. package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
  129. package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
  130. package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
  131. package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
  132. package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
  133. package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
  134. package/libusb/msvc/libusb_sources +10 -5
  135. package/libusb/msvc/libusb_static.dsp +2 -2
  136. package/libusb/msvc/libusb_static_2005.vcproj +32 -4
  137. package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
  138. package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
  139. package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
  140. package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
  141. package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
  142. package/libusb/msvc/libusb_static_wince.vcproj +20 -26
  143. package/libusb/msvc/libusb_wince.sln +88 -88
  144. package/libusb/msvc/listdevs_2010.vcxproj +16 -99
  145. package/libusb/msvc/listdevs_2012.vcxproj +16 -102
  146. package/libusb/msvc/listdevs_2013.vcxproj +16 -102
  147. package/libusb/msvc/listdevs_2015.vcxproj +83 -0
  148. package/libusb/msvc/listdevs_2017.vcxproj +106 -0
  149. package/libusb/msvc/listdevs_sources +2 -1
  150. package/libusb/msvc/stress_2010.vcxproj +20 -101
  151. package/libusb/msvc/stress_2012.vcxproj +20 -104
  152. package/libusb/msvc/stress_2013.vcxproj +20 -104
  153. package/libusb/msvc/stress_2015.vcxproj +87 -0
  154. package/libusb/msvc/stress_2017.vcxproj +110 -0
  155. package/libusb/msvc/stress_sources +21 -0
  156. package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
  157. package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
  158. package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
  159. package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
  160. package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
  161. package/libusb/msvc/testlibusb_sources +20 -0
  162. package/libusb/msvc/xusb_2010.vcxproj +17 -98
  163. package/libusb/msvc/xusb_2012.vcxproj +17 -101
  164. package/libusb/msvc/xusb_2013.vcxproj +17 -101
  165. package/libusb/msvc/xusb_2015.vcxproj +83 -0
  166. package/libusb/msvc/xusb_2017.vcxproj +106 -0
  167. package/libusb/msvc/xusb_sources +1 -1
  168. package/libusb/tests/stress.c +2 -2
  169. package/libusb/tests/testlib.c +0 -4
  170. package/libusb/travis-autogen.sh +39 -0
  171. package/libusb.gypi +13 -2
  172. package/package.json +23 -13
  173. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  174. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  175. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  176. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  177. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  178. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  179. package/prebuilds/linux-ia32/node.napi.node +0 -0
  180. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  181. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  182. package/prebuilds/win32-ia32/node.napi.node +0 -0
  183. package/prebuilds/win32-x64/node.napi.node +0 -0
  184. package/src/device.cc +7 -7
  185. package/src/node_usb.cc +43 -1
  186. package/src/node_usb.h +1 -0
  187. package/src/uv_async_queue.h +33 -25
  188. package/test/usb.coffee +12 -4
  189. package/tsc/index.ts +68 -8
  190. package/tsc/usb/bindings.ts +19 -1
  191. package/tsc/usb/index.ts +66 -68
  192. package/tsc/usb/interface.ts +2 -2
  193. package/tsc/webusb/index.ts +187 -75
  194. package/tsc/webusb/webusb-device.ts +28 -17
  195. package/.github/workflows/prebuild.yml +0 -48
  196. package/Readme.md +0 -339
  197. package/dist/webusb/typed-event-target.d.ts +0 -11
  198. package/dist/webusb/typed-event-target.js +0 -21
  199. package/dist/webusb/typed-event-target.js.map +0 -1
  200. package/docs/assets/css/main.css +0 -2660
  201. package/docs/assets/images/icons.png +0 -0
  202. package/docs/assets/images/icons@2x.png +0 -0
  203. package/docs/assets/images/widgets.png +0 -0
  204. package/docs/assets/images/widgets@2x.png +0 -0
  205. package/docs/assets/js/main.js +0 -248
  206. package/docs/assets/js/search.js +0 -1
  207. package/docs/classes/usb_bindings.device.html +0 -1338
  208. package/docs/classes/usb_bindings.libusbexception.html +0 -234
  209. package/docs/classes/usb_bindings.transfer.html +0 -344
  210. package/docs/classes/usb_capability.capability.html +0 -297
  211. package/docs/classes/usb_device.extendeddevice.html +0 -766
  212. package/docs/classes/usb_endpoint.endpoint.html +0 -472
  213. package/docs/classes/usb_endpoint.inendpoint.html +0 -766
  214. package/docs/classes/usb_endpoint.outendpoint.html +0 -582
  215. package/docs/classes/usb_interface.interface.html +0 -648
  216. package/docs/classes/webusb.webusb-1.html +0 -615
  217. package/docs/classes/webusb_mutex.mutex.html +0 -270
  218. package/docs/classes/webusb_typed_event_target.typedeventtarget.html +0 -443
  219. package/docs/classes/webusb_webusb_device.webusbdevice.html +0 -904
  220. package/docs/index.html +0 -500
  221. package/docs/interfaces/usb.deviceevents.html +0 -242
  222. package/docs/interfaces/usb_descriptors.bosdescriptor.html +0 -293
  223. package/docs/interfaces/usb_descriptors.capabilitydescriptor.html +0 -274
  224. package/docs/interfaces/usb_descriptors.configdescriptor.html +0 -388
  225. package/docs/interfaces/usb_descriptors.devicedescriptor.html +0 -464
  226. package/docs/interfaces/usb_descriptors.endpointdescriptor.html +0 -370
  227. package/docs/interfaces/usb_descriptors.interfacedescriptor.html +0 -407
  228. package/docs/interfaces/webusb.usboptions.html +0 -226
  229. package/docs/modules/index.html +0 -173
  230. package/docs/modules/usb.html +0 -173
  231. package/docs/modules/usb_bindings.html +0 -2319
  232. package/docs/modules/usb_capability.html +0 -156
  233. package/docs/modules/usb_descriptors.html +0 -176
  234. package/docs/modules/usb_device.html +0 -156
  235. package/docs/modules/usb_endpoint.html +0 -164
  236. package/docs/modules/usb_interface.html +0 -156
  237. package/docs/modules/webusb.html +0 -165
  238. package/docs/modules/webusb_mutex.html +0 -156
  239. package/docs/modules/webusb_typed_event_target.html +0 -156
  240. package/docs/modules/webusb_webusb_device.html +0 -156
  241. package/docs/modules.html +0 -156
  242. package/libusb/INSTALL +0 -234
  243. package/libusb/README +0 -28
  244. package/libusb/libusb/os/windows_usb.c +0 -5347
  245. package/libusb/libusb/os/windows_usb.h +0 -971
  246. package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
  247. package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
  248. package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
  249. package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
  250. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
  251. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
  252. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
  253. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
  254. package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
  255. package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
  256. package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
  257. package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
  258. package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
  259. package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
  260. package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
  261. package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
  262. package/tsc/webusb/typed-event-target.ts +0 -23
@@ -1,54 +1,148 @@
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;
36
- };
27
+ deviceTimeout?: number;
28
+ }
37
29
 
38
- export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
30
+ export class WebUSB implements USB {
39
31
 
40
- private allowedDevices: Array<Device> = [];
32
+ protected emitter = new EventEmitter();
33
+ protected knownDevices: Map<string, USBDevice> = new Map();
34
+ protected allowedDevices: USBDeviceFilter[];
41
35
 
42
36
  constructor(private options: USBOptions = {}) {
43
- super();
37
+ this.allowedDevices = options.allowedDevices || [];
38
+
39
+ const deviceConnectCallback = async (device: usb.Device) => {
40
+ const webDevice = await WebUSBDevice.createInstance(device);
41
+
42
+ // When connected, emit an event if it is an allowed device
43
+ if (webDevice && this.isAllowedDevice(webDevice)) {
44
+ const deviceId = this.getDeviceId(device);
45
+ if (deviceId) {
46
+ this.knownDevices.set(deviceId, webDevice);
47
+ }
48
+
49
+ const event = {
50
+ type: 'connect',
51
+ device: webDevice
52
+ };
53
+
54
+ this.emitter.emit('connect', event);
55
+ }
56
+ };
57
+
58
+ const deviceDisconnectCallback = async (device: usb.Device) => {
59
+ const deviceId = this.getDeviceId(device);
60
+
61
+ // When disconnected, emit an event if the device was a known allowed device
62
+ if (deviceId !== undefined && this.knownDevices.has(deviceId)) {
63
+ const webDevice = this.knownDevices.get(deviceId);
64
+
65
+ if (webDevice && this.isAllowedDevice(webDevice)) {
66
+ const event = {
67
+ type: 'disconnect',
68
+ device: webDevice
69
+ };
70
+
71
+ this.emitter.emit('disconnect', event);
72
+ }
73
+ }
74
+ };
75
+
76
+ this.emitter.on('newListener', event => {
77
+ const listenerCount = this.emitter.listenerCount(event);
78
+
79
+ if (listenerCount !== 0) {
80
+ return;
81
+ }
82
+
83
+ if (event === 'connect') {
84
+ usb.addListener('attach', deviceConnectCallback);
85
+ } else if (event === 'disconnect') {
86
+ usb.addListener('detach', deviceDisconnectCallback);
87
+ }
88
+ });
89
+
90
+ this.emitter.on('removeListener', event => {
91
+ const listenerCount = this.emitter.listenerCount(event);
92
+
93
+ if (listenerCount !== 0) {
94
+ return;
95
+ }
96
+
97
+ if (event === 'connect') {
98
+ usb.removeListener('attach', deviceConnectCallback);
99
+ } else if (event === 'disconnect') {
100
+ usb.removeListener('detach', deviceDisconnectCallback);
101
+ }
102
+ });
103
+ }
104
+
105
+ private _onconnect: ((ev: USBConnectionEvent) => void) | undefined;
106
+ public set onconnect(fn: (ev: USBConnectionEvent) => void) {
107
+ if (this._onconnect) {
108
+ this.removeEventListener('connect', this._onconnect);
109
+ this._onconnect = undefined;
110
+ }
111
+
112
+ if (fn) {
113
+ this._onconnect = fn;
114
+ this.addEventListener('connect', this._onconnect);
115
+ }
116
+ }
117
+
118
+ private _ondisconnect: ((ev: USBConnectionEvent) => void) | undefined;
119
+ public set ondisconnect(fn: (ev: USBConnectionEvent) => void) {
120
+ if (this._ondisconnect) {
121
+ this.removeEventListener('disconnect', this._ondisconnect);
122
+ this._ondisconnect = undefined;
123
+ }
124
+
125
+ if (fn) {
126
+ this._ondisconnect = fn;
127
+ this.addEventListener('disconnect', this._ondisconnect);
128
+ }
129
+ }
130
+
131
+ public addEventListener(type: 'connect' | 'disconnect', listener: (this: this, ev: USBConnectionEvent) => void): void;
132
+ public addEventListener(type: 'connect' | 'disconnect', listener: EventListener): void;
133
+ public addEventListener(type: string, listener: (ev: USBConnectionEvent) => void): void {
134
+ this.emitter.addListener(type, listener);
44
135
  }
45
136
 
46
- public set onconnect(listener: (event: USBConnectionEvent) => void) {
47
- this.addEventListener('connect', listener);
137
+ public removeEventListener(type: 'connect' | 'disconnect', callback: (this: this, ev: USBConnectionEvent) => void): void;
138
+ public removeEventListener(type: 'connect' | 'disconnect', callback: EventListener): void;
139
+ public removeEventListener(type: string, callback: (this: this, ev: USBConnectionEvent) => void): void {
140
+ this.emitter.removeListener(type, callback);
48
141
  }
49
142
 
50
- public set ondisconnect(listener: (event: USBConnectionEvent) => void) {
51
- this.addEventListener('disconnect', listener);
143
+ public dispatchEvent(_event: Event): boolean {
144
+ // Don't dispatch from here
145
+ return false;
52
146
  }
53
147
 
54
148
  /**
@@ -105,7 +199,7 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
105
199
  throw new Error('selected device not found');
106
200
  }
107
201
 
108
- if (!this.replaceAllowedDevice(device)) {
202
+ if (!this.isAllowedDevice(device)) {
109
203
  this.allowedDevices.push({
110
204
  vendorId: device.vendorId,
111
205
  productId: device.productId,
@@ -114,7 +208,7 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
114
208
  }
115
209
 
116
210
  return device;
117
- } catch(error) {
211
+ } catch (error) {
118
212
  throw new Error(`requestDevice error: ${error}`);
119
213
  }
120
214
  }
@@ -124,47 +218,54 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
124
218
  * @returns Promise containing an array of devices
125
219
  */
126
220
  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
- }));
221
+ let preFilters: USBDeviceFilter[] | undefined;
222
+
223
+ if (!this.options.allowAllDevices) {
224
+ // Create pre-filters
225
+ preFilters = this.allowedDevices.map(device => ({
226
+ vendorId: device.vendorId || undefined,
227
+ productId: device.productId || undefined,
228
+ serialNumber: device.serialNumber || undefined
229
+ }));
230
+ }
133
231
 
134
232
  // 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;
233
+ const devices = await this.loadDevices(preFilters);
234
+ return devices.filter(device => this.isAllowedDevice(device));
147
235
  }
148
236
 
149
- private async loadDevices(preFilters?: Array<Device>): Promise<USBDevice[]> {
237
+ private async loadDevices(preFilters?: USBDeviceFilter[]): Promise<USBDevice[]> {
150
238
  let devices = usb.getDeviceList();
151
239
 
152
- if (preFilters) {
153
- // Pre-filter devices
154
- devices = this.preFilterDevices(devices, preFilters);
155
- }
240
+ // Pre-filter devices
241
+ devices = this.preFilterDevices(devices, preFilters);
156
242
 
157
243
  const webDevices: USBDevice[] = [];
158
244
 
159
245
  for (const device of devices) {
246
+ if (this.options.deviceTimeout) {
247
+ device.timeout = this.options.deviceTimeout;
248
+ }
249
+
160
250
  const webDevice = await WebUSBDevice.createInstance(device);
161
- webDevices.push(webDevice);
251
+ if (webDevice) {
252
+ webDevices.push(webDevice);
253
+
254
+ const deviceId = this.getDeviceId(device);
255
+ if (deviceId) {
256
+ this.knownDevices.set(deviceId, webDevice);
257
+ }
258
+ }
162
259
  }
163
260
 
164
261
  return webDevices;
165
262
  }
166
263
 
167
- private preFilterDevices(devices: Array<usb.Device>, preFilters: Array<Device>): Array<usb.Device> {
264
+ private preFilterDevices(devices: usb.Device[], preFilters?: USBDeviceFilter[]): usb.Device[] {
265
+ if (!preFilters || !preFilters.length) {
266
+ return devices;
267
+ }
268
+
168
269
  // Just pre-filter on vid/pid
169
270
  return devices.filter(device => preFilters.some(filter => {
170
271
  // Vendor
@@ -178,28 +279,11 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
178
279
  }));
179
280
  }
180
281
 
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
- }
282
+ private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean {
283
+ if (!options.filters || !options.filters.length) {
284
+ return true;
197
285
  }
198
286
 
199
- return false;
200
- }
201
-
202
- private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean {
203
287
  return options.filters.some(filter => {
204
288
  // Vendor
205
289
  if (filter.vendorId && filter.vendorId !== device.vendorId) return false;
@@ -248,4 +332,32 @@ export class WebUSB extends TypedEventTarget<USBEvents> implements USB {
248
332
  return true;
249
333
  });
250
334
  }
335
+
336
+ private getDeviceId(device: usb.Device): string | undefined {
337
+ if (device.busNumber === undefined || device.deviceAddress === undefined) {
338
+ return undefined;
339
+ }
340
+
341
+ return `${device.busNumber}.${device.deviceAddress}`;
342
+ }
343
+
344
+ private isAllowedDevice(device: USBDeviceFilter): boolean {
345
+ if (this.options.allowAllDevices) {
346
+ return true;
347
+ }
348
+
349
+ const isSameDevice = (device1: USBDeviceFilter, device2: USBDeviceFilter): boolean => {
350
+ return (device1.productId === device2.productId
351
+ && device1.vendorId === device2.vendorId
352
+ && device1.serialNumber === device2.serialNumber);
353
+ };
354
+
355
+ for (const i in this.allowedDevices) {
356
+ if (isSameDevice(device, this.allowedDevices[i])) {
357
+ return true;
358
+ }
359
+ }
360
+
361
+ return false;
362
+ }
251
363
  }
@@ -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,20 @@ 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();
395
403
  } finally {
396
- this.device.close();
404
+ if (this.opened) {
405
+ this.device.close();
406
+ }
407
+
397
408
  this.deviceMutex.unlock();
398
409
  }
399
410
  }
@@ -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"