usb 2.5.2-alpha.1 → 2.6.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 (43) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/index.d.ts +10 -6
  3. package/dist/index.js +27 -11
  4. package/dist/index.js.map +1 -1
  5. package/dist/usb/endpoint.js +3 -1
  6. package/dist/usb/endpoint.js.map +1 -1
  7. package/dist/webusb/index.js +40 -24
  8. package/dist/webusb/index.js.map +1 -1
  9. package/dist/webusb/webusb-device.d.ts +1 -1
  10. package/dist/webusb/webusb-device.js +24 -30
  11. package/dist/webusb/webusb-device.js.map +1 -1
  12. package/package.json +12 -12
  13. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  14. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  15. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  16. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  17. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  18. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  19. package/prebuilds/linux-ia32/node.napi.node +0 -0
  20. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  21. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  22. package/prebuilds/win32-ia32/node.napi.node +0 -0
  23. package/prebuilds/win32-x64/node.napi.node +0 -0
  24. package/.eslintignore +0 -4
  25. package/.eslintrc.json +0 -87
  26. package/.gitattributes +0 -1
  27. package/.gitmodules +0 -3
  28. package/.vscode/launch.json +0 -15
  29. package/.vscode/tasks.json +0 -23
  30. package/libusb/.gitattributes +0 -7
  31. package/libusb/msvc/.gitattributes +0 -3
  32. package/tsc/index.ts +0 -75
  33. package/tsc/usb/bindings.ts +0 -310
  34. package/tsc/usb/capability.ts +0 -22
  35. package/tsc/usb/descriptors.ts +0 -180
  36. package/tsc/usb/device.ts +0 -331
  37. package/tsc/usb/endpoint.ts +0 -229
  38. package/tsc/usb/index.ts +0 -149
  39. package/tsc/usb/interface.ts +0 -167
  40. package/tsc/webusb/index.ts +0 -374
  41. package/tsc/webusb/webusb-device.ts +0 -490
  42. package/tsconfig.json +0 -17
  43. package/typedoc.json +0 -9
