@onekeyfe/hd-transport-web-device 1.2.0-alpha.2 → 1.2.0-alpha.21

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/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
  }
@@ -74,6 +69,7 @@ class WebUsbTransport {
74
69
  this.deviceProtocolHints = new Map();
75
70
  this.protocolV2Assemblers = new Map();
76
71
  this.protocolV2Sessions = new Map();
72
+ this.protocolV2Sequences = new Map();
77
73
  this.protocolV2ReadTimeouts = new Map();
78
74
  this.deviceEndpoints = new Map();
79
75
  this.mockSerialPaths = new WeakMap();
@@ -100,11 +96,9 @@ class WebUsbTransport {
100
96
  this.messages = messages;
101
97
  }
102
98
  configureProtocolV2(signedData) {
103
- var _a;
104
99
  this.messagesV2 = parseConfigure$1(signedData);
105
100
  this.protocolV2Sessions.clear();
106
101
  this.protocolV2ReadTimeouts.clear();
107
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[WebUsbTransport] Protocol V2 schema configured');
108
102
  }
109
103
  promptDeviceAccess() {
110
104
  return __awaiter(this, void 0, void 0, function* () {
@@ -145,7 +139,10 @@ class WebUsbTransport {
145
139
  if (!this.usb)
146
140
  return [];
147
141
  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));
142
+ const onekeyDevices = devices.filter(dev => {
143
+ const isOneKey = hdShared.ONEKEY_WEBUSB_FILTER.some((desc) => dev.vendorId === desc.vendorId && dev.productId === desc.productId);
144
+ return isOneKey && !hdShared.isKnownTrezorWebUsbDevice(dev);
145
+ });
149
146
  this.deviceList = onekeyDevices.map(device => {
150
147
  const path = this.getDevicePath(device);
151
148
  const protocolHint = inferProtocolHintFromDeviceName$1(device.productName);
@@ -158,10 +155,6 @@ class WebUsbTransport {
158
155
  commType: 'webusb',
159
156
  };
160
157
  });
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
158
  return this.deviceList;
166
159
  });
167
160
  }
