@onekeyfe/hd-transport-web-device 1.2.0-alpha.11 → 1.2.0-alpha.13

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.
@@ -0,0 +1,40 @@
1
+ import transport, { ProtocolV2FrameAssembler } from '@onekeyfe/hd-transport';
2
+
3
+ import WebUsbTransport from '../src/webusb';
4
+
5
+ const schema = {
6
+ nested: {
7
+ Ping: { fields: { message: { type: 'string', id: 1 } } },
8
+ Success: { fields: { message: { type: 'string', id: 1 } } },
9
+ MessageType: {
10
+ values: {
11
+ MessageType_Ping: 60206,
12
+ MessageType_Success: 60207,
13
+ },
14
+ },
15
+ },
16
+ };
17
+
18
+ describe('WebUsbTransport Protocol V2 timeout recovery', () => {
19
+ test('invalidates and resets the cached connection before another call can start', async () => {
20
+ const webusb = new WebUsbTransport() as any;
21
+ const path = 'pro2-webusb';
22
+ webusb.messages = transport.parseConfigure(schema);
23
+ webusb.messagesV2 = transport.parseConfigure(schema);
24
+ webusb.protocolV2Assemblers.set(path, new ProtocolV2FrameAssembler());
25
+ webusb.transferOutOnce = jest.fn().mockResolvedValue(undefined);
26
+ webusb.receiveProtocolV2Frame = jest.fn(() => new Promise(() => undefined));
27
+ webusb.resetConnectionAfterProbe = jest.fn().mockImplementation(async () => {
28
+ webusb.protocolV2Sessions.delete(path);
29
+ webusb.protocolV2ReadTimeouts.delete(path);
30
+ webusb.protocolV2Assemblers.get(path)?.reset();
31
+ });
32
+
33
+ await expect(
34
+ webusb.callProtocolV2(path, 'Ping', { message: 'timeout' }, { timeoutMs: 10 })
35
+ ).rejects.toThrow('timeout');
36
+
37
+ expect(webusb.resetConnectionAfterProbe).toHaveBeenCalledWith(path);
38
+ expect(webusb.protocolV2Sessions.has(path)).toBe(false);
39
+ });
40
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":";AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnG,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AAevC,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;CACjC,CAAC;AAqCF,MAAM,CAAC,OAAO,OAAO,oBAAoB;IACvC,OAAO,CAAC,SAAS,CAA0D;IAE3E,OAAO,CAAC,WAAW,CAA0D;IAE7E,IAAI,SAA0B;IAE9B,UAAU,UAAS;IAEnB,UAAU,EAAE,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,IAAI,CAAQ;IAExD,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,OAAO,CAAC,gBAAgB,CAA0B;IAElD,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAEnE,OAAO,CAAC,SAAS,CAAsE;IAEvF,OAAO,CAAC,YAAY,CAAoD;IAExE,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO,CAAC,eAAe,CAAgD;IAEvE,OAAO,CAAC,eAAe,CAmBpB;IAEH,OAAO,CAAC,oBAAoB,CAAsC;IAElE,OAAO,CAAC,kBAAkB,CAAsC;IAEhE,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,qBAAqB,CAAK;IAElC,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,kBAAkB;IA0B1B,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY;IAcxC,SAAS,CAAC,UAAU,EAAE,GAAG;IAKzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAQ7B,MAAM;IAIN,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAqBxC,OAAO,CAAC,KAAK,EAAE,eAAe;;;;;;;;;;;IA0F9B,OAAO,CAAC,EAAE,EAAE,MAAM;IAgBxB,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;YAMZ,cAAc;IA+C5B,OAAO,CAAC,8BAA8B;YAgBxB,iCAAiC;YAqCjC,eAAe;YAgBf,eAAe;YAuBf,iBAAiB;YAsBjB,SAAS;IASvB,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,sBAAsB;YAShB,mBAAmB;IAiBjC,OAAO,CAAC,4BAA4B;IAgB9B,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YA+BlB,cAAc;YAuEd,cAAc;IA6B5B,OAAO,CAAC,uBAAuB;IA0C/B,OAAO,CAAC,6BAA6B;IAsCrC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
1
+ {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":";AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnG,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;CACjC,CAAC;AAqCF,MAAM,CAAC,OAAO,OAAO,oBAAoB;IACvC,OAAO,CAAC,SAAS,CAA0D;IAE3E,OAAO,CAAC,WAAW,CAA0D;IAE7E,IAAI,SAA0B;IAE9B,UAAU,UAAS;IAEnB,UAAU,EAAE,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,IAAI,CAAQ;IAExD,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,OAAO,CAAC,gBAAgB,CAA0B;IAElD,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAEnE,OAAO,CAAC,SAAS,CAAsE;IAEvF,OAAO,CAAC,YAAY,CAAoD;IAExE,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO,CAAC,eAAe,CAAgD;IAEvE,OAAO,CAAC,eAAe,CAmBpB;IAEH,OAAO,CAAC,oBAAoB,CAAsC;IAElE,OAAO,CAAC,kBAAkB,CAAsC;IAEhE,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,qBAAqB,CAAK;IAElC,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,kBAAkB;IA0B1B,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY;IAcxC,SAAS,CAAC,UAAU,EAAE,GAAG;IAKzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAO7B,MAAM;IAIN,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAqBxC,OAAO,CAAC,KAAK,EAAE,eAAe;;;;;;;;;;;IA0F9B,OAAO,CAAC,EAAE,EAAE,MAAM;IAgBxB,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;YAMZ,cAAc;IA+C5B,OAAO,CAAC,8BAA8B;YAgBxB,iCAAiC;YAqCjC,eAAe;YAgBf,eAAe;YAuBf,iBAAiB;YAsBjB,SAAS;IASvB,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,sBAAsB;YAShB,mBAAmB;IAiBjC,OAAO,CAAC,4BAA4B;IAgB9B,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YA2BlB,cAAc;YAuEd,cAAc;IA6B5B,OAAO,CAAC,uBAAuB;IA0C/B,OAAO,CAAC,6BAA6B;IAsCrC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
package/dist/index.js CHANGED
@@ -41,6 +41,14 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
41
41
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
42
42
  };
43
43
 
44
+ const HIGH_VOLUME_CALLS = new Set(['FileWrite', 'FilesystemFileWrite', 'EmmcFileWrite']);
45
+ function shouldSuppressHighVolumeCallLog(name) {
46
+ return HIGH_VOLUME_CALLS.has(name);
47
+ }
48
+ function createTransportCallLog(name, protocol) {
49
+ return { name, protocol };
50
+ }
51
+
44
52
  const { parseConfigure: parseConfigure$1, check: check$1, ProtocolV1: ProtocolV1$1 } = transport__default["default"];
45
53
  const CONFIGURATION_ID = 1;
46
54
  const INTERFACE_ID = 0;
@@ -52,19 +60,6 @@ const HEADER_LENGTH = transport.PROTOCOL_V1_MESSAGE_HEADER_SIZE;
52
60
  const PACKET_IO_MAX_RETRIES = 3;
53
61
  const PACKET_IO_RETRY_DELAY = 300;
54
62
  const PROTOCOL_PROBE_TIMEOUT = 1000;
55
- const WEBUSB_FILE_WRITE_LOG_BLOCK_PATTERN = /(?:^|[^a-z])(?:raw)?(?:filesystem|emmc)?filewrite$/i;
56
- function shouldSuppressWebUsbCallLog(name) {
57
- const normalized = name.replace(/[_\s-]/g, '');
58
- return WEBUSB_FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
59
- }
60
- function isLogBlockCommand$1(name) {
61
- var _a, _b;
62
- return (_b = (_a = transport.LogBlockCommand === null || transport.LogBlockCommand === void 0 ? void 0 : transport.LogBlockCommand.has) === null || _a === void 0 ? void 0 : _a.call(transport.LogBlockCommand, name)) !== null && _b !== void 0 ? _b : false;
63
- }
64
- function shouldBlockWebUsbCallDataLog(name) {
65
- const normalized = name.replace(/[_\s-]/g, '');
66
- return isLogBlockCommand$1(name) || WEBUSB_FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
67
- }
68
63
  function inferProtocolHintFromDeviceName$1(name) {
69
64
  return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
70
65
  }
@@ -100,11 +95,9 @@ class WebUsbTransport {
100
95
  this.messages = messages;
101
96
  }
102
97
  configureProtocolV2(signedData) {
103
- var _a;
104
98
  this.messagesV2 = parseConfigure$1(signedData);
105
99
  this.protocolV2Sessions.clear();
106
100
  this.protocolV2ReadTimeouts.clear();
107
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[WebUsbTransport] Protocol V2 schema configured');
108
101
  }
109
102
  promptDeviceAccess() {
110
103
  return __awaiter(this, void 0, void 0, function* () {
@@ -145,7 +138,10 @@ class WebUsbTransport {
145
138
  if (!this.usb)
146
139
  return [];
147
140
  const devices = yield this.usb.getDevices();
148
- const onekeyDevices = devices.filter(dev => hdShared.ONEKEY_WEBUSB_FILTER.some(desc => dev.vendorId === desc.vendorId && dev.productId === desc.productId));
141
+ const onekeyDevices = devices.filter(dev => {
142
+ const isOneKey = hdShared.ONEKEY_WEBUSB_FILTER.some((desc) => dev.vendorId === desc.vendorId && dev.productId === desc.productId);
143
+ return isOneKey && !hdShared.isKnownTrezorWebUsbDevice(dev);
144
+ });
149
145
  this.deviceList = onekeyDevices.map(device => {
150
146
  const path = this.getDevicePath(device);
151
147
  const protocolHint = inferProtocolHintFromDeviceName$1(device.productName);
@@ -158,10 +154,6 @@ class WebUsbTransport {
158
154
  commType: 'webusb',
159
155
  };
160
156
  });
161
- for (const dev of onekeyDevices) {
162
- this.Log.debug(`[WebUSB] Device: name="${dev.productName}" serial="${dev.serialNumber}" ` +
163
- `VID=0x${dev.vendorId.toString(16)} PID=0x${dev.productId.toString(16)}`);
164
- }
165
157
  return this.deviceList;
166
158
  });
167
159
  }
@@ -200,14 +192,12 @@ class WebUsbTransport {
200
192
  if (expectedProtocol === 'V1') {
201
193
  if (yield this.probeProtocolV1(path)) {
202
194
  this.deviceProtocol.set(path, 'V1');
203
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> V1 (expected)`);
204
195
  return 'V1';
205
196
  }
206
197
  throw this.createProtocolMismatchError(expectedProtocol);
207
198
  }
208
199
  if (expectedProtocol === 'V2') {
209
200
  this.deviceProtocol.set(path, 'V2');
210
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> V2 (expected)`);
211
201
  return 'V2';
212
202
  }
213
203
  const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(path) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
@@ -215,7 +205,6 @@ class WebUsbTransport {
215
205
  const detected = protocol === 'V1' ? yield this.probeProtocolV1(path) : yield this.probeProtocolV2(path);
216
206
  if (detected) {
217
207
  this.deviceProtocol.set(path, protocol);
218
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> ${protocol}`);
219
208
  return protocol;
220
209
  }
221
210
  }
@@ -287,7 +276,6 @@ class WebUsbTransport {
287
276
  var _a, _b;
288
277
  return __awaiter(this, void 0, void 0, function* () {
289
278
  let device = yield this.findDevice(path);
290
- this.Log.debug('[WebUsbTransport] connecting to device:', device.productName, 'PID:', device.productId);
291
279
  if (!device.opened) {
292
280
  yield device.open();
293
281
  }
@@ -524,7 +512,7 @@ class WebUsbTransport {
524
512
  yield this.connect(path, false);
525
513
  });
526
514
  }
527
- withProtocolReadTimeout(path, promise, timeoutMs, protocol, onTimeout) {
515
+ withProtocolReadTimeout(_path, promise, timeoutMs, protocol, onTimeout) {
528
516
  return __awaiter(this, void 0, void 0, function* () {
529
517
  let timer;
530
518
  let timedOut = false;
@@ -539,11 +527,11 @@ class WebUsbTransport {
539
527
  return yield Promise.race([
540
528
  guardedPromise,
541
529
  new Promise((_, reject) => {
542
- timer = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
530
+ timer = setTimeout(() => {
543
531
  timedOut = true;
544
532
  onTimeout === null || onTimeout === void 0 ? void 0 : onTimeout();
545
533
  reject(new Error(`Protocol ${protocol} read timeout after ${timeoutMs}ms`));
546
- }), timeoutMs);
534
+ }, timeoutMs);
547
535
  }),
548
536
  ]);
549
537
  }
@@ -562,8 +550,7 @@ class WebUsbTransport {
562
550
  yield this.callProtocolV1(path, 'Initialize', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT });
563
551
  return true;
564
552
  }
565
- catch (error) {
566
- this.Log.debug('[WebUsbTransport] Protocol V1 Initialize probe failed:', error);
553
+ catch (_error) {
567
554
  return false;
568
555
  }
569
556
  });
@@ -595,12 +582,8 @@ class WebUsbTransport {
595
582
  if (!protocol) {
596
583
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${path}`);
597
584
  }
598
- if (shouldSuppressWebUsbCallLog(name)) ;
599
- else if (shouldBlockWebUsbCallDataLog(name)) {
600
- this.Log.debug('call-', ' name: ', name, ' protocol: ', protocol);
601
- }
602
- else {
603
- this.Log.debug('call-', ' name: ', name, ' data: ', data, ' protocol: ', protocol);
585
+ if (!shouldSuppressHighVolumeCallLog(name)) {
586
+ this.Log.debug('transport call', createTransportCallLog(name, protocol));
604
587
  }
605
588
  if (protocol === 'V2') {
606
589
  return this.callProtocolV2(path, name, data, options);
@@ -660,6 +643,18 @@ class WebUsbTransport {
660
643
  try {
661
644
  return yield session.call(name, data, options);
662
645
  }
646
+ catch (error) {
647
+ const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
648
+ if (message.includes('protocol v2 read timeout') || message.includes('response timeout')) {
649
+ try {
650
+ yield this.resetConnectionAfterProbe(path);
651
+ }
652
+ catch (resetError) {
653
+ this.Log.debug('[WebUsbTransport] Protocol V2 timeout reset failed:', resetError);
654
+ }
655
+ }
656
+ throw error;
657
+ }
663
658
  finally {
664
659
  this.protocolV2ReadTimeouts.delete(path);
665
660
  }
@@ -742,6 +737,8 @@ class WebUsbTransport {
742
737
  this.deviceProtocolHints.delete(path);
743
738
  (_b = this.protocolV2Assemblers.get(path)) === null || _b === void 0 ? void 0 : _b.reset();
744
739
  this.protocolV2Assemblers.delete(path);
740
+ this.protocolV2Sessions.delete(path);
741
+ this.protocolV2ReadTimeouts.delete(path);
745
742
  this.deviceEndpoints.delete(path);
746
743
  });
747
744
  }
@@ -750,15 +747,6 @@ class WebUsbTransport {
750
747
  }
751
748
  }
752
749
 
753
- const FILE_WRITE_LOG_BLOCK_PATTERN = /(?:^|[^a-z])(?:raw)?(?:filesystem|emmc)?filewrite$/i;
754
- function shouldSuppressHighVolumeCallLog(name) {
755
- const normalized = name.replace(/[_\s-]/g, '');
756
- return FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
757
- }
758
- function isLogBlockCommand(name) {
759
- var _a, _b;
760
- return (_b = (_a = transport.LogBlockCommand === null || transport.LogBlockCommand === void 0 ? void 0 : transport.LogBlockCommand.has) === null || _a === void 0 ? void 0 : _a.call(transport.LogBlockCommand, name)) !== null && _b !== void 0 ? _b : false;
761
- }
762
750
  const { parseConfigure, ProtocolV1, check } = transport__default["default"];
763
751
  function inferProtocolHintFromDeviceName(name) {
764
752
  return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
@@ -871,12 +859,10 @@ class ElectronBleTransport {
871
859
  this.configured = true;
872
860
  }
873
861
  configureProtocolV2(signedData) {
874
- var _a;
875
862
  this._messagesV2 = parseConfigure(signedData);
876
863
  this.protocolV2Links
877
864
  .invalidateAllLinks('Protocol V2 schema reconfigured')
878
865
  .catch(error => { var _a; return (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] schema link cleanup failed:', error); });
879
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] Protocol V2 schema configured');
880
866
  }
881
867
  listen() {
882
868
  return __awaiter(this, void 0, void 0, function* () {
@@ -1281,7 +1267,7 @@ class ElectronBleTransport {
1281
1267
  }
1282
1268
  }
1283
1269
  call(uuid, name, data, options) {
1284
- var _a, _b;
1270
+ var _a;
1285
1271
  return __awaiter(this, void 0, void 0, function* () {
1286
1272
  if (!this._messages) {
1287
1273
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
@@ -1293,12 +1279,8 @@ class ElectronBleTransport {
1293
1279
  if (!protocol) {
1294
1280
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${uuid}`);
1295
1281
  }
1296
- if (shouldSuppressHighVolumeCallLog(name)) ;
1297
- else if (isLogBlockCommand(name)) {
1298
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] call', 'name:', name, 'protocol:', protocol);
1299
- }
1300
- else {
1301
- (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Electron BLE] call', 'name:', name, 'data:', data, 'protocol:', protocol);
1282
+ if (!shouldSuppressHighVolumeCallLog(name)) {
1283
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('transport call', createTransportCallLog(name, protocol));
1302
1284
  }
1303
1285
  if (protocol === 'V2') {
1304
1286
  return this.callProtocolV2(uuid, name, data, options);
@@ -0,0 +1,7 @@
1
+ import type { ProtocolType } from '@onekeyfe/hd-transport';
2
+ export declare function shouldSuppressHighVolumeCallLog(name: string): boolean;
3
+ export declare function createTransportCallLog(name: string, protocol: ProtocolType): {
4
+ name: string;
5
+ protocol: ProtocolType;
6
+ };
7
+ //# sourceMappingURL=transportLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transportLog.d.ts","sourceRoot":"","sources":["../src/transportLog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,WAE3D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY;;;EAE1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"webusb.d.ts","sourceRoot":"","sources":["../src/webusb.ts"],"names":[],"mappings":";AACA,OAAO,SAWN,MAAM,wBAAwB,CAAC;AAIhC,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAqChC,MAAM,WAAW,UAAW,SAAQ,oBAAoB;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAaD,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,QAAQ,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAGlE,UAAU,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAGpE,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAGnE,OAAO,CAAC,oBAAoB,CAAoD;IAGhF,OAAO,CAAC,kBAAkB,CAA6C;IAGvE,OAAO,CAAC,sBAAsB,CAA8C;IAG5E,OAAO,CAAC,eAAe,CAA2C;IAOlE,OAAO,CAAC,eAAe,CAA6C;IAEpE,OAAO,CAAC,iBAAiB,CAAK;IAE9B,IAAI,SAAqB;IAEzB,OAAO,UAAS;IAEhB,UAAU,UAAS;IAEnB,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,GAAG,CAAC,EAAE,GAAG,CAAC;IAMV,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAM;IAEnC,eAAe,SAAoB;IAEnC,UAAU,SAAe;IAEzB,WAAW,SAAgB;IAK3B,IAAI,CAAC,MAAM,EAAE,GAAG;IAgBhB,SAAS,CAAC,UAAU,EAAE,GAAG;IASzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAY7B,kBAAkB;IAmBlB,SAAS;IASf,OAAO,CAAC,aAAa;IAmBf,mBAAmB;IAsCnB,OAAO,CAAC,KAAK,EAAE,YAAY;IA0BjC,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;YAOtB,cAAc;IA6CtB,UAAU,CAAC,IAAI,EAAE,MAAM;IAwBvB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAkB1C,OAAO,CAAC,iBAAiB;IAiCnB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;YA0CpC,eAAe;YAmBf,iBAAiB;IAezB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIvE,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,wBAAwB;YAalB,yBAAyB;IAiCvC,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,aAAa;YASP,oBAAoB;YA2BpB,eAAe;YAaf,mBAAmB;YA2CnB,yBAAyB;YAyBzB,uBAAuB;YAoCvB,eAAe;YAcf,eAAe;IAiBvB,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YAkClB,cAAc;YAkCd,cAAc;YA4Cd,sBAAsB;IA4C9B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAgD5C,OAAO,CAAC,IAAI,EAAE,MAAM;IAiB1B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
1
+ {"version":3,"file":"webusb.d.ts","sourceRoot":"","sources":["../src/webusb.ts"],"names":[],"mappings":";AACA,OAAO,SAUN,MAAM,wBAAwB,CAAC;AAYhC,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAqBhC,MAAM,WAAW,UAAW,SAAQ,oBAAoB;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAaD,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,QAAQ,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAGlE,UAAU,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAGpE,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAGnE,OAAO,CAAC,oBAAoB,CAAoD;IAGhF,OAAO,CAAC,kBAAkB,CAA6C;IAGvE,OAAO,CAAC,sBAAsB,CAA8C;IAG5E,OAAO,CAAC,eAAe,CAA2C;IAOlE,OAAO,CAAC,eAAe,CAA6C;IAEpE,OAAO,CAAC,iBAAiB,CAAK;IAE9B,IAAI,SAAqB;IAEzB,OAAO,UAAS;IAEhB,UAAU,UAAS;IAEnB,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,GAAG,CAAC,EAAE,GAAG,CAAC;IAMV,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAM;IAEnC,eAAe,SAAoB;IAEnC,UAAU,SAAe;IAEzB,WAAW,SAAgB;IAK3B,IAAI,CAAC,MAAM,EAAE,GAAG;IAgBhB,SAAS,CAAC,UAAU,EAAE,GAAG;IASzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAW7B,kBAAkB;IAmBlB,SAAS;IASf,OAAO,CAAC,aAAa;IAmBf,mBAAmB;IAgCnB,OAAO,CAAC,KAAK,EAAE,YAAY;IA0BjC,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;YAOtB,cAAc;IA0CtB,UAAU,CAAC,IAAI,EAAE,MAAM;IAwBvB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAkB1C,OAAO,CAAC,iBAAiB;IAiCnB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;YAmCpC,eAAe;YAmBf,iBAAiB;IAezB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIvE,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,wBAAwB;YAalB,yBAAyB;IAiCvC,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,aAAa;YASP,oBAAoB;YA2BpB,eAAe;YAaf,mBAAmB;YA2CnB,yBAAyB;YAyBzB,uBAAuB;YAmCvB,eAAe;YAaf,eAAe;IAiBvB,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YA8BlB,cAAc;YAkCd,cAAc;YAuDd,sBAAsB;IA4C9B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAgD5C,OAAO,CAAC,IAAI,EAAE,MAAM;IAmB1B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-web-device",
3
- "version": "1.2.0-alpha.11",
3
+ "version": "1.2.0-alpha.13",
4
4
  "author": "OneKey",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -20,13 +20,13 @@
20
20
  "lint:fix": "eslint . --fix"
21
21
  },
22
22
  "dependencies": {
23
- "@onekeyfe/hd-shared": "1.2.0-alpha.11",
24
- "@onekeyfe/hd-transport": "1.2.0-alpha.11"
23
+ "@onekeyfe/hd-shared": "1.2.0-alpha.13",
24
+ "@onekeyfe/hd-transport": "1.2.0-alpha.13"
25
25
  },
26
26
  "devDependencies": {
27
- "@onekeyfe/hd-transport-electron": "1.2.0-alpha.11",
27
+ "@onekeyfe/hd-transport-electron": "1.2.0-alpha.13",
28
28
  "@types/w3c-web-usb": "^1.0.6",
29
29
  "@types/web-bluetooth": "^0.0.17"
30
30
  },
31
- "gitHead": "05d3421ec00e07e99f6665e6436a612503e32dfc"
31
+ "gitHead": "a907a7ec140123107f6188b37550a7143f1e0d91"
32
32
  }
@@ -1,5 +1,4 @@
1
1
  import transport, {
2
- LogBlockCommand,
3
2
  PROTOCOL_V1_MESSAGE_HEADER_SIZE,
4
3
  PROTOCOL_V2_CHANNEL_BLE_UART,
5
4
  ProtocolV2FrameAssembler,
@@ -17,22 +16,13 @@ import {
17
16
  wait,
18
17
  } from '@onekeyfe/hd-shared';
19
18
 
19
+ import { createTransportCallLog, shouldSuppressHighVolumeCallLog } from './transportLog';
20
+
20
21
  import type { Deferred } from '@onekeyfe/hd-shared';
21
22
  import type { DesktopAPI } from '@onekeyfe/hd-transport-electron';
22
23
  import type { OneKeyDeviceInfo, ProtocolType, TransportCallOptions } from '@onekeyfe/hd-transport';
23
24
  import type EventEmitter from 'events';
24
25
 
25
- const FILE_WRITE_LOG_BLOCK_PATTERN = /(?:^|[^a-z])(?:raw)?(?:filesystem|emmc)?filewrite$/i;
26
-
27
- function shouldSuppressHighVolumeCallLog(name: string) {
28
- const normalized = name.replace(/[_\s-]/g, '');
29
- return FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
30
- }
31
-
32
- function isLogBlockCommand(name: string) {
33
- return (LogBlockCommand as Set<string> | undefined)?.has?.(name) ?? false;
34
- }
35
-
36
26
  const { parseConfigure, ProtocolV1, check } = transport;
37
27
 
38
28
  declare global {
@@ -221,7 +211,6 @@ export default class ElectronBleTransport {
221
211
  this.protocolV2Links
222
212
  .invalidateAllLinks('Protocol V2 schema reconfigured')
223
213
  .catch(error => this.Log?.debug('[Electron BLE] schema link cleanup failed:', error));
224
- this.Log?.debug('[Electron BLE] Protocol V2 schema configured');
225
214
  }
226
215
 
227
216
  async listen() {
@@ -682,12 +671,8 @@ export default class ElectronBleTransport {
682
671
  `Device protocol has not been detected for ${uuid}`
683
672
  );
684
673
  }
685
- if (shouldSuppressHighVolumeCallLog(name)) {
686
- // 高频文件写入不要逐包发 debug 事件,否则调试日志会反向拖慢传输。
687
- } else if (isLogBlockCommand(name)) {
688
- this.Log?.debug('[Electron BLE] call', 'name:', name, 'protocol:', protocol);
689
- } else {
690
- this.Log?.debug('[Electron BLE] call', 'name:', name, 'data:', data, 'protocol:', protocol);
674
+ if (!shouldSuppressHighVolumeCallLog(name)) {
675
+ this.Log?.debug('transport call', createTransportCallLog(name, protocol));
691
676
  }
692
677
 
693
678
  if (protocol === 'V2') {
@@ -0,0 +1,11 @@
1
+ import type { ProtocolType } from '@onekeyfe/hd-transport';
2
+
3
+ const HIGH_VOLUME_CALLS = new Set(['FileWrite', 'FilesystemFileWrite', 'EmmcFileWrite']);
4
+
5
+ export function shouldSuppressHighVolumeCallLog(name: string) {
6
+ return HIGH_VOLUME_CALLS.has(name);
7
+ }
8
+
9
+ export function createTransportCallLog(name: string, protocol: ProtocolType) {
10
+ return { name, protocol };
11
+ }
package/src/webusb.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable no-undef */
2
2
  import transport, {
3
- LogBlockCommand,
4
3
  PROTOCOL_V1_CHUNK_PAYLOAD_SIZE,
5
4
  PROTOCOL_V1_MESSAGE_HEADER_SIZE,
6
5
  PROTOCOL_V1_REPORT_ID,
@@ -11,9 +10,17 @@ import transport, {
11
10
  ProtocolV2Session,
12
11
  probeProtocolV2 as probeProtocolV2Helper,
13
12
  } from '@onekeyfe/hd-transport';
14
- import { ERRORS, HardwareErrorCode, ONEKEY_WEBUSB_FILTER, wait } from '@onekeyfe/hd-shared';
13
+ import {
14
+ ERRORS,
15
+ HardwareErrorCode,
16
+ ONEKEY_WEBUSB_FILTER,
17
+ isKnownTrezorWebUsbDevice,
18
+ wait,
19
+ } from '@onekeyfe/hd-shared';
15
20
  import ByteBuffer from 'bytebuffer';
16
21
 
22
+ import { createTransportCallLog, shouldSuppressHighVolumeCallLog } from './transportLog';
23
+
17
24
  import type {
18
25
  AcquireInput,
19
26
  OneKeyDeviceInfoBase,
@@ -33,22 +40,6 @@ const HEADER_LENGTH = PROTOCOL_V1_MESSAGE_HEADER_SIZE;
33
40
  const PACKET_IO_MAX_RETRIES = 3;
34
41
  const PACKET_IO_RETRY_DELAY = 300;
35
42
  const PROTOCOL_PROBE_TIMEOUT = 1000;
36
- const WEBUSB_FILE_WRITE_LOG_BLOCK_PATTERN = /(?:^|[^a-z])(?:raw)?(?:filesystem|emmc)?filewrite$/i;
37
-
38
- function shouldSuppressWebUsbCallLog(name: string) {
39
- const normalized = name.replace(/[_\s-]/g, '');
40
- return WEBUSB_FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
41
- }
42
-
43
- function isLogBlockCommand(name: string) {
44
- return (LogBlockCommand as Set<string> | undefined)?.has?.(name) ?? false;
45
- }
46
-
47
- function shouldBlockWebUsbCallDataLog(name: string) {
48
- const normalized = name.replace(/[_\s-]/g, '');
49
- return isLogBlockCommand(name) || WEBUSB_FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
50
- }
51
-
52
43
  function inferProtocolHintFromDeviceName(name?: string | null): ProtocolType | undefined {
53
44
  return /\bpro\s*2\b/i.test(name ?? '') ? 'V2' : undefined;
54
45
  }
@@ -159,7 +150,6 @@ export default class WebUsbTransport {
159
150
  this.messagesV2 = parseConfigure(signedData);
160
151
  this.protocolV2Sessions.clear();
161
152
  this.protocolV2ReadTimeouts.clear();
162
- this.Log?.debug('[WebUsbTransport] Protocol V2 schema configured');
163
153
  }
164
154
 
165
155
  /**
@@ -218,11 +208,13 @@ export default class WebUsbTransport {
218
208
  if (!this.usb) return [];
219
209
 
220
210
  const devices = await this.usb.getDevices();
221
- const onekeyDevices = devices.filter(dev =>
222
- ONEKEY_WEBUSB_FILTER.some(
223
- desc => dev.vendorId === desc.vendorId && dev.productId === desc.productId
224
- )
225
- );
211
+ const onekeyDevices = devices.filter(dev => {
212
+ const isOneKey = ONEKEY_WEBUSB_FILTER.some(
213
+ (desc: { vendorId: number; productId: number }) =>
214
+ dev.vendorId === desc.vendorId && dev.productId === desc.productId
215
+ );
216
+ return isOneKey && !isKnownTrezorWebUsbDevice(dev);
217
+ });
226
218
 
227
219
  this.deviceList = onekeyDevices.map(device => {
228
220
  const path = this.getDevicePath(device);
@@ -238,14 +230,6 @@ export default class WebUsbTransport {
238
230
  };
239
231
  });
240
232
 
241
- // Debug: log all discovered devices. Protocol is detected after acquire via wire probe.
242
- for (const dev of onekeyDevices) {
243
- this.Log.debug(
244
- `[WebUSB] Device: name="${dev.productName}" serial="${dev.serialNumber}" ` +
245
- `VID=0x${dev.vendorId.toString(16)} PID=0x${dev.productId.toString(16)}`
246
- );
247
- }
248
-
249
233
  return this.deviceList;
250
234
  }
251
235
 
@@ -300,7 +284,6 @@ export default class WebUsbTransport {
300
284
  if (expectedProtocol === 'V1') {
301
285
  if (await this.probeProtocolV1(path)) {
302
286
  this.deviceProtocol.set(path, 'V1');
303
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> V1 (expected)`);
304
287
  return 'V1';
305
288
  }
306
289
  throw this.createProtocolMismatchError(expectedProtocol);
@@ -310,7 +293,6 @@ export default class WebUsbTransport {
310
293
  // 免探测路径:调用方显式承诺该设备是 V2(例如固件升级重启后的重连场景,
311
294
  // 上层已经探测过协议并通过 expectedProtocol 传回),这里不再重复探测。
312
295
  this.deviceProtocol.set(path, 'V2');
313
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> V2 (expected)`);
314
296
  return 'V2';
315
297
  }
316
298
 
@@ -325,7 +307,6 @@ export default class WebUsbTransport {
325
307
  protocol === 'V1' ? await this.probeProtocolV1(path) : await this.probeProtocolV2(path);
326
308
  if (detected) {
327
309
  this.deviceProtocol.set(path, protocol);
328
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> ${protocol}`);
329
310
  return protocol;
330
311
  }
331
312
  }
@@ -414,13 +395,6 @@ export default class WebUsbTransport {
414
395
  */
415
396
  async connectToDevice(path: string, first: boolean) {
416
397
  let device: USBDevice = await this.findDevice(path);
417
- this.Log.debug(
418
- '[WebUsbTransport] connecting to device:',
419
- device.productName,
420
- 'PID:',
421
- device.productId
422
- );
423
-
424
398
  if (!device.opened) {
425
399
  await device.open();
426
400
  }
@@ -676,13 +650,12 @@ export default class WebUsbTransport {
676
650
  }
677
651
 
678
652
  private async withProtocolReadTimeout<T>(
679
- path: string,
653
+ _path: string,
680
654
  promise: Promise<T>,
681
655
  timeoutMs: number,
682
656
  protocol: ProtocolType,
683
657
  onTimeout?: () => void
684
658
  ): Promise<T> {
685
- void path;
686
659
  let timer: ReturnType<typeof setTimeout> | undefined;
687
660
  let timedOut = false;
688
661
  const waitForeverAfterTimeout = () => new Promise<never>(() => {});
@@ -699,7 +672,7 @@ export default class WebUsbTransport {
699
672
  return await Promise.race([
700
673
  guardedPromise,
701
674
  new Promise<never>((_, reject) => {
702
- timer = setTimeout(async () => {
675
+ timer = setTimeout(() => {
703
676
  timedOut = true;
704
677
  onTimeout?.();
705
678
  reject(new Error(`Protocol ${protocol} read timeout after ${timeoutMs}ms`));
@@ -719,8 +692,7 @@ export default class WebUsbTransport {
719
692
  try {
720
693
  await this.callProtocolV1(path, 'Initialize', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT });
721
694
  return true;
722
- } catch (error) {
723
- this.Log.debug('[WebUsbTransport] Protocol V1 Initialize probe failed:', error);
695
+ } catch (_error) {
724
696
  return false;
725
697
  }
726
698
  }
@@ -765,12 +737,8 @@ export default class WebUsbTransport {
765
737
  );
766
738
  }
767
739
 
768
- if (shouldSuppressWebUsbCallLog(name)) {
769
- // 高频文件写入不要逐包发 debug 事件,否则浏览器侧会被日志处理拖慢。
770
- } else if (shouldBlockWebUsbCallDataLog(name)) {
771
- this.Log.debug('call-', ' name: ', name, ' protocol: ', protocol);
772
- } else {
773
- this.Log.debug('call-', ' name: ', name, ' data: ', data, ' protocol: ', protocol);
740
+ if (!shouldSuppressHighVolumeCallLog(name)) {
741
+ this.Log.debug('transport call', createTransportCallLog(name, protocol));
774
742
  }
775
743
 
776
744
  if (protocol === 'V2') {
@@ -853,6 +821,17 @@ export default class WebUsbTransport {
853
821
  this.protocolV2Assemblers.get(path)?.reset();
854
822
  try {
855
823
  return await session.call(name, data, options);
824
+ } catch (error) {
825
+ const message =
826
+ error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
827
+ if (message.includes('protocol v2 read timeout') || message.includes('response timeout')) {
828
+ try {
829
+ await this.resetConnectionAfterProbe(path);
830
+ } catch (resetError) {
831
+ this.Log.debug('[WebUsbTransport] Protocol V2 timeout reset failed:', resetError);
832
+ }
833
+ }
834
+ throw error;
856
835
  } finally {
857
836
  this.protocolV2ReadTimeouts.delete(path);
858
837
  }
@@ -960,6 +939,8 @@ export default class WebUsbTransport {
960
939
  this.deviceProtocolHints.delete(path);
961
940
  this.protocolV2Assemblers.get(path)?.reset();
962
941
  this.protocolV2Assemblers.delete(path);
942
+ this.protocolV2Sessions.delete(path);
943
+ this.protocolV2ReadTimeouts.delete(path);
963
944
  this.deviceEndpoints.delete(path);
964
945
  }
965
946