@onekeyfe/hd-transport-web-device 1.2.8-alpha.2 → 1.2.8-alpha.20
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/__tests__/electron-ble-transport.test.ts +14 -0
- package/__tests__/webusb-identity-probe.test.ts +887 -0
- package/dist/electron-ble-transport.d.ts.map +1 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +289 -24
- package/dist/webusb.d.ts +17 -1
- package/dist/webusb.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/electron-ble-transport.ts +5 -2
- package/src/webusb.ts +282 -23
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":";AAyBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,iCAAiC,CAAC;AAC5F,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EAEZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AAIvC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,CAAC,EAAE,UAAU,CAAC;KACzB;CACF;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,YAAY,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAiDF,MAAM,CAAC,OAAO,OAAO,oBAAoB;IACvC,OAAO,CAAC,SAAS,CAA0D;IAE3E,OAAO,CAAC,WAAW,CAA0D;IAE7E,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,IAAI,SAA0B;IAE9B,UAAU,UAAS;IAEnB,UAAU,EAAE,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,IAAI,CAAQ;IAExD,OAAO,CAAC,kBAAkB,CAAuB;IAEjD,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,OAAO,CAAC,gBAAgB,CAA0B;IASlD,OAAO,CAAC,gBAAgB,CAA0B;IAElD,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAEnE,OAAO,CAAC,UAAU,CAAkC;IAEpD,OAAO,CAAC,sBAAsB,CAAkC;IAEhE,OAAO,CAAC,SAAS,CAAsE;IAEvF,OAAO,CAAC,YAAY,CAAoD;IAExE,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO,CAAC,eAAe,CAAgD;IAEvE,OAAO,CAAC,eAAe,CAmBpB;IAGH,OAAO,CAAC,oBAAoB,CAAS;IAErC,OAAO,CAAC,oBAAoB,CAAsC;IAElE,OAAO,CAAC,WAAW,CAAsC;IAUzD,OAAO,CAAC,qBAAqB,CAAC,CAAa;IAE3C,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,qBAAqB,CAAK;IAElC,OAAO,CAAC,uBAAuB;
|
|
1
|
+
{"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ interface DeviceInfo extends OneKeyDeviceInfoBase {
|
|
|
13
13
|
protocolType?: ProtocolType;
|
|
14
14
|
}
|
|
15
15
|
declare class WebUsbTransport extends ProtocolV2UsbTransportBase<string> {
|
|
16
|
+
private readonly identityProbe;
|
|
16
17
|
messages: ReturnType<typeof _onekeyfe_hd_transport__default.parseConfigure> | undefined;
|
|
17
18
|
/** Protobuf schema for Protocol V2 transports. */
|
|
18
19
|
messagesV2: ReturnType<typeof _onekeyfe_hd_transport__default.parseConfigure> | undefined;
|
|
@@ -29,6 +30,11 @@ declare class WebUsbTransport extends ProtocolV2UsbTransportBase<string> {
|
|
|
29
30
|
private staleProtocolPaths;
|
|
30
31
|
/** Paths currently acquired (between a successful acquire() and its release()). */
|
|
31
32
|
private acquiredPaths;
|
|
33
|
+
private identityProbeDevices;
|
|
34
|
+
private normalDevices;
|
|
35
|
+
private pendingHandleOperations;
|
|
36
|
+
private stopPromise?;
|
|
37
|
+
private identityProbeCleanupPaths;
|
|
32
38
|
/**
|
|
33
39
|
* The exact USBDevice object each cached protocol was probed against. The
|
|
34
40
|
* browser returns the same object identity for a device as long as it stays
|
|
@@ -53,11 +59,15 @@ declare class WebUsbTransport extends ProtocolV2UsbTransportBase<string> {
|
|
|
53
59
|
configurationId: number;
|
|
54
60
|
endpointId: number;
|
|
55
61
|
interfaceId: number;
|
|
56
|
-
constructor();
|
|
62
|
+
constructor(identityProbe?: boolean);
|
|
57
63
|
/**
|
|
58
64
|
* Initialize WebUSB transport
|
|
59
65
|
*/
|
|
60
66
|
init(logger: any, emitter?: EventEmitter): void;
|
|
67
|
+
stop(): Promise<void>;
|
|
68
|
+
private stopResources;
|
|
69
|
+
private assertRunning;
|
|
70
|
+
private runHandleOperation;
|
|
61
71
|
/**
|
|
62
72
|
* Announce that a USB device left. Called from the module-scoped disconnect
|
|
63
73
|
* listener, which is why it is public rather than inlined.
|
|
@@ -129,6 +139,12 @@ declare class WebUsbTransport extends ProtocolV2UsbTransportBase<string> {
|
|
|
129
139
|
* Discovers interface/endpoint numbers from USB descriptors on first connection.
|
|
130
140
|
*/
|
|
131
141
|
connectToDevice(path: string, first: boolean): Promise<undefined>;
|
|
142
|
+
private assertHandleAvailable;
|
|
143
|
+
private claimNormalHandle;
|
|
144
|
+
private releaseNormalHandles;
|
|
145
|
+
private isHandleOwnershipError;
|
|
146
|
+
private claimIdentityProbeHandle;
|
|
147
|
+
private releaseIdentityProbeHandle;
|
|
132
148
|
private closeOpenDevice;
|
|
133
149
|
private clearEndpointHalt;
|
|
134
150
|
/**
|
package/dist/index.js
CHANGED
|
@@ -51,11 +51,15 @@ const REPORT_ID = transport.PROTOCOL_V1_REPORT_ID;
|
|
|
51
51
|
const HEADER_LENGTH = transport.PROTOCOL_V1_MESSAGE_HEADER_SIZE;
|
|
52
52
|
const PACKET_IO_MAX_RETRIES = 3;
|
|
53
53
|
const PACKET_IO_RETRY_DELAY = 300;
|
|
54
|
+
const USB_DEVICE_IN_USE = 'USB device is already in use';
|
|
54
55
|
const PROTOCOL_V1_PROBE_TIMEOUT = 5000;
|
|
55
56
|
const PROTOCOL_V2_PROBE_TIMEOUT = 1000;
|
|
56
57
|
const EXPECTED_PROTOCOL_V2_PROBE_ATTEMPTS = 2;
|
|
57
58
|
let activeWebUsbTransport;
|
|
58
59
|
let usbDisconnectListenerAttached = false;
|
|
60
|
+
const identityProbeHandles = new WeakSet();
|
|
61
|
+
const openingHandles = new WeakSet();
|
|
62
|
+
const normalHandleOwners = new WeakMap();
|
|
59
63
|
function registerActiveWebUsbTransport(instance, usb) {
|
|
60
64
|
activeWebUsbTransport = instance;
|
|
61
65
|
if (usbDisconnectListenerAttached)
|
|
@@ -72,17 +76,22 @@ function registerActiveWebUsbTransport(instance, usb) {
|
|
|
72
76
|
});
|
|
73
77
|
}
|
|
74
78
|
class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
75
|
-
constructor() {
|
|
79
|
+
constructor(identityProbe = false) {
|
|
76
80
|
super({
|
|
77
81
|
router: transport.PROTOCOL_V2_CHANNEL_USB,
|
|
78
82
|
maxFrameBytes: transport.PROTOCOL_V2_FRAME_MAX_BYTES,
|
|
79
83
|
logPrefix: 'ProtocolV2 WebUSB',
|
|
80
84
|
});
|
|
85
|
+
this.identityProbe = identityProbe;
|
|
81
86
|
this.deviceProtocol = new Map();
|
|
82
87
|
this.confirmedDeviceProtocols = new Map();
|
|
83
88
|
this.deviceProtocolHints = new Map();
|
|
84
89
|
this.staleProtocolPaths = new Set();
|
|
85
90
|
this.acquiredPaths = new Set();
|
|
91
|
+
this.identityProbeDevices = new Map();
|
|
92
|
+
this.normalDevices = new Map();
|
|
93
|
+
this.pendingHandleOperations = new Set();
|
|
94
|
+
this.identityProbeCleanupPaths = new Set();
|
|
86
95
|
this.probedDeviceObjects = new Map();
|
|
87
96
|
this.deviceEndpoints = new Map();
|
|
88
97
|
this.name = 'WebUsbTransport';
|
|
@@ -101,7 +110,104 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
101
110
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'WebUSB is not supported by current browsers');
|
|
102
111
|
}
|
|
103
112
|
this.usb = usb;
|
|
104
|
-
|
|
113
|
+
if (!this.identityProbe)
|
|
114
|
+
registerActiveWebUsbTransport(this, usb);
|
|
115
|
+
}
|
|
116
|
+
stop() {
|
|
117
|
+
this.stopped = true;
|
|
118
|
+
this.acquiredPaths.clear();
|
|
119
|
+
if (activeWebUsbTransport === this)
|
|
120
|
+
activeWebUsbTransport = undefined;
|
|
121
|
+
if (!this.stopPromise) {
|
|
122
|
+
this.stopPromise = this.stopResources().catch(error => {
|
|
123
|
+
this.stopPromise = undefined;
|
|
124
|
+
throw error;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return this.stopPromise;
|
|
128
|
+
}
|
|
129
|
+
stopResources() {
|
|
130
|
+
var _a, _b, _c;
|
|
131
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
let cleanupError;
|
|
133
|
+
try {
|
|
134
|
+
yield this.disposeProtocolV2UsbLinks('WebUSB transport stopped');
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
cleanupError = error;
|
|
138
|
+
}
|
|
139
|
+
yield Promise.allSettled([...this.pendingHandleOperations]);
|
|
140
|
+
const handles = this.identityProbe
|
|
141
|
+
? [...this.identityProbeDevices].map(([path, device]) => [device, path])
|
|
142
|
+
: [...this.normalDevices];
|
|
143
|
+
for (const [device, path] of handles) {
|
|
144
|
+
if (!this.identityProbe && normalHandleOwners.get(device) !== this) {
|
|
145
|
+
this.normalDevices.delete(device);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
try {
|
|
149
|
+
if (device.opened) {
|
|
150
|
+
const iface = (_b = (_a = this.deviceEndpoints.get(path)) === null || _a === void 0 ? void 0 : _a.interfaceNumber) !== null && _b !== void 0 ? _b : this.interfaceId;
|
|
151
|
+
try {
|
|
152
|
+
yield device.releaseInterface(iface);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
(_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('[WebUsbTransport] stop releaseInterface failed:', error);
|
|
156
|
+
}
|
|
157
|
+
yield device.close();
|
|
158
|
+
if (device.opened)
|
|
159
|
+
throw new Error('WebUSB handle remains open after stop');
|
|
160
|
+
}
|
|
161
|
+
if (this.identityProbe) {
|
|
162
|
+
identityProbeHandles.delete(device);
|
|
163
|
+
this.identityProbeDevices.delete(path);
|
|
164
|
+
this.identityProbeCleanupPaths.delete(path);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
normalHandleOwners.delete(device);
|
|
168
|
+
this.normalDevices.delete(device);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
cleanupError !== null && cleanupError !== void 0 ? cleanupError : (cleanupError = error);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
this.deviceList = [];
|
|
177
|
+
this.deviceProtocol.clear();
|
|
178
|
+
this.confirmedDeviceProtocols.clear();
|
|
179
|
+
this.deviceProtocolHints.clear();
|
|
180
|
+
this.staleProtocolPaths.clear();
|
|
181
|
+
this.probedDeviceObjects.clear();
|
|
182
|
+
if (!this.normalDevices.size && !this.identityProbeDevices.size) {
|
|
183
|
+
this.deviceEndpoints.clear();
|
|
184
|
+
}
|
|
185
|
+
if (cleanupError) {
|
|
186
|
+
throw cleanupError instanceof Error
|
|
187
|
+
? cleanupError
|
|
188
|
+
: new Error(this.getErrorMessage(cleanupError));
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
assertRunning() {
|
|
193
|
+
if (this.stopped) {
|
|
194
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'WebUSB transport is stopped');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
runHandleOperation(operation) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
this.assertRunning();
|
|
200
|
+
const pending = Promise.resolve(operation());
|
|
201
|
+
this.pendingHandleOperations.add(pending);
|
|
202
|
+
try {
|
|
203
|
+
const result = yield pending;
|
|
204
|
+
this.assertRunning();
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
this.pendingHandleOperations.delete(pending);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
105
211
|
}
|
|
106
212
|
emitDeviceDisconnect(path, device) {
|
|
107
213
|
var _a, _b;
|
|
@@ -150,15 +256,36 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
150
256
|
}
|
|
151
257
|
enumerate() {
|
|
152
258
|
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
for (const path of this.identityProbeCleanupPaths) {
|
|
260
|
+
try {
|
|
261
|
+
yield this.release(path);
|
|
262
|
+
}
|
|
263
|
+
catch (_a) {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
153
266
|
yield this.getConnectedDevices();
|
|
154
267
|
return this.deviceList;
|
|
155
268
|
});
|
|
156
269
|
}
|
|
157
270
|
getConnectedDevices() {
|
|
271
|
+
var _a;
|
|
158
272
|
return __awaiter(this, void 0, void 0, function* () {
|
|
273
|
+
this.assertRunning();
|
|
159
274
|
if (!this.usb)
|
|
160
275
|
return [];
|
|
161
276
|
const devices = yield this.usb.getDevices();
|
|
277
|
+
this.assertRunning();
|
|
278
|
+
for (const owner of new Set(devices.map(device => normalHandleOwners.get(device)))) {
|
|
279
|
+
if (owner === null || owner === void 0 ? void 0 : owner.stopped) {
|
|
280
|
+
try {
|
|
281
|
+
yield owner.stop();
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
(_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[WebUsbTransport] stopped owner cleanup failed:', error);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this.assertRunning();
|
|
162
289
|
const onekeyDevices = devices.filter(dev => {
|
|
163
290
|
const isOneKey = hdShared.ONEKEY_WEBUSB_FILTER.some((desc) => dev.vendorId === desc.vendorId && dev.productId === desc.productId);
|
|
164
291
|
return isOneKey && !hdShared.isKnownTrezorWebUsbDevice(dev);
|
|
@@ -185,8 +312,16 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
185
312
|
acquire(input) {
|
|
186
313
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
187
314
|
return __awaiter(this, void 0, void 0, function* () {
|
|
315
|
+
this.assertRunning();
|
|
188
316
|
if (!input.path)
|
|
189
317
|
return;
|
|
318
|
+
if (this.identityProbe) {
|
|
319
|
+
yield this.getConnectedDevices();
|
|
320
|
+
this.claimIdentityProbeHandle(input.path, yield this.findDevice(input.path));
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
this.claimNormalHandle(input.path, yield this.findDevice(input.path));
|
|
324
|
+
}
|
|
190
325
|
try {
|
|
191
326
|
yield this.rotateProtocolV2UsbGeneration(input.path, 'WebUSB transport acquired');
|
|
192
327
|
yield this.closeOpenDevice(input.path);
|
|
@@ -236,19 +371,27 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
236
371
|
this.deviceProtocolHints.set(input.path, protocolHint);
|
|
237
372
|
}
|
|
238
373
|
const detectedProtocol = yield this.detectProtocol(input.path, input.expectedProtocol, protocolHint);
|
|
374
|
+
this.assertRunning();
|
|
239
375
|
this.confirmedDeviceProtocols.set(input.path, detectedProtocol);
|
|
240
376
|
const probedDevice = (_g = this.deviceList.find(d => d.path === input.path)) === null || _g === void 0 ? void 0 : _g.device;
|
|
241
377
|
if (probedDevice) {
|
|
242
378
|
this.probedDeviceObjects.set(input.path, probedDevice);
|
|
243
379
|
}
|
|
244
380
|
}
|
|
381
|
+
this.assertRunning();
|
|
245
382
|
this.acquiredPaths.add(input.path);
|
|
246
383
|
return yield Promise.resolve(input.path);
|
|
247
384
|
}
|
|
248
385
|
catch (e) {
|
|
249
386
|
this.Log.debug('acquire error: ', e instanceof Error ? `${e.name}: ${e.message}` : String(e));
|
|
250
387
|
this.acquiredPaths.delete(input.path);
|
|
251
|
-
|
|
388
|
+
try {
|
|
389
|
+
yield this.closeOpenDevice(input.path);
|
|
390
|
+
}
|
|
391
|
+
finally {
|
|
392
|
+
this.releaseIdentityProbeHandle(input.path);
|
|
393
|
+
this.releaseNormalHandles(input.path);
|
|
394
|
+
}
|
|
252
395
|
throw e;
|
|
253
396
|
}
|
|
254
397
|
});
|
|
@@ -328,10 +471,12 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
328
471
|
return __awaiter(this, void 0, void 0, function* () {
|
|
329
472
|
const maxRetries = 5;
|
|
330
473
|
for (let i = 0; i < maxRetries; i++) {
|
|
474
|
+
this.assertRunning();
|
|
331
475
|
try {
|
|
332
476
|
return yield this.connectToDevice(path, first);
|
|
333
477
|
}
|
|
334
478
|
catch (e) {
|
|
479
|
+
this.assertRunning();
|
|
335
480
|
if (e instanceof hdShared.HardwareError && e.errorCode === hdShared.HardwareErrorCode.BridgeNeedsPermission) {
|
|
336
481
|
throw e;
|
|
337
482
|
}
|
|
@@ -374,42 +519,68 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
374
519
|
connectToDevice(path, first) {
|
|
375
520
|
var _a;
|
|
376
521
|
return __awaiter(this, void 0, void 0, function* () {
|
|
522
|
+
this.assertRunning();
|
|
377
523
|
let device = yield this.findDevice(path);
|
|
524
|
+
if (this.identityProbe && this.identityProbeDevices.get(path) !== device) {
|
|
525
|
+
yield this.closeOpenDevice(path);
|
|
526
|
+
this.releaseIdentityProbeHandle(path);
|
|
527
|
+
this.claimIdentityProbeHandle(path, device);
|
|
528
|
+
}
|
|
529
|
+
if (!this.identityProbe)
|
|
530
|
+
this.claimNormalHandle(path, device);
|
|
531
|
+
this.assertHandleAvailable(device);
|
|
378
532
|
if (!device.opened) {
|
|
533
|
+
openingHandles.add(device);
|
|
379
534
|
try {
|
|
380
|
-
yield device.open();
|
|
535
|
+
yield this.runHandleOperation(() => device.open());
|
|
381
536
|
}
|
|
382
537
|
catch (error) {
|
|
383
|
-
return this.throwWebUsbIoError(path, 'open', error);
|
|
538
|
+
return yield this.throwWebUsbIoError(path, 'open', error);
|
|
539
|
+
}
|
|
540
|
+
finally {
|
|
541
|
+
openingHandles.delete(device);
|
|
384
542
|
}
|
|
385
543
|
}
|
|
386
544
|
if (first || this.deviceProtocol.get(path) !== 'V1') {
|
|
387
545
|
try {
|
|
388
|
-
yield device.reset();
|
|
546
|
+
yield this.runHandleOperation(() => device.reset());
|
|
389
547
|
}
|
|
390
548
|
catch (error) {
|
|
549
|
+
this.assertRunning();
|
|
391
550
|
(_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[WebUsbTransport] reset before claim failed, continuing:', error);
|
|
392
551
|
}
|
|
393
552
|
}
|
|
394
553
|
yield this.getConnectedDevices();
|
|
395
554
|
device = yield this.findDevice(path);
|
|
555
|
+
if (this.identityProbe && this.identityProbeDevices.get(path) !== device) {
|
|
556
|
+
yield this.closeOpenDevice(path);
|
|
557
|
+
this.releaseIdentityProbeHandle(path);
|
|
558
|
+
this.claimIdentityProbeHandle(path, device);
|
|
559
|
+
}
|
|
560
|
+
if (!this.identityProbe)
|
|
561
|
+
this.claimNormalHandle(path, device);
|
|
562
|
+
this.assertHandleAvailable(device);
|
|
396
563
|
if (!device.opened) {
|
|
564
|
+
openingHandles.add(device);
|
|
397
565
|
try {
|
|
398
|
-
yield device.open();
|
|
566
|
+
yield this.runHandleOperation(() => device.open());
|
|
399
567
|
}
|
|
400
568
|
catch (error) {
|
|
401
|
-
return this.throwWebUsbIoError(path, 'open', error);
|
|
569
|
+
return yield this.throwWebUsbIoError(path, 'open', error);
|
|
570
|
+
}
|
|
571
|
+
finally {
|
|
572
|
+
openingHandles.delete(device);
|
|
402
573
|
}
|
|
403
574
|
}
|
|
404
575
|
if (first ||
|
|
405
576
|
!device.configuration ||
|
|
406
577
|
device.configuration.configurationValue !== this.configurationId) {
|
|
407
|
-
yield device.selectConfiguration(this.configurationId);
|
|
578
|
+
yield this.runHandleOperation(() => device.selectConfiguration(this.configurationId));
|
|
408
579
|
}
|
|
409
580
|
const endpoints = this.discoverEndpoints(device);
|
|
410
581
|
this.deviceEndpoints.set(path, endpoints);
|
|
411
582
|
try {
|
|
412
|
-
yield device.claimInterface(endpoints.interfaceNumber);
|
|
583
|
+
yield this.runHandleOperation(() => device.claimInterface(endpoints.interfaceNumber));
|
|
413
584
|
}
|
|
414
585
|
catch (error) {
|
|
415
586
|
return this.throwWebUsbIoError(path, 'claimInterface', error);
|
|
@@ -418,40 +589,104 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
418
589
|
yield this.clearEndpointHalt(device, 'out', endpoints.endpointOut);
|
|
419
590
|
});
|
|
420
591
|
}
|
|
592
|
+
assertHandleAvailable(device) {
|
|
593
|
+
this.assertRunning();
|
|
594
|
+
const normalOwner = normalHandleOwners.get(device);
|
|
595
|
+
if ((normalOwner && normalOwner !== this) ||
|
|
596
|
+
(identityProbeHandles.has(device) &&
|
|
597
|
+
![...this.identityProbeDevices.values()].includes(device))) {
|
|
598
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, USB_DEVICE_IN_USE);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
claimNormalHandle(path, device) {
|
|
602
|
+
this.assertHandleAvailable(device);
|
|
603
|
+
normalHandleOwners.set(device, this);
|
|
604
|
+
this.normalDevices.set(device, path);
|
|
605
|
+
}
|
|
606
|
+
releaseNormalHandles(path) {
|
|
607
|
+
if (this.stopped)
|
|
608
|
+
return;
|
|
609
|
+
for (const [device, ownedPath] of this.normalDevices) {
|
|
610
|
+
if (ownedPath === path) {
|
|
611
|
+
normalHandleOwners.delete(device);
|
|
612
|
+
this.normalDevices.delete(device);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
isHandleOwnershipError(error) {
|
|
617
|
+
return (error instanceof hdShared.HardwareError &&
|
|
618
|
+
error.errorCode === hdShared.HardwareErrorCode.RuntimeError &&
|
|
619
|
+
this.getErrorMessage(error).includes(USB_DEVICE_IN_USE));
|
|
620
|
+
}
|
|
621
|
+
claimIdentityProbeHandle(path, device) {
|
|
622
|
+
this.assertRunning();
|
|
623
|
+
if (device.opened ||
|
|
624
|
+
openingHandles.has(device) ||
|
|
625
|
+
identityProbeHandles.has(device) ||
|
|
626
|
+
normalHandleOwners.has(device)) {
|
|
627
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, USB_DEVICE_IN_USE);
|
|
628
|
+
}
|
|
629
|
+
identityProbeHandles.add(device);
|
|
630
|
+
this.identityProbeDevices.set(path, device);
|
|
631
|
+
}
|
|
632
|
+
releaseIdentityProbeHandle(path) {
|
|
633
|
+
if (this.stopped)
|
|
634
|
+
return;
|
|
635
|
+
const device = this.identityProbeDevices.get(path);
|
|
636
|
+
if (device === null || device === void 0 ? void 0 : device.opened) {
|
|
637
|
+
this.identityProbeCleanupPaths.add(path);
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
if (device)
|
|
641
|
+
identityProbeHandles.delete(device);
|
|
642
|
+
this.identityProbeDevices.delete(path);
|
|
643
|
+
this.identityProbeCleanupPaths.delete(path);
|
|
644
|
+
}
|
|
421
645
|
closeOpenDevice(path) {
|
|
422
646
|
var _a, _b, _c, _d;
|
|
423
647
|
return __awaiter(this, void 0, void 0, function* () {
|
|
424
|
-
|
|
648
|
+
if (this.stopped)
|
|
649
|
+
return;
|
|
650
|
+
const current = this.identityProbe
|
|
651
|
+
? this.identityProbeDevices.get(path)
|
|
652
|
+
: (_a = this.deviceList.find(device => device.path === path)) === null || _a === void 0 ? void 0 : _a.device;
|
|
425
653
|
if (!(current === null || current === void 0 ? void 0 : current.opened))
|
|
426
654
|
return;
|
|
655
|
+
this.assertHandleAvailable(current);
|
|
427
656
|
const endpoints = this.deviceEndpoints.get(path);
|
|
428
657
|
const ifaceNum = (_b = endpoints === null || endpoints === void 0 ? void 0 : endpoints.interfaceNumber) !== null && _b !== void 0 ? _b : this.interfaceId;
|
|
429
658
|
try {
|
|
430
|
-
yield current.releaseInterface(ifaceNum);
|
|
659
|
+
yield this.runHandleOperation(() => current.releaseInterface(ifaceNum));
|
|
431
660
|
}
|
|
432
661
|
catch (error) {
|
|
433
662
|
(_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('[WebUsbTransport] releaseInterface before reconnect failed:', error);
|
|
434
663
|
}
|
|
664
|
+
this.assertHandleAvailable(current);
|
|
435
665
|
try {
|
|
436
|
-
yield current.close();
|
|
666
|
+
yield this.runHandleOperation(() => current.close());
|
|
437
667
|
}
|
|
438
668
|
catch (error) {
|
|
439
669
|
(_d = this.Log) === null || _d === void 0 ? void 0 : _d.debug('[WebUsbTransport] close before reconnect failed:', error);
|
|
670
|
+
if (this.identityProbe)
|
|
671
|
+
throw error;
|
|
440
672
|
}
|
|
441
673
|
});
|
|
442
674
|
}
|
|
443
675
|
clearEndpointHalt(device, direction, endpointNumber) {
|
|
444
676
|
var _a;
|
|
445
677
|
return __awaiter(this, void 0, void 0, function* () {
|
|
678
|
+
this.assertHandleAvailable(device);
|
|
446
679
|
try {
|
|
447
|
-
yield device.clearHalt(direction, endpointNumber);
|
|
680
|
+
yield this.runHandleOperation(() => device.clearHalt(direction, endpointNumber));
|
|
448
681
|
}
|
|
449
682
|
catch (error) {
|
|
683
|
+
this.assertRunning();
|
|
450
684
|
(_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[WebUsbTransport] clearHalt ${direction} endpoint ${endpointNumber} failed, continuing:`, error);
|
|
451
685
|
}
|
|
452
686
|
});
|
|
453
687
|
}
|
|
454
688
|
assertAcquired(path) {
|
|
689
|
+
this.assertRunning();
|
|
455
690
|
if (!this.acquiredPaths.has(path)) {
|
|
456
691
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device is not acquired for ${path}`);
|
|
457
692
|
}
|
|
@@ -508,7 +743,8 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
508
743
|
throwWebUsbIoError(path, operation, error) {
|
|
509
744
|
var _a;
|
|
510
745
|
return __awaiter(this, void 0, void 0, function* () {
|
|
511
|
-
|
|
746
|
+
this.assertRunning();
|
|
747
|
+
if (this.isHandleOwnershipError(error) || this.isWebUsbIoHardwareError(error))
|
|
512
748
|
throw error;
|
|
513
749
|
if (error instanceof transport.ProtocolV2LinkError && error.code !== 'io')
|
|
514
750
|
throw error;
|
|
@@ -542,7 +778,9 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
542
778
|
return /LIBUSB_ERROR_ACCESS|\b(?:access|permission) denied\b/i.test(message);
|
|
543
779
|
}
|
|
544
780
|
isRetryablePacketIoError(error) {
|
|
545
|
-
if (this.
|
|
781
|
+
if (this.stopped)
|
|
782
|
+
return false;
|
|
783
|
+
if (this.isHandleOwnershipError(error) || this.isWebUsbIoHardwareError(error))
|
|
546
784
|
return false;
|
|
547
785
|
const message = this.getErrorMessage(error).toLowerCase();
|
|
548
786
|
if (this.isWebUsbPermissionDeniedMessage(message))
|
|
@@ -561,21 +799,27 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
561
799
|
this.Log.debug(`[WebUsbTransport] transfer${direction} failed, retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(error)}`);
|
|
562
800
|
this.staleProtocolPaths.add(path);
|
|
563
801
|
yield hdShared.wait(attempt * PACKET_IO_RETRY_DELAY);
|
|
802
|
+
this.assertRunning();
|
|
564
803
|
try {
|
|
565
804
|
const currentDevice = yield this.findDevice(path);
|
|
805
|
+
this.assertHandleAvailable(currentDevice);
|
|
566
806
|
if (currentDevice.opened) {
|
|
567
807
|
const endpoints = this.deviceEndpoints.get(path);
|
|
568
808
|
const ifaceNum = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints.interfaceNumber) !== null && _a !== void 0 ? _a : this.interfaceId;
|
|
569
809
|
try {
|
|
570
|
-
yield currentDevice.releaseInterface(ifaceNum);
|
|
810
|
+
yield this.runHandleOperation(() => currentDevice.releaseInterface(ifaceNum));
|
|
571
811
|
}
|
|
572
812
|
catch (releaseError) {
|
|
573
813
|
this.Log.debug('[WebUsbTransport] releaseInterface before retry error:', releaseError);
|
|
574
814
|
}
|
|
575
|
-
|
|
815
|
+
this.assertHandleAvailable(currentDevice);
|
|
816
|
+
yield this.runHandleOperation(() => currentDevice.close());
|
|
576
817
|
}
|
|
577
818
|
}
|
|
578
819
|
catch (closeError) {
|
|
820
|
+
this.assertRunning();
|
|
821
|
+
if (this.isHandleOwnershipError(closeError))
|
|
822
|
+
throw closeError;
|
|
579
823
|
this.Log.debug('[WebUsbTransport] close device before retry error:', closeError);
|
|
580
824
|
}
|
|
581
825
|
yield this.getConnectedDevices();
|
|
@@ -617,6 +861,9 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
617
861
|
yield this.reconnectForPacketIoRetry(path, 'out', attempt, error);
|
|
618
862
|
}
|
|
619
863
|
catch (reconnectError) {
|
|
864
|
+
this.assertRunning();
|
|
865
|
+
if (this.isHandleOwnershipError(reconnectError))
|
|
866
|
+
throw reconnectError;
|
|
620
867
|
lastError = reconnectError;
|
|
621
868
|
this.Log.debug(`[WebUsbTransport] transferout reconnect failed on retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(reconnectError)}`);
|
|
622
869
|
}
|
|
@@ -635,7 +882,9 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
635
882
|
const endpoints = this.deviceEndpoints.get(path);
|
|
636
883
|
const endpointOut = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpointOut) !== null && _a !== void 0 ? _a : this.endpointId;
|
|
637
884
|
const transferBuffer = this.toArrayBuffer(packet.buffer.slice(packet.byteOffset, packet.byteOffset + packet.byteLength));
|
|
885
|
+
this.assertHandleAvailable(device);
|
|
638
886
|
const result = yield device.transferOut(endpointOut, transferBuffer);
|
|
887
|
+
this.assertHandleAvailable(device);
|
|
639
888
|
if (result.status !== 'ok') {
|
|
640
889
|
return this.throwWebUsbIoError(path, 'transferOut', new Error(`transferOut status: ${String(result.status)}`));
|
|
641
890
|
}
|
|
@@ -656,7 +905,9 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
656
905
|
}
|
|
657
906
|
const endpoints = this.deviceEndpoints.get(path);
|
|
658
907
|
const endpointIn = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpointIn) !== null && _a !== void 0 ? _a : this.endpointId;
|
|
908
|
+
this.assertHandleAvailable(device);
|
|
659
909
|
const result = yield device.transferIn(endpointIn, length);
|
|
910
|
+
this.assertHandleAvailable(device);
|
|
660
911
|
return this.getTransferInData(result);
|
|
661
912
|
}
|
|
662
913
|
catch (error) {
|
|
@@ -672,6 +923,9 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
672
923
|
yield this.reconnectForPacketIoRetry(path, 'in', attempt, error);
|
|
673
924
|
}
|
|
674
925
|
catch (reconnectError) {
|
|
926
|
+
this.assertRunning();
|
|
927
|
+
if (this.isHandleOwnershipError(reconnectError))
|
|
928
|
+
throw reconnectError;
|
|
675
929
|
lastError = reconnectError;
|
|
676
930
|
this.Log.debug(`[WebUsbTransport] transferin reconnect failed on retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(reconnectError)}`);
|
|
677
931
|
}
|
|
@@ -689,7 +943,9 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
689
943
|
}
|
|
690
944
|
const endpoints = this.deviceEndpoints.get(path);
|
|
691
945
|
const endpointIn = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpointIn) !== null && _a !== void 0 ? _a : this.endpointId;
|
|
946
|
+
this.assertHandleAvailable(device);
|
|
692
947
|
const result = yield device.transferIn(endpointIn, length);
|
|
948
|
+
this.assertHandleAvailable(device);
|
|
693
949
|
return this.getTransferInData(result);
|
|
694
950
|
});
|
|
695
951
|
}
|
|
@@ -749,10 +1005,10 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
749
1005
|
return false;
|
|
750
1006
|
}
|
|
751
1007
|
try {
|
|
752
|
-
yield this.callProtocolV1(path, 'Initialize', {}, {
|
|
1008
|
+
const response = yield this.callProtocolV1(path, this.identityProbe ? 'GetFeatures' : 'Initialize', {}, {
|
|
753
1009
|
timeoutMs: PROTOCOL_V1_PROBE_TIMEOUT,
|
|
754
1010
|
});
|
|
755
|
-
return
|
|
1011
|
+
return !this.identityProbe || response.type === 'Features';
|
|
756
1012
|
}
|
|
757
1013
|
catch (error) {
|
|
758
1014
|
if (this.isWebUsbIoHardwareError(error))
|
|
@@ -869,8 +1125,14 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
|
|
|
869
1125
|
release(path) {
|
|
870
1126
|
return __awaiter(this, void 0, void 0, function* () {
|
|
871
1127
|
this.acquiredPaths.delete(path);
|
|
872
|
-
|
|
873
|
-
|
|
1128
|
+
try {
|
|
1129
|
+
yield this.invalidateProtocolV2UsbLink(path, 'WebUSB transport released');
|
|
1130
|
+
yield this.closeOpenDevice(path);
|
|
1131
|
+
}
|
|
1132
|
+
finally {
|
|
1133
|
+
this.releaseIdentityProbeHandle(path);
|
|
1134
|
+
this.releaseNormalHandles(path);
|
|
1135
|
+
}
|
|
874
1136
|
this.deviceEndpoints.delete(path);
|
|
875
1137
|
});
|
|
876
1138
|
}
|
|
@@ -1001,11 +1263,14 @@ class ElectronBleTransport {
|
|
|
1001
1263
|
if (error.code === hdShared.HardwareErrorCode.BlePermissionError) {
|
|
1002
1264
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError);
|
|
1003
1265
|
}
|
|
1266
|
+
if (error.code === hdShared.HardwareErrorCode.BleLocationError) {
|
|
1267
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationError);
|
|
1268
|
+
}
|
|
1004
1269
|
}
|
|
1005
1270
|
const errorMessage = error.message || String(error);
|
|
1006
1271
|
const poweredOffMessage = hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.BlePoweredOff];
|
|
1007
1272
|
const unsupportedMessage = hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.BleUnsupported];
|
|
1008
|
-
const permissionMessage = hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.
|
|
1273
|
+
const permissionMessage = hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.BleLocationError];
|
|
1009
1274
|
if (errorMessage.includes(poweredOffMessage) || errorMessage.includes('poweredOff')) {
|
|
1010
1275
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePoweredOff);
|
|
1011
1276
|
}
|
|
@@ -1013,7 +1278,7 @@ class ElectronBleTransport {
|
|
|
1013
1278
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleUnsupported);
|
|
1014
1279
|
}
|
|
1015
1280
|
if (errorMessage.includes(permissionMessage) || errorMessage.includes('unauthorized')) {
|
|
1016
|
-
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.
|
|
1281
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationError);
|
|
1017
1282
|
}
|
|
1018
1283
|
}
|
|
1019
1284
|
return error;
|