@@ -200,14 +193,13 @@ class WebUsbTransport {
200
193
  if (expectedProtocol === 'V1') {
201
194
  if (yield this.probeProtocolV1(path)) {
202
195
  this.deviceProtocol.set(path, 'V1');
203
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> V1 (expected)`);
204
196
  return 'V1';
205
197
  }
198
+ yield this.resetConnectionAfterProbe(path);
206
199
  throw this.createProtocolMismatchError(expectedProtocol);
207
200
  }
208
201
  if (expectedProtocol === 'V2') {
209
202
  this.deviceProtocol.set(path, 'V2');
210
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> V2 (expected)`);
211
203
  return 'V2';
212
204
  }
213
205
  const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(path) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
@@ -215,9 +207,11 @@ class WebUsbTransport {
215
207
  const detected = protocol === 'V1' ? yield this.probeProtocolV1(path) : yield this.probeProtocolV2(path);
216
208
  if (detected) {
217
209
  this.deviceProtocol.set(path, protocol);
218
- this.Log.debug(`[WebUsbTransport] detectProtocol: path=${path} -> ${protocol}`);
219
210
  return protocol;
220
211
  }
212
+ if (protocol === 'V1') {
213
+ yield this.resetConnectionAfterProbe(path);
214
+ }
221
215
  }
222
216
  this.deviceProtocol.delete(path);
223
217
  throw this.createProtocolDetectionError();
@@ -287,7 +281,6 @@ class WebUsbTransport {
287
281
  var _a, _b;
288
282
  return __awaiter(this, void 0, void 0, function* () {
289
283
  let device = yield this.findDevice(path);
290
- this.Log.debug('[WebUsbTransport] connecting to device:', device.productName, 'PID:', device.productId);
291
284
  if (!device.opened) {
292
285
  yield device.open();
293
286
  }
@@ -420,19 +413,11 @@ class WebUsbTransport {
420
413
  return copied.buffer;
421
414
  }
422
415
  transferOutWithRetry(path, packet) {
423
- var _a;
424
416
  return __awaiter(this, void 0, void 0, function* () {
425
417
  let lastError;
426
418
  for (let attempt = 1; attempt <= PACKET_IO_MAX_RETRIES; attempt += 1) {
427
419
  try {
428
- const device = yield this.findDevice(path);
429
- if (!device.opened) {
430
- yield this.connect(path, false);
431
- }
432
- const endpoints = this.deviceEndpoints.get(path);
433
- const endpointOut = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpointOut) !== null && _a !== void 0 ? _a : this.endpointId;
434
- const transferBuffer = this.toArrayBuffer(packet.buffer.slice(packet.byteOffset, packet.byteOffset + packet.byteLength));
435
- yield device.transferOut(endpointOut, transferBuffer);
420
+ yield this.transferOutOnce(path, packet);
436
421
  return;
437
422
  }
438
423
  catch (error) {
@@ -453,6 +438,19 @@ class WebUsbTransport {
453
438
  throw lastError;
454
439
  });
455
440
  }
441
+ transferOutOnce(path, packet) {
442
+ var _a;
443
+ return __awaiter(this, void 0, void 0, function* () {
444
+ const device = yield this.findDevice(path);
445
+ if (!device.opened) {
446
+ yield this.connect(path, false);
447
+ }
448
+ const endpoints = this.deviceEndpoints.get(path);
449
+ const endpointOut = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints.endpointOut) !== null && _a !== void 0 ? _a : this.endpointId;
450
+ const transferBuffer = this.toArrayBuffer(packet.buffer.slice(packet.byteOffset, packet.byteOffset + packet.byteLength));
451
+ yield device.transferOut(endpointOut, transferBuffer);
452
+ });
453
+ }
456
454
  transferInWithRetry(path, length, cancelToken) {
457
455
  var _a;
458
456
  return __awaiter(this, void 0, void 0, function* () {
@@ -519,7 +517,7 @@ class WebUsbTransport {
519
517
  yield this.connect(path, false);
520
518
  });
521
519
  }
522
- withProtocolReadTimeout(path, promise, timeoutMs, protocol, onTimeout) {
520
+ withProtocolReadTimeout(_path, promise, timeoutMs, protocol, onTimeout) {
523
521
  return __awaiter(this, void 0, void 0, function* () {
524
522
  let timer;
525
523
  let timedOut = false;
@@ -534,11 +532,11 @@ class WebUsbTransport {
534
532
  return yield Promise.race([
535
533
  guardedPromise,
536
534
  new Promise((_, reject) => {
537
- timer = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
535
+ timer = setTimeout(() => {
538
536
  timedOut = true;
539
537
  onTimeout === null || onTimeout === void 0 ? void 0 : onTimeout();
540
538
  reject(new Error(`Protocol ${protocol} read timeout after ${timeoutMs}ms`));
541
- }), timeoutMs);
539
+ }, timeoutMs);
542
540
  }),
543
541
  ]);
544
542
  }
@@ -557,8 +555,7 @@ class WebUsbTransport {
557
555
  yield this.callProtocolV1(path, 'Initialize', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT });
558
556
  return true;
559
557
  }
560
- catch (error) {
561
- this.Log.debug('[WebUsbTransport] Protocol V1 Initialize probe failed:', error);
558
+ catch (_error) {
562
559
  return false;
563
560
  }
564
561
  });
@@ -573,7 +570,6 @@ class WebUsbTransport {
573
570
  timeoutMs: PROTOCOL_PROBE_TIMEOUT,
574
571
  logger: this.Log,
575
572
  logPrefix: 'ProtocolV2 WebUSB',
576
- onProbeFailed: () => this.resetConnectionAfterProbe(path),
577
573
  });
578
574
  });
579
575
  }
@@ -590,12 +586,8 @@ class WebUsbTransport {
590
586
  if (!protocol) {
591
587
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${path}`);
592
588
  }
593
- if (shouldSuppressWebUsbCallLog(name)) ;
594
- else if (shouldBlockWebUsbCallDataLog(name)) {
595
- this.Log.debug('call-', ' name: ', name, ' protocol: ', protocol);
596
- }
597
- else {
598
- this.Log.debug('call-', ' name: ', name, ' data: ', data, ' protocol: ', protocol);
589
+ if (!shouldSuppressHighVolumeCallLog(name)) {
590
+ this.Log.debug('transport call', createTransportCallLog(name, protocol));
599
591
  }
600
592
  if (protocol === 'V2') {
601
593
  return this.callProtocolV2(path, name, data, options);
@@ -636,13 +628,19 @@ class WebUsbTransport {
636
628
  }
637
629
  let session = this.protocolV2Sessions.get(path);
638
630
  if (!session) {
631
+ let sequenceCursor = this.protocolV2Sequences.get(path);
632
+ if (!sequenceCursor) {
633
+ sequenceCursor = new transport.ProtocolV2SequenceCursor();
634
+ this.protocolV2Sequences.set(path, sequenceCursor);
635
+ }
639
636
  session = new transport.ProtocolV2Session({
640
637
  schemas: {
641
638
  protocolV1: protocolV1Messages,
642
639
  protocolV2: this.messagesV2,
643
640
  },
644
641
  router: transport.PROTOCOL_V2_CHANNEL_USB,
645
- writeFrame: (frame) => this.transferOutWithRetry(path, frame),
642
+ sequenceCursor,
643
+ writeFrame: (frame) => this.transferOutOnce(path, frame),
646
644
  readFrame: () => this.receiveProtocolV2Frame(path, this.protocolV2ReadTimeouts.get(path)),
647
645
  logger: this.Log,
648
646
  logPrefix: 'ProtocolV2 WebUSB',
@@ -655,6 +653,18 @@ class WebUsbTransport {
655
653
  try {
656
654
  return yield session.call(name, data, options);
657
655
  }
656
+ catch (error) {
657
+ const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
658
+ if (message.includes('protocol v2 read timeout') || message.includes('response timeout')) {
659
+ try {
660
+ yield this.resetConnectionAfterProbe(path);
661
+ }
662
+ catch (resetError) {
663
+ this.Log.debug('[WebUsbTransport] Protocol V2 timeout reset failed:', resetError);
664
+ }
665
+ }
666
+ throw error;
667
+ }
658
668
  finally {
659
669
  this.protocolV2ReadTimeouts.delete(path);
660
670
  }
@@ -737,6 +747,8 @@ class WebUsbTransport {
737
747
  this.deviceProtocolHints.delete(path);
738
748
  (_b = this.protocolV2Assemblers.get(path)) === null || _b === void 0 ? void 0 : _b.reset();
739
749
  this.protocolV2Assemblers.delete(path);
750
+ this.protocolV2Sessions.delete(path);
751
+ this.protocolV2ReadTimeouts.delete(path);
740
752
  this.deviceEndpoints.delete(path);
741
753
  });
742
754
  }
@@ -745,15 +757,6 @@ class WebUsbTransport {
745
757
  }
746
758
  }
747
759
 
748
- const FILE_WRITE_LOG_BLOCK_PATTERN = /(?:^|[^a-z])(?:raw)?(?:filesystem|emmc)?filewrite$/i;
749
- function shouldSuppressHighVolumeCallLog(name) {
750
- const normalized = name.replace(/[_\s-]/g, '');
751
- return FILE_WRITE_LOG_BLOCK_PATTERN.test(normalized);
752
- }
753
- function isLogBlockCommand(name) {
754
- var _a, _b;
755
- 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;
756
- }
757
760
  const { parseConfigure, ProtocolV1, check } = transport__default["default"];
758
761
  function inferProtocolHintFromDeviceName(name) {
759
762
  return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
@@ -761,8 +764,6 @@ function inferProtocolHintFromDeviceName(name) {
761
764
  const toBleDescriptor = (device, protocolType) => (Object.assign({ id: device.id, name: device.name, path: device.id, debug: false, commType: 'electron-ble' }, (protocolType ? { protocolType } : {})));
762
765
  const BLE_PACKET_SIZE = 192;
763
766
  const BLE_WRITE_DELAY_MS = 5;
764
- const BLE_WRITE_MAX_RETRIES = 3;
765
- const BLE_WRITE_RETRY_DELAY_MS = 300;
766
767
  const BLE_RESPONSE_TIMEOUT_MS = 30000;
767
768
  const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
768
769
  const PROTOCOL_V2_PROBE_TIMEOUT_MS = 5000;
@@ -778,8 +779,27 @@ class ElectronBleTransport {
778
779
  this.v2Assemblers = new Map();
779
780
  this.v2FrameQueues = new Map();
780
781
  this.v2FramePromises = new Map();
781
- this.activeProtocolV2Call = null;
782
- this.nextProtocolV2CallToken = 1;
782
+ this.protocolV2Links = new transport.ProtocolV2LinkManager({
783
+ getSchemas: () => {
784
+ if (!this._messages || !this._messagesV2) {
785
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
786
+ }
787
+ return {
788
+ protocolV1: this._messages,
789
+ protocolV2: this._messagesV2,
790
+ };
791
+ },
792
+ classifyError: () => 'link-fatal',
793
+ onLinkInvalidated: (uuid, reason) => __awaiter(this, void 0, void 0, function* () {
794
+ var _a, _b;
795
+ (_a = this.v2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
796
+ this.rejectProtocolV2Frames(uuid, new Error(reason));
797
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Electron BLE] Protocol V2 link invalidated:', uuid, reason);
798
+ if (reason.startsWith('Protocol V2 link-fatal error:')) {
799
+ yield this.release(uuid);
800
+ }
801
+ }),
802
+ });
783
803
  this.notificationCleanups = new Map();
784
804
  this.disconnectCleanups = new Map();
785
805
  this.notificationTokens = new Map();
@@ -815,15 +835,14 @@ class ElectronBleTransport {
815
835
  throw error;
816
836
  }
817
837
  cleanupDeviceState(deviceId) {
818
- var _a;
838
+ this.protocolV2Links
839
+ .invalidateLink(deviceId, 'Electron BLE device state cleaned')
840
+ .catch(error => { var _a; return (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] link cleanup failed:', error); });
819
841
  this.connectedDevices.delete(deviceId);
820
842
  this.deviceProtocol.delete(deviceId);
821
843
  this.v1Buffers.delete(deviceId);
822
844
  this.v2Assemblers.delete(deviceId);
823
845
  this.resetProtocolV2Frames(deviceId);
824
- if (((_a = this.activeProtocolV2Call) === null || _a === void 0 ? void 0 : _a.uuid) === deviceId) {
825
- this.activeProtocolV2Call = null;
826
- }
827
846
  this.notificationTokens.delete(deviceId);
828
847
  const notifyCleanup = this.notificationCleanups.get(deviceId);
829
848
  if (notifyCleanup) {
@@ -850,9 +869,10 @@ class ElectronBleTransport {
850
869
  this.configured = true;
851
870
  }
852
871
  configureProtocolV2(signedData) {
853
- var _a;
854
872
  this._messagesV2 = parseConfigure(signedData);
855
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] Protocol V2 schema configured');
873
+ this.protocolV2Links
874
+ .invalidateAllLinks('Protocol V2 schema reconfigured')
875
+ .catch(error => { var _a; return (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] schema link cleanup failed:', error); });
856
876
  }
857
877
  listen() {
858
878
  return __awaiter(this, void 0, void 0, function* () {
@@ -890,12 +910,14 @@ class ElectronBleTransport {
890
910
  if (!uuid) {
891
911
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleRequiredUUID);
892
912
  }
913
+ if (this.connectedDevices.has(uuid)) {
914
+ yield this.release(uuid);
915
+ }
893
916
  if (forceCleanRunPromise && this.runPromise) {
894
917
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
895
918
  this.runPromise.reject(error);
896
919
  this.rejectAllProtocolV2Frames(error);
897
920
  this.runPromise = null;
898
- this.activeProtocolV2Call = null;
899
921
  }
900
922
  try {
901
923
  if (!((_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle)) {
@@ -963,6 +985,7 @@ class ElectronBleTransport {
963
985
  var _a, _b;
964
986
  return __awaiter(this, void 0, void 0, function* () {
965
987
  try {
988
+ yield this.protocolV2Links.invalidateLink(id, 'Electron BLE transport released');
966
989
  if (this.connectedDevices.has(id)) {
967
990
  if ((_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle) {
968
991
  yield window.desktopApi.nobleBle.unsubscribe(id);
@@ -1036,14 +1059,12 @@ class ElectronBleTransport {
1036
1059
  });
1037
1060
  }
1038
1061
  resetProbeStateAfterProtocolProbe(uuid, protocol) {
1039
- var _a, _b, _c, _d, _e, _f, _g, _h;
1062
+ var _a, _b, _c, _d, _e, _f, _g;
1040
1063
  return __awaiter(this, void 0, void 0, function* () {
1064
+ yield this.protocolV2Links.invalidateLink(uuid, `Reset notify state after Protocol ${protocol} probe`);
1041
1065
  this.v1Buffers.set(uuid, { buffer: [], bufferLength: 0 });
1042
1066
  (_a = this.v2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1043
1067
  this.resetProtocolV2Frames(uuid);
1044
- if (((_b = this.activeProtocolV2Call) === null || _b === void 0 ? void 0 : _b.uuid) === uuid) {
1045
- this.activeProtocolV2Call = null;
1046
- }
1047
1068
  if (this.runPromise) {
1048
1069
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
1049
1070
  this.runPromise.reject(error);
@@ -1056,16 +1077,16 @@ class ElectronBleTransport {
1056
1077
  }
1057
1078
  this.notificationTokens.delete(uuid);
1058
1079
  try {
1059
- yield ((_d = (_c = window.desktopApi) === null || _c === void 0 ? void 0 : _c.nobleBle) === null || _d === void 0 ? void 0 : _d.unsubscribe(uuid));
1080
+ yield ((_c = (_b = window.desktopApi) === null || _b === void 0 ? void 0 : _b.nobleBle) === null || _c === void 0 ? void 0 : _c.unsubscribe(uuid));
1060
1081
  }
1061
1082
  catch (error) {
1062
- (_e = this.Log) === null || _e === void 0 ? void 0 : _e.debug(`[Electron BLE] unsubscribe after Protocol ${protocol} probe failed:`, error);
1083
+ (_d = this.Log) === null || _d === void 0 ? void 0 : _d.debug(`[Electron BLE] unsubscribe after Protocol ${protocol} probe failed:`, error);
1063
1084
  }
1064
1085
  try {
1065
- yield ((_g = (_f = window.desktopApi) === null || _f === void 0 ? void 0 : _f.nobleBle) === null || _g === void 0 ? void 0 : _g.subscribe(uuid));
1086
+ yield ((_f = (_e = window.desktopApi) === null || _e === void 0 ? void 0 : _e.nobleBle) === null || _f === void 0 ? void 0 : _f.subscribe(uuid));
1066
1087
  }
1067
1088
  catch (error) {
1068
- (_h = this.Log) === null || _h === void 0 ? void 0 : _h.debug(`[Electron BLE] resubscribe after Protocol ${protocol} probe failed:`, error);
1089
+ (_g = this.Log) === null || _g === void 0 ? void 0 : _g.debug(`[Electron BLE] resubscribe after Protocol ${protocol} probe failed:`, error);
1069
1090
  throw error;
1070
1091
  }
1071
1092
  const cleanup = this.createNotificationSubscription(uuid);
@@ -1120,52 +1141,40 @@ class ElectronBleTransport {
1120
1141
  const totalBytes = hexData.length / 2;
1121
1142
  if (totalBytes <= BLE_PACKET_SIZE) {
1122
1143
  yield hdShared.wait(BLE_WRITE_DELAY_MS);
1123
- yield this.writeWithRetry(uuid, hexData);
1144
+ yield this.writeOnce(uuid, hexData);
1124
1145
  return;
1125
1146
  }
1126
1147
  for (let offset = 0; offset < hexData.length;) {
1127
1148
  const chunkHexLen = Math.min(BLE_PACKET_SIZE * 2, hexData.length - offset);
1128
1149
  const chunkHex = hexData.substring(offset, offset + chunkHexLen);
1129
1150
  offset += chunkHexLen;
1130
- yield this.writeWithRetry(uuid, chunkHex);
1151
+ yield this.writeOnce(uuid, chunkHex);
1131
1152
  if (offset < hexData.length) {
1132
1153
  yield hdShared.wait(BLE_WRITE_DELAY_MS);
1133
1154
  }
1134
1155
  }
1135
1156
  });
1136
1157
  }
1137
- writeWithRetry(uuid, hexData) {
1138
- var _a, _b, _c;
1158
+ writeOnce(uuid, hexData) {
1159
+ var _a;
1139
1160
  return __awaiter(this, void 0, void 0, function* () {
1140
- let lastError;
1141
1161
  const nobleBle = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle;
1142
1162
  if (!nobleBle) {
1143
1163
  throw new Error('Noble BLE API not available');
1144
1164
  }
1145
- for (let attempt = 1; attempt <= BLE_WRITE_MAX_RETRIES; attempt++) {
1146
- try {
1147
- yield nobleBle.write(uuid, hexData);
1148
- return;
1149
- }
1150
- catch (error) {
1151
- lastError = error;
1152
- (_b = this.Log) === null || _b === void 0 ? void 0 : _b.error(`[Electron BLE] write failed (attempt ${attempt}/${BLE_WRITE_MAX_RETRIES}):`, error);
1153
- if (attempt < BLE_WRITE_MAX_RETRIES) {
1154
- yield hdShared.wait(BLE_WRITE_RETRY_DELAY_MS);
1155
- }
1156
- }
1157
- }
1158
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError, `BLE write failed after ${BLE_WRITE_MAX_RETRIES} attempts: ${(_c = lastError === null || lastError === void 0 ? void 0 : lastError.message) !== null && _c !== void 0 ? _c : lastError}`);
1165
+ yield nobleBle.write(uuid, hexData);
1159
1166
  });
1160
1167
  }
1161
1168
  handleNotification(deviceId, hexData) {
1162
1169
  var _a, _b;
1163
1170
  if (hexData === 'PAIRING_REJECTED') {
1164
1171
  (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] Pairing rejection detected for device:', deviceId);
1165
- if (this.runPromise) {
1166
- const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceBondedCanceled);
1172
+ const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceBondedCanceled);
1173
+ if (this.deviceProtocol.get(deviceId) === 'V2') {
1174
+ this.rejectProtocolV2Frames(deviceId, error);
1175
+ }
1176
+ else if (this.runPromise) {
1167
1177
  this.runPromise.reject(error);
1168
- this.rejectAllProtocolV2Frames(error);
1169
1178
  }
1170
1179
  return;
1171
1180
  }
@@ -1181,13 +1190,8 @@ class ElectronBleTransport {
1181
1190
  this.handleProtocolV1Notification(deviceId, hexData);
1182
1191
  }
1183
1192
  handleProtocolV2Notification(deviceId, hexData) {
1184
- var _a, _b, _c;
1193
+ var _a;
1185
1194
  try {
1186
- if (!this.runPromise || ((_a = this.activeProtocolV2Call) === null || _a === void 0 ? void 0 : _a.uuid) !== deviceId) {
1187
- (_b = this.v2Assemblers.get(deviceId)) === null || _b === void 0 ? void 0 : _b.reset();
1188
- this.resetProtocolV2Frames(deviceId);
1189
- return;
1190
- }
1191
1195
  const bytes = transport.hexToBytes(hexData);
1192
1196
  if (bytes.length === 0)
1193
1197
  return;
@@ -1199,12 +1203,9 @@ class ElectronBleTransport {
1199
1203
  }
1200
1204
  }
1201
1205
  catch (error) {
1202
- (_c = this.Log) === null || _c === void 0 ? void 0 : _c.error('[Electron BLE] Protocol V2 notification error:', error);
1203
- if (this.runPromise) {
1204
- const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
1205
- this.runPromise.reject(notifyError);
1206
- this.rejectAllProtocolV2Frames(notifyError);
1207
- }
1206
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.error('[Electron BLE] Protocol V2 notification error:', error);
1207
+ const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
1208
+ this.rejectProtocolV2Frames(deviceId, notifyError);
1208
1209
  }
1209
1210
  }
1210
1211
  getProtocolV2FrameQueue(uuid) {
@@ -1235,9 +1236,13 @@ class ElectronBleTransport {
1235
1236
  this.v2FrameQueues.delete(uuid);
1236
1237
  this.v2FramePromises.delete(uuid);
1237
1238
  }
1238
- isActiveProtocolV2Call(uuid, token) {
1239
- var _a;
1240
- return ((_a = this.activeProtocolV2Call) === null || _a === void 0 ? void 0 : _a.uuid) === uuid && this.activeProtocolV2Call.token === token;
1239
+ rejectProtocolV2Frames(uuid, error) {
1240
+ this.v2FrameQueues.delete(uuid);
1241
+ const framePromise = this.v2FramePromises.get(uuid);
1242
+ if (framePromise) {
1243
+ this.v2FramePromises.delete(uuid);
1244
+ framePromise.reject(error);
1245
+ }
1241
1246
  }
1242
1247
  readProtocolV2Frame(uuid) {
1243
1248
  return __awaiter(this, void 0, void 0, function* () {
@@ -1272,7 +1277,7 @@ class ElectronBleTransport {
1272
1277
  }
1273
1278
  }
1274
1279
  call(uuid, name, data, options) {
1275
- var _a, _b;
1280
+ var _a;
1276
1281
  return __awaiter(this, void 0, void 0, function* () {
1277
1282
  if (!this._messages) {
1278
1283
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
@@ -1284,12 +1289,8 @@ class ElectronBleTransport {
1284
1289
  if (!protocol) {
1285
1290
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${uuid}`);
1286
1291
  }
1287
- if (shouldSuppressHighVolumeCallLog(name)) ;
1288
- else if (isLogBlockCommand(name)) {
1289
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] call', 'name:', name, 'protocol:', protocol);
1290
- }
1291
- else {
1292
- (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Electron BLE] call', 'name:', name, 'data:', data, 'protocol:', protocol);
1292
+ if (!shouldSuppressHighVolumeCallLog(name)) {
1293
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('transport call', createTransportCallLog(name, protocol));
1293
1294
  }
1294
1295
  if (protocol === 'V2') {
1295
1296
  return this.callProtocolV2(uuid, name, data, options);
@@ -1360,76 +1361,60 @@ class ElectronBleTransport {
1360
1361
  });
1361
1362
  }