@@ -1,374 +0,0 @@
1
- import * as usb from '../usb';
2
- import { EventEmitter } from 'events';
3
- import { WebUSBDevice } from './webusb-device';
4
-
5
- /**
6
- * USB Options
7
- */
8
- export interface USBOptions {
9
- /**
10
- * Optional `device found` callback function to allow the user to select a device
11
- */
12
- devicesFound?: (devices: USBDevice[]) => Promise<USBDevice | void>;
13
-
14
- /**
15
- * Optional array of preconfigured allowed devices
16
- */
17
- allowedDevices?: USBDeviceFilter[];
18
-
19
- /**
20
- * Optional flag to automatically allow all devices
21
- */
22
- allowAllDevices?: boolean;
23
-
24
- /**
25
- * Optional timeout (in milliseconds) to use for the device control transfers
26
- */
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();
39
- };
40
-
41
- export class WebUSB implements USB {
42
-
43
- protected emitter = new EventEmitter();
44
- protected knownDevices: Map<string, USBDevice> = new Map();
45
- protected allowedDevices: USBDeviceFilter[];
46
-
47
- constructor(private options: USBOptions = {}) {
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
- }
140
- }
141
-
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);
146
- }
147
-
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;
157
- }
158
-
159
- /**
160
- * Requests a single Web USB device
161
- * @param options The options to use when scanning
162
- * @returns Promise containing the selected device
163
- */
164
- public async requestDevice(options?: USBDeviceRequestOptions): Promise<USBDevice> {
165
- // Must have options
166
- if (!options) {
167
- throw new TypeError('requestDevice error: 1 argument required, but only 0 present');
168
- }
169
-
170
- // Options must be an object
171
- if (options.constructor !== {}.constructor) {
172
- throw new TypeError('requestDevice error: parameter 1 (options) is not an object');
173
- }
174
-
175
- // Must have a filter
176
- if (!options.filters) {
177
- throw new TypeError('requestDevice error: required member filters is undefined');
178
- }
179
-
180
- // Filter must be an array
181
- if (options.filters.constructor !== [].constructor) {
182
- throw new TypeError('requestDevice error: the provided value cannot be converted to a sequence');
183
- }
184
-
185
- // Check filters
186
- options.filters.forEach(filter => {
187
- // Protocol & Subclass
188
- if (filter.protocolCode && !filter.subclassCode) {
189
- throw new TypeError('requestDevice error: subclass code is required');
190
- }
191
-
192
- // Subclass & Class
193
- if (filter.subclassCode && !filter.classCode) {
194
- throw new TypeError('requestDevice error: class code is required');
195
- }
196
- });
197
-
198
- let devices = await this.loadDevices(options.filters);
199
- devices = devices.filter(device => this.filterDevice(options, device));
200
-
201
- if (devices.length === 0) {
202
- throw new Error('requestDevice error: no devices found');
203
- }
204
-
205
- try {
206
- // If no devicesFound function, select the first device found
207
- const device = this.options.devicesFound ? await this.options.devicesFound(devices) : devices[0];
208
-
209
- if (!device) {
210
- throw new Error('selected device not found');
211
- }
212
-
213
- if (!this.isAllowedDevice(device)) {
214
- this.allowedDevices.push({
215
- vendorId: device.vendorId,
216
- productId: device.productId,
217
- serialNumber: device.serialNumber
218
- });
219
- }
220
-
221
- return device;
222
- } catch (error) {
223
- throw new Error(`requestDevice error: ${error}`);
224
- }
225
- }
226
-
227
- /**
228
- * Gets all allowed Web USB devices which are connected
229
- * @returns Promise containing an array of devices
230
- */
231
- public async getDevices(): Promise<USBDevice[]> {
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
- }
242
-
243
- // Refresh devices and filter for allowed ones
244
- const devices = await this.loadDevices(preFilters);
245
- return devices.filter(device => this.isAllowedDevice(device));
246
- }
247
-
248
- private async loadDevices(preFilters?: USBDeviceFilter[]): Promise<USBDevice[]> {
249
- let devices = usb.getDeviceList();
250
-
251
- // Pre-filter devices
252
- devices = this.preFilterDevices(devices, preFilters);
253
-
254
- const webDevices: USBDevice[] = [];
255
-
256
- for (const device of devices) {
257
- if (this.options.deviceTimeout) {
258
- device.timeout = this.options.deviceTimeout;
259
- }
260
-
261
- const webDevice = await WebUSBDevice.createInstance(device);
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
- }
270
- }
271
-
272
- return webDevices;
273
- }
274
-
275
- private preFilterDevices(devices: usb.Device[], preFilters?: USBDeviceFilter[]): usb.Device[] {
276
- if (!preFilters || !preFilters.length) {
277
- return devices;
278
- }
279
-
280
- // Just pre-filter on vid/pid
281
- return devices.filter(device => preFilters.some(filter => {
282
- // Vendor
283
- if (filter.vendorId && filter.vendorId !== device.deviceDescriptor.idVendor) return false;
284
-
285
- // Product
286
- if (filter.productId && filter.productId !== device.deviceDescriptor.idProduct) return false;
287
-
288
- // Ignore serial number for node-usb as it requires device connection
289
- return true;
290
- }));
291
- }
292
-
293
- private filterDevice(options: USBDeviceRequestOptions, device: USBDevice): boolean {
294
- if (!options.filters || !options.filters.length) {
295
- return true;
296
- }
297
-
298
- return options.filters.some(filter => {
299
- // Vendor
300
- if (filter.vendorId && filter.vendorId !== device.vendorId) return false;
301
-
302
- // Product
303
- if (filter.productId && filter.productId !== device.productId) return false;
304
-
305
- // Class
306
- if (filter.classCode) {
307
-
308
- if (!device.configuration) {
309
- return false;
310
- }
311
-
312
- // Interface Descriptors
313
- const match = device.configuration.interfaces.some(iface => {
314
- // Class
315
- if (filter.classCode && filter.classCode !== iface.alternate.interfaceClass) return false;
316
-
317
- // Subclass
318
- if (filter.subclassCode && filter.subclassCode !== iface.alternate.interfaceSubclass) return false;
319
-
320
- // Protocol
321
- if (filter.protocolCode && filter.protocolCode !== iface.alternate.interfaceProtocol) return false;
322
-
323
- return true;
324
- });
325
-
326
- if (match) {
327
- return true;
328
- }
329
- }
330
-
331
- // Class
332
- if (filter.classCode && filter.classCode !== device.deviceClass) return false;
333
-
334
- // Subclass
335
- if (filter.subclassCode && filter.subclassCode !== device.deviceSubclass) return false;
336
-
337
- // Protocol
338
- if (filter.protocolCode && filter.protocolCode !== device.deviceProtocol) return false;
339
-
340
- // Serial
341
- if (filter.serialNumber && filter.serialNumber !== device.serialNumber) return false;
342
-
343
- return true;
344
- });
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
- }
374
- }