1362
1363
  callProtocolV2(uuid, name, data, options) {
1363
- var _a, _b, _c, _d, _e;
1364
+ var _a, _b;
1364
1365
  return __awaiter(this, void 0, void 0, function* () {
1365
1366
  if (!this._messages || !this._messagesV2) {
1366
1367
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
1367
1368
  }
1368
- const forceRun = name === 'Initialize' || name === 'Cancel' || name === 'Ping';
1369
- if (this.runPromise) {
1370
- if (!forceRun) {
1371
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
1372
- }
1373
- const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
1374
- this.runPromise.reject(error);
1375
- this.rejectAllProtocolV2Frames(error);
1376
- this.runPromise = null;
1377
- this.activeProtocolV2Call = null;
1378
- }
1379
- const runPromise = hdShared.createDeferred();
1380
- runPromise.promise.catch(() => undefined);
1381
- this.runPromise = runPromise;
1382
- const callToken = this.nextProtocolV2CallToken++;
1383
- this.activeProtocolV2Call = { uuid, token: callToken };
1384
- (_a = this.v2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1385
- this.resetProtocolV2Frames(uuid);
1386
- let completed = false;
1387
- const callOptions = Object.assign(Object.assign({}, options), { timeoutMs: (_b = options === null || options === void 0 ? void 0 : options.timeoutMs) !== null && _b !== void 0 ? _b : BLE_RESPONSE_TIMEOUT_MS });
1369
+ const callOptions = Object.assign(Object.assign({}, options), { timeoutMs: (_a = options === null || options === void 0 ? void 0 : options.timeoutMs) !== null && _a !== void 0 ? _a : BLE_RESPONSE_TIMEOUT_MS });
1388
1370
  try {
1389
- const session = new transport.ProtocolV2Session({
1390
- schemas: {
1391
- protocolV1: this._messages,
1392
- protocolV2: this._messagesV2,
1393
- },
1394
- router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
1395
- writeFrame: (frame) => this.writeWithChunking(uuid, transport.bytesToHex(frame)),
1396
- readFrame: () => __awaiter(this, void 0, void 0, function* () {
1397
- const rxFrame = yield this.readProtocolV2Frame(uuid);
1398
- if (!(rxFrame instanceof Uint8Array)) {
1399
- throw new Error('Response is not Uint8Array');
1400
- }
1401
- return rxFrame;
1402
- }),
1403
- logger: this.Log,
1404
- logPrefix: 'ProtocolV2 BLE',
1405
- createTimeoutError: (_messageName, timeout) => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE response timeout after ${timeout}ms for ${name}`),
1406
- });
1407
- const result = yield session.call(name, data, callOptions);
1408
- completed = true;
1409
- return result;
1371
+ return yield this.protocolV2Links.call(uuid, () => this.createProtocolV2Adapter(uuid), name, data, callOptions);
1410
1372
  }
1411
1373
  catch (e) {
1412
- if (this.isActiveProtocolV2Call(uuid, callToken)) {
1413
- (_c = this.v2Assemblers.get(uuid)) === null || _c === void 0 ? void 0 : _c.reset();
1414
- this.resetProtocolV2Frames(uuid);
1415
- }
1416
- (_d = this.Log) === null || _d === void 0 ? void 0 : _d.error('[Electron BLE] Protocol V2 call error:', e);
1374
+ (_b = this.Log) === null || _b === void 0 ? void 0 : _b.error('[Electron BLE] Protocol V2 call error:', e);
1417
1375
  throw e;
1418
1376
  }
1419
- finally {
1420
- if (this.isActiveProtocolV2Call(uuid, callToken)) {
1421
- if (!completed) {
1422
- (_e = this.v2Assemblers.get(uuid)) === null || _e === void 0 ? void 0 : _e.reset();
1423
- }
1424
- this.resetProtocolV2Frames(uuid);
1425
- this.activeProtocolV2Call = null;
1426
- }
1427
- if (this.runPromise === runPromise) {
1428
- this.runPromise = null;
1429
- }
1430
- }
1431
1377
  });
1432
1378
  }
1379
+ createProtocolV2Adapter(uuid) {
1380
+ var _a;
1381
+ const generation = (_a = this.notificationTokens.get(uuid)) !== null && _a !== void 0 ? _a : 0;
1382
+ const assertCurrentGeneration = () => {
1383
+ if (this.notificationTokens.get(uuid) !== generation) {
1384
+ throw new Error(`Protocol V2 notification generation changed for ${uuid}`);
1385
+ }
1386
+ };
1387
+ return {
1388
+ router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
1389
+ generation,
1390
+ prepareCall: () => {
1391
+ var _a;
1392
+ assertCurrentGeneration();
1393
+ (_a = this.v2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1394
+ this.resetProtocolV2Frames(uuid);
1395
+ },
1396
+ writeFrame: (frame) => {
1397
+ assertCurrentGeneration();
1398
+ return this.writeWithChunking(uuid, transport.bytesToHex(frame));
1399
+ },
1400
+ readFrame: () => __awaiter(this, void 0, void 0, function* () {
1401
+ assertCurrentGeneration();
1402
+ const rxFrame = yield this.readProtocolV2Frame(uuid);
1403
+ if (!(rxFrame instanceof Uint8Array)) {
1404
+ throw new Error('Response is not Uint8Array');
1405
+ }
1406
+ return rxFrame;
1407
+ }),
1408
+ reset: (reason) => {
1409
+ var _a;
1410
+ (_a = this.v2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1411
+ this.rejectProtocolV2Frames(uuid, new Error(reason));
1412
+ },
1413
+ logger: this.Log,
1414
+ logPrefix: 'ProtocolV2 BLE',
1415
+ createTimeoutError: (messageName, timeout) => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE response timeout after ${timeout}ms for ${messageName}`),
1416
+ };
1417
+ }
1433
1418
  processProtocolV1Notification(deviceId, hexData) {
1434
1419
  try {
1435
1420
  if (typeof hexData !== 'string') {
@@ -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"}