@onekeyfe/hd-transport-usb 1.2.0-alpha.3 → 1.2.0-alpha.30

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
@@ -59,6 +59,14 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
59
59
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
60
60
  };
61
61
 
62
+ const HIGH_VOLUME_CALLS = new Set(['FileWrite', 'FilesystemFileWrite', 'EmmcFileWrite']);
63
+ function shouldSuppressHighVolumeCallLog(name) {
64
+ return HIGH_VOLUME_CALLS.has(name);
65
+ }
66
+ function createTransportCallLog(name, protocol) {
67
+ return { name, protocol };
68
+ }
69
+
62
70
  const { parseConfigure, ProtocolV1, check } = transport__default["default"];
63
71
  const PACKET_SIZE = transport.PROTOCOL_V1_USB_PACKET_SIZE;
64
72
  const REPORT_ID = transport.PROTOCOL_V1_REPORT_ID;
@@ -71,7 +79,7 @@ const TRANSFER_TIMEOUT_MS = 30000;
71
79
  const SERIAL_READ_TIMEOUT_MS = 5000;
72
80
  const PACKET_IO_MAX_RETRIES = 3;
73
81
  const PACKET_IO_RETRY_DELAY = 300;
74
- const PROTOCOL_PROBE_TIMEOUT = 1000;
82
+ const PROTOCOL_PROBE_TIMEOUT = 5000;
75
83
  function getBusId(dev) {
76
84
  return `usb:${dev.busNumber}:${dev.deviceAddress}`;
77
85
  }
@@ -132,46 +140,6 @@ function readSerialNumber(dev, openDevices) {
132
140
  }
133
141
  });
134
142
  }
135
- function transferInOnce(ep, length) {
136
- return new Promise((resolve, reject) => {
137
- ep.transfer(length, (err, data) => {
138
- if (err)
139
- return reject(err);
140
- if (!data || data.length === 0)
141
- return reject(new Error('Empty USB transfer'));
142
- resolve(data);
143
- });
144
- });
145
- }
146
- function transferOutOnce(ep, data) {
147
- return new Promise((resolve, reject) => {
148
- ep.transfer(data, (err) => {
149
- if (err)
150
- return reject(err);
151
- resolve();
152
- });
153
- });
154
- }
155
- function resetUsbDevice(dev) {
156
- return new Promise(resolve => {
157
- const reset = dev.reset;
158
- if (typeof reset !== 'function') {
159
- resolve();
160
- return;
161
- }
162
- reset.call(dev, () => resolve());
163
- });
164
- }
165
- function clearEndpointHalt(ep) {
166
- return new Promise(resolve => {
167
- const clearHalt = ep.clearHalt;
168
- if (typeof clearHalt !== 'function') {
169
- resolve();
170
- return;
171
- }
172
- clearHalt.call(ep, () => resolve());
173
- });
174
- }
175
143
  function skipReportByte(packet) {
176
144
  if (packet[0] === REPORT_ID) {
177
145
  return packet.subarray(1);
@@ -181,8 +149,13 @@ function skipReportByte(packet) {
181
149
  function toArrayBuffer(buf) {
182
150
  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
183
151
  }
184
- class NodeUsbTransport {
152
+ class NodeUsbTransport extends transport.ProtocolV2UsbTransportBase {
185
153
  constructor() {
154
+ super({
155
+ router: transport.PROTOCOL_V2_CHANNEL_USB,
156
+ maxFrameBytes: transport.PROTOCOL_V2_FRAME_MAX_BYTES,
157
+ logPrefix: 'ProtocolV2 NodeUSB',
158
+ });
186
159
  this.name = 'NodeUsbTransport';
187
160
  this.version = '';
188
161
  this.configured = false;
@@ -190,10 +163,8 @@ class NodeUsbTransport {
190
163
  this.serialToBusId = new Map();
191
164
  this.openDevices = new Map();
192
165
  this.deviceProtocol = new Map();
193
- this.protocolV2Assemblers = new Map();
194
- this.protocolV2Sessions = new Map();
195
- this.protocolV2ReadTimeouts = new Map();
196
166
  this.reconnectLocks = new Map();
167
+ this.activeTransfers = new Map();
197
168
  this.cancelled = false;
198
169
  }
199
170
  init(logger, emitter) {
@@ -209,14 +180,38 @@ class NodeUsbTransport {
209
180
  }
210
181
  configureProtocolV2(signedData) {
211
182
  var _a;
183
+ const schemaSource = typeof signedData === 'string'
184
+ ? signedData
185
+ : (_a = JSON.stringify(signedData)) !== null && _a !== void 0 ? _a : String(signedData);
186
+ if (schemaSource === this.protocolV2SchemaSource)
187
+ return;
188
+ const hadProtocolV2Schema = this.protocolV2SchemaSource !== undefined;
212
189
  this.messagesV2 = parseConfigure(signedData);
213
- this.protocolV2Sessions.clear();
214
- this.protocolV2ReadTimeouts.clear();
215
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[NodeUsbTransport] Protocol V2 schema configured');
190
+ this.protocolV2SchemaSource = schemaSource;
191
+ if (!hadProtocolV2Schema)
192
+ return;
193
+ this.invalidateAllProtocolV2UsbLinks('Protocol V2 schema reconfigured').catch(error => { var _a; return (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[NodeUsbTransport] schema link cleanup failed:', error); });
216
194
  }
217
195
  listen() {
218
196
  }
219
197
  stop() {
198
+ var _a;
199
+ return __awaiter(this, void 0, void 0, function* () {
200
+ this.cancelled = true;
201
+ yield this.cancelActiveTransfers();
202
+ try {
203
+ yield this.disposeProtocolV2UsbLinks('Node USB transport stopped');
204
+ }
205
+ catch (error) {
206
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[NodeUsbTransport] stop link cleanup failed:', error);
207
+ }
208
+ yield Promise.allSettled(this.reconnectLocks.values());
209
+ yield this.cancelActiveTransfers();
210
+ yield Promise.all(Array.from(this.openDevices.keys(), path => this.closeOpenDevice(path)));
211
+ this.reconnectLocks.clear();
212
+ this.deviceProtocol.clear();
213
+ this.serialToBusId.clear();
214
+ });
220
215
  }
221
216
  post(path, name, data) {
222
217
  return __awaiter(this, void 0, void 0, function* () {
@@ -274,6 +269,7 @@ class NodeUsbTransport {
274
269
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, 'No device path provided');
275
270
  }
276
271
  try {
272
+ yield this.rotateProtocolV2UsbGeneration(path, 'Node USB transport acquired');
277
273
  yield this.closeOpenDevice(path);
278
274
  yield this.openDevice(path);
279
275
  yield this.detectProtocol(path, input.expectedProtocol);
@@ -287,9 +283,81 @@ class NodeUsbTransport {
287
283
  }
288
284
  release(path, _onclose) {
289
285
  return __awaiter(this, void 0, void 0, function* () {
286
+ yield this.cancelActiveTransfers(path);
287
+ yield this.invalidateProtocolV2UsbLink(path, 'Node USB transport released');
290
288
  yield this.closeOpenDevice(path);
291
289
  this.deviceProtocol.delete(path);
292
- this.protocolV2Assemblers.delete(path);
290
+ });
291
+ }
292
+ cancelActiveTransfers(path) {
293
+ return __awaiter(this, void 0, void 0, function* () {
294
+ const transfers = Array.from(this.activeTransfers.entries()).filter(([, active]) => path === undefined || active.path === path);
295
+ transfers.forEach(([transfer]) => {
296
+ try {
297
+ transfer.cancel();
298
+ }
299
+ catch (_a) {
300
+ }
301
+ });
302
+ yield Promise.allSettled(transfers.map(([, active]) => active.settled));
303
+ });
304
+ }
305
+ createTrackedTransfer(path, endpoint, callback) {
306
+ let resolveSettled = () => undefined;
307
+ const settled = new Promise(resolve => {
308
+ resolveSettled = resolve;
309
+ });
310
+ const transfer = endpoint.makeTransfer(endpoint.timeout, (error, buffer, actualLength) => {
311
+ this.activeTransfers.delete(transfer);
312
+ resolveSettled();
313
+ callback(error, buffer, actualLength);
314
+ });
315
+ this.activeTransfers.set(transfer, { path, settled, resolveSettled });
316
+ return transfer;
317
+ }
318
+ transferInOnce(path, ep, length) {
319
+ return new Promise((resolve, reject) => {
320
+ const buffer = Buffer.alloc(length);
321
+ const transfer = this.createTrackedTransfer(path, ep, (error, _submittedBuffer, actualLength) => {
322
+ if (error) {
323
+ reject(error);
324
+ return;
325
+ }
326
+ if (actualLength <= 0) {
327
+ reject(new Error('Empty USB transfer'));
328
+ return;
329
+ }
330
+ resolve(buffer.subarray(0, actualLength));
331
+ });
332
+ try {
333
+ transfer.submit(buffer);
334
+ }
335
+ catch (error) {
336
+ const active = this.activeTransfers.get(transfer);
337
+ this.activeTransfers.delete(transfer);
338
+ active === null || active === void 0 ? void 0 : active.resolveSettled();
339
+ reject(error);
340
+ }
341
+ });
342
+ }
343
+ transferOutOnce(path, ep, data) {
344
+ return new Promise((resolve, reject) => {
345
+ const transfer = this.createTrackedTransfer(path, ep, error => {
346
+ if (error) {
347
+ reject(error);
348
+ return;
349
+ }
350
+ resolve();
351
+ });
352
+ try {
353
+ transfer.submit(data);
354
+ }
355
+ catch (error) {
356
+ const active = this.activeTransfers.get(transfer);
357
+ this.activeTransfers.delete(transfer);
358
+ active === null || active === void 0 ? void 0 : active.resolveSettled();
359
+ reject(error);
360
+ }
293
361
  });
294
362
  }
295
363
  closeOpenDevice(path) {
@@ -320,7 +388,7 @@ class NodeUsbTransport {
320
388
  });
321
389
  }
322
390
  call(path, name, data, options) {
323
- var _a, _b;
391
+ var _a;
324
392
  return __awaiter(this, void 0, void 0, function* () {
325
393
  this.cancelled = false;
326
394
  if (!this.messages) {
@@ -333,11 +401,8 @@ class NodeUsbTransport {
333
401
  if (!protocol) {
334
402
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${path}`);
335
403
  }
336
- if (transport.LogBlockCommand.has(name)) {
337
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('NodeUsbTransport call-', ' name: ', name, ' protocol: ', protocol);
338
- }
339
- else {
340
- (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('NodeUsbTransport call-', ' name: ', name, ' data: ', data, ' protocol: ', protocol);
404
+ if (!shouldSuppressHighVolumeCallLog(name)) {
405
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('transport call', createTransportCallLog(name, protocol));
341
406
  }
342
407
  if (protocol === 'V2') {
343
408
  return this.callProtocolV2(path, name, data, options);
@@ -362,8 +427,6 @@ class NodeUsbTransport {
362
427
  });
363
428
  }
364
429
  cancel() {
365
- var _a;
366
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('NodeUsbTransport cancel');
367
430
  this.cancelled = true;
368
431
  }
369
432
  getOpenDevice(path) {
@@ -386,6 +449,9 @@ class NodeUsbTransport {
386
449
  }
387
450
  isRetryableError(error) {
388
451
  const message = this.getErrorMessage(error).toLowerCase();
452
+ if (message.includes('cancelled') || message.includes('canceled')) {
453
+ return false;
454
+ }
389
455
  return (message.includes('libusb') ||
390
456
  message.includes('transfer') ||
391
457
  message.includes('disconnected') ||
@@ -397,6 +463,10 @@ class NodeUsbTransport {
397
463
  message.includes('timeout') ||
398
464
  message.includes('interrupt'));
399
465
  }
466
+ isUsbTransferTimeout(error) {
467
+ const message = this.getErrorMessage(error).toLowerCase();
468
+ return message.includes('timeout') || message.includes('timed_out');
469
+ }
400
470
  getDeviceInterface(dev) {
401
471
  var _a;
402
472
  const { interfaces } = dev;
@@ -416,6 +486,7 @@ class NodeUsbTransport {
416
486
  var _a, _b;
417
487
  (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] transfer${direction} failed, retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(error)}`);
418
488
  yield hdShared.wait(attempt * PACKET_IO_RETRY_DELAY);
489
+ yield this.rotateProtocolV2UsbGeneration(path, `Node USB Protocol V1 ${direction} reconnect attempt ${attempt}`);
419
490
  try {
420
491
  yield this.closeOpenDevice(path);
421
492
  }
@@ -449,7 +520,7 @@ class NodeUsbTransport {
449
520
  const packet = new Uint8Array(PACKET_SIZE);
450
521
  packet[0] = REPORT_ID;
451
522
  packet.set(new Uint8Array(buffer), 1);
452
- yield transferOutOnce(this.getOpenDevice(path).epOut, Buffer.from(packet));
523
+ yield this.transferOutOnce(path, this.getOpenDevice(path).epOut, Buffer.from(packet));
453
524
  }
454
525
  return;
455
526
  }
@@ -472,7 +543,7 @@ class NodeUsbTransport {
472
543
  throw lastError;
473
544
  });
474
545
  }
475
- transferInWithRetry(path, openDev, length) {
546
+ transferInWithRetry(path, openDev, length, options) {
476
547
  var _a;
477
548
  return __awaiter(this, void 0, void 0, function* () {
478
549
  let lastError;
@@ -482,21 +553,26 @@ class NodeUsbTransport {
482
553
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromOutside, 'Cancelled');
483
554
  }
484
555
  try {
485
- return yield transferInOnce(currentDev.epIn, length);
556
+ return yield this.transferInOnce(path, currentDev.epIn, length);
486
557
  }
487
558
  catch (error) {
488
559
  lastError = error;
489
- const shouldRetry = attempt < PACKET_IO_MAX_RETRIES && this.isRetryableError(error);
490
- if (!shouldRetry) {
491
- throw error;
492
- }
493
- try {
494
- currentDev = yield this.reconnectForRetry(path, 'in', attempt, error);
560
+ if ((options === null || options === void 0 ? void 0 : options.waitIndefinitelyOnTimeout) && this.isUsbTransferTimeout(error)) {
561
+ attempt -= 1;
495
562
  }
496
- catch (reconnectError) {
497
- lastError = reconnectError;
498
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] reconnect failed on retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(reconnectError)}`);
499
- break;
563
+ else {
564
+ const shouldRetry = attempt < PACKET_IO_MAX_RETRIES && this.isRetryableError(error);
565
+ if (!shouldRetry) {
566
+ throw error;
567
+ }
568
+ try {
569
+ currentDev = yield this.reconnectForRetry(path, 'in', attempt, error);
570
+ }
571
+ catch (reconnectError) {
572
+ lastError = reconnectError;
573
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] reconnect failed on retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(reconnectError)}`);
574
+ break;
575
+ }
500
576
  }
501
577
  }
502
578
  }
@@ -518,13 +594,6 @@ class NodeUsbTransport {
518
594
  try {
519
595
  dev.open();
520
596
  dev.timeout = TRANSFER_TIMEOUT_MS;
521
- yield resetUsbDevice(dev);
522
- try {
523
- dev.open();
524
- }
525
- catch (_d) {
526
- }
527
- dev.timeout = TRANSFER_TIMEOUT_MS;
528
597
  const iface = this.getDeviceInterface(dev);
529
598
  if (process.platform === 'linux') {
530
599
  try {
@@ -532,7 +601,7 @@ class NodeUsbTransport {
532
601
  iface.detachKernelDriver();
533
602
  }
534
603
  }
535
- catch (_e) {
604
+ catch (_d) {
536
605
  }
537
606
  }
538
607
  iface.claim();
@@ -543,29 +612,27 @@ class NodeUsbTransport {
543
612
  }
544
613
  epIn.timeout = TRANSFER_TIMEOUT_MS;
545
614
  epOut.timeout = TRANSFER_TIMEOUT_MS;
546
- yield clearEndpointHalt(epIn);
547
- yield clearEndpointHalt(epOut);
548
- yield this.drainStaleInput(epIn);
615
+ yield this.drainStaleInput(path, epIn);
549
616
  this.openDevices.set(path, { device: dev, iface, epIn, epOut });
550
617
  }
551
618
  catch (err) {
552
619
  try {
553
620
  dev.close();
554
621
  }
555
- catch (_f) {
622
+ catch (_e) {
556
623
  }
557
624
  throw err;
558
625
  }
559
626
  });
560
627
  }
561
- drainStaleInput(epIn) {
628
+ drainStaleInput(path, epIn) {
562
629
  return __awaiter(this, void 0, void 0, function* () {
563
630
  const originalTimeout = epIn.timeout;
564
631
  epIn.timeout = 50;
565
632
  try {
566
633
  for (let index = 0; index < 16; index += 1) {
567
634
  try {
568
- yield transferInOnce(epIn, PACKET_SIZE);
635
+ yield this.transferInOnce(path, epIn, PACKET_SIZE);
569
636
  }
570
637
  catch (_a) {
571
638
  break;
@@ -584,37 +651,33 @@ class NodeUsbTransport {
584
651
  return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Unable to detect USB protocol: device did not respond to Protocol V1 Initialize or Protocol V2 Ping');
585
652
  }
586
653
  detectProtocol(path, expectedProtocol) {
587
- var _a, _b, _c, _d, _e;
654
+ var _a;
588
655
  return __awaiter(this, void 0, void 0, function* () {
589
- if (expectedProtocol === 'V1') {
590
- if (yield this.probeProtocolV1(path)) {
591
- this.deviceProtocol.set(path, 'V1');
592
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] detectProtocol: path=${path} -> V1 (expected)`);
593
- return 'V1';
594
- }
595
- throw this.createProtocolMismatchError(expectedProtocol);
596
- }
597
656
  if (expectedProtocol === 'V2') {
598
657
  if (yield this.probeProtocolV2(path)) {
599
658
  this.deviceProtocol.set(path, 'V2');
600
- (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug(`[NodeUsbTransport] detectProtocol: path=${path} -> V2 (expected)`);
659
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] detectProtocol: path=${path} -> V2 (expected)`);
601
660
  return 'V2';
602
661
  }
603
662
  throw this.createProtocolMismatchError(expectedProtocol);
604
663
  }
664
+ if (expectedProtocol === 'V1') {
665
+ if (yield this.probeProtocolV1(path)) {
666
+ this.deviceProtocol.set(path, 'V1');
667
+ return 'V1';
668
+ }
669
+ throw this.createProtocolMismatchError(expectedProtocol);
670
+ }
605
671
  if (this.deviceProtocol.get(path) === 'V2' && (yield this.probeProtocolV2(path))) {
606
672
  this.deviceProtocol.set(path, 'V2');
607
- (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug(`[NodeUsbTransport] detectProtocol: path=${path} -> V2 (cached)`);
608
673
  return 'V2';
609
674
  }
610
675
  if (yield this.probeProtocolV1(path)) {
611
676
  this.deviceProtocol.set(path, 'V1');
612
- (_d = this.Log) === null || _d === void 0 ? void 0 : _d.debug(`[NodeUsbTransport] detectProtocol: path=${path} -> V1`);
613
677
  return 'V1';
614
678
  }
615
679
  if (yield this.probeProtocolV2(path)) {
616
680
  this.deviceProtocol.set(path, 'V2');
617
- (_e = this.Log) === null || _e === void 0 ? void 0 : _e.debug(`[NodeUsbTransport] detectProtocol: path=${path} -> V2`);
618
681
  return 'V2';
619
682
  }
620
683
  this.deviceProtocol.delete(path);
@@ -622,16 +685,15 @@ class NodeUsbTransport {
622
685
  });
623
686
  }
624
687
  resetConnectionAfterProbe(path) {
625
- var _a, _b;
688
+ var _a;
626
689
  return __awaiter(this, void 0, void 0, function* () {
627
- (_a = this.protocolV2Assemblers.get(path)) === null || _a === void 0 ? void 0 : _a.reset();
628
- this.protocolV2Sessions.delete(path);
629
- this.protocolV2ReadTimeouts.delete(path);
690
+ yield this.rotateProtocolV2UsbGeneration(path, 'Node USB protocol probe reset');
630
691
  try {
692
+ yield this.cancelActiveTransfers(path);
631
693
  yield this.closeOpenDevice(path);
632
694
  }
633
695
  catch (error) {
634
- (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[NodeUsbTransport] close after protocol probe error:', error);
696
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[NodeUsbTransport] close after protocol probe error:', error);
635
697
  }
636
698
  yield this.enumerate();
637
699
  yield this.openDevice(path);
@@ -675,7 +737,6 @@ class NodeUsbTransport {
675
737
  });
676
738
  }
677
739
  probeProtocolV1(path) {
678
- var _a;
679
740
  return __awaiter(this, void 0, void 0, function* () {
680
741
  if (!this.messages) {
681
742
  return false;
@@ -684,8 +745,7 @@ class NodeUsbTransport {
684
745
  yield this.callProtocolV1(path, 'Initialize', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT });
685
746
  return true;
686
747
  }
687
- catch (error) {
688
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[NodeUsbTransport] Protocol V1 Initialize probe failed:', error);
748
+ catch (_error) {
689
749
  return false;
690
750
  }
691
751
  });
@@ -704,96 +764,61 @@ class NodeUsbTransport {
704
764
  });
705
765
  });
706
766
  }
707
- writeProtocolV2Frame(path, frame) {
708
- var _a;
767
+ getProtocolV2UsbSchemas() {
768
+ if (!this.messages || !this.messagesV2) {
769
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
770
+ }
771
+ return {
772
+ protocolV1: this.messages,
773
+ protocolV2: this.messagesV2,
774
+ };
775
+ }
776
+ getProtocolV2UsbLogger() {
777
+ return this.Log;
778
+ }
779
+ writeProtocolV2UsbPacket(path, frame, _context) {
709
780
  return __awaiter(this, void 0, void 0, function* () {
710
- let lastError;
711
- for (let attempt = 1; attempt <= PACKET_IO_MAX_RETRIES; attempt++) {
781
+ if (this.cancelled) {
782
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromOutside, 'Cancelled');
783
+ }
784
+ yield this.transferOutOnce(path, this.getOpenDevice(path).epOut, Buffer.from(frame));
785
+ });
786
+ }
787
+ readProtocolV2UsbPacket(path, _context) {
788
+ return __awaiter(this, void 0, void 0, function* () {
789
+ for (;;) {
712
790
  if (this.cancelled) {
713
791
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromOutside, 'Cancelled');
714
792
  }
715
793
  try {
716
- yield transferOutOnce(this.getOpenDevice(path).epOut, Buffer.from(frame));
717
- return;
794
+ const packet = yield this.transferInOnce(path, this.getOpenDevice(path).epIn, transport.PROTOCOL_V2_FRAME_MAX_BYTES);
795
+ return new Uint8Array(packet.buffer.slice(packet.byteOffset, packet.byteOffset + packet.byteLength));
718
796
  }
719
797
  catch (error) {
720
- lastError = error;
721
- const shouldRetry = attempt < PACKET_IO_MAX_RETRIES && this.isRetryableError(error);
722
- if (!shouldRetry) {
798
+ if (!this.isUsbTransferTimeout(error)) {
723
799
  throw error;
724
800
  }
725
- try {
726
- yield this.reconnectForRetry(path, 'out', attempt, error);
727
- }
728
- catch (reconnectError) {
729
- lastError = reconnectError;
730
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] Protocol V2 write reconnect failed on retry ${attempt}/${PACKET_IO_MAX_RETRIES}: ${this.getErrorMessage(reconnectError)}`);
731
- break;
732
- }
733
801
  }
734
802
  }
735
- throw lastError;
736
803
  });
737
804
  }
738
- receiveProtocolV2Frame(path, timeoutMs) {
805
+ resetProtocolV2UsbNativeLink(path, _reason) {
739
806
  return __awaiter(this, void 0, void 0, function* () {
740
- let assembler = this.protocolV2Assemblers.get(path);
741
- if (!assembler) {
742
- assembler = new transport.ProtocolV2FrameAssembler(transport.PROTOCOL_V2_FRAME_MAX_BYTES);
743
- this.protocolV2Assemblers.set(path, assembler);
744
- }
745
- let frame = assembler.push(new Uint8Array(0));
746
- const deadline = timeoutMs ? Date.now() + timeoutMs : undefined;
747
- while (!frame) {
748
- const transferIn = this.transferInWithRetry(path, this.getOpenDevice(path), transport.PROTOCOL_V2_FRAME_MAX_BYTES);
749
- const packet = deadline
750
- ? yield this.withProtocolReadTimeout(path, transferIn, Math.max(deadline - Date.now(), 1), 'V2')
751
- : yield transferIn;
752
- const bytes = new Uint8Array(packet.buffer.slice(packet.byteOffset, packet.byteOffset + packet.byteLength));
753
- try {
754
- frame = assembler.push(bytes);
755
- }
756
- catch (error) {
757
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.NetworkError, error instanceof Error ? error.message : String(error));
758
- }
759
- }
760
- return frame;
807
+ yield this.cancelActiveTransfers(path);
808
+ yield this.closeOpenDevice(path);
761
809
  });
762
810
  }
763
- callProtocolV2(path, name, data, options) {
811
+ onProtocolV2UsbLinkInvalidated(path, reason) {
764
812
  var _a;
813
+ this.deviceProtocol.delete(path);
814
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug(`[NodeUsbTransport] Protocol V2 link invalidated: ${path}`, reason);
815
+ }
816
+ createProtocolV2UsbTimeoutError(name, timeoutMs) {
817
+ return new transport.ProtocolV2LinkError('response-timeout', `Protocol V2 response timeout after ${timeoutMs}ms for ${name}`);
818
+ }
819
+ callProtocolV2(path, name, data, options) {
765
820
  return __awaiter(this, void 0, void 0, function* () {
766
- const protocolV1Messages = this.messages;
767
- if (!this.messagesV2) {
768
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured, 'Protocol V2 schema not configured');
769
- }
770
- if (!protocolV1Messages) {
771
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
772
- }
773
- let session = this.protocolV2Sessions.get(path);
774
- if (!session) {
775
- session = new transport.ProtocolV2Session({
776
- schemas: {
777
- protocolV1: protocolV1Messages,
778
- protocolV2: this.messagesV2,
779
- },
780
- router: transport.PROTOCOL_V2_CHANNEL_USB,
781
- writeFrame: (frame) => this.writeProtocolV2Frame(path, frame),
782
- readFrame: () => this.receiveProtocolV2Frame(path, this.protocolV2ReadTimeouts.get(path)),
783
- logger: this.Log,
784
- logPrefix: 'ProtocolV2 NodeUSB',
785
- createTimeoutError: (messageName, timeoutMs) => new Error(`Protocol V2 response timeout after ${timeoutMs}ms for ${messageName}`),
786
- });
787
- this.protocolV2Sessions.set(path, session);
788
- }
789
- this.protocolV2ReadTimeouts.set(path, options === null || options === void 0 ? void 0 : options.timeoutMs);
790
- (_a = this.protocolV2Assemblers.get(path)) === null || _a === void 0 ? void 0 : _a.reset();
791
- try {
792
- return yield session.call(name, data, options);
793
- }
794
- finally {
795
- this.protocolV2ReadTimeouts.delete(path);
796
- }
821
+ return this.callProtocolV2Usb(path, name, data, options);
797
822
  });
798
823
  }
799
824
  receiveData(path, dev, timeoutMs) {
@@ -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"}
package/jest.config.js ADDED
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ preset: '../../jest.config.js',
3
+ testEnvironment: 'node',
4
+ modulePathIgnorePatterns: ['node_modules', '<rootDir>/dist'],
5
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-usb",
3
- "version": "1.2.0-alpha.3",
3
+ "version": "1.2.0-alpha.30",
4
4
  "description": "OneKey hardware wallet direct USB transport plugin (libusb)",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -16,14 +16,15 @@
16
16
  "scripts": {
17
17
  "dev": "rimraf dist && rollup -c ../../build/rollup.config.js -w",
18
18
  "build": "rimraf dist && rollup -c ../../build/rollup.config.js",
19
+ "test": "jest",
19
20
  "lint": "eslint .",
20
21
  "lint:fix": "eslint . --fix"
21
22
  },
22
23
  "dependencies": {
23
- "@onekeyfe/hd-shared": "1.2.0-alpha.3",
24
- "@onekeyfe/hd-transport": "1.2.0-alpha.3",
24
+ "@onekeyfe/hd-shared": "1.2.0-alpha.30",
25
+ "@onekeyfe/hd-transport": "1.2.0-alpha.30",
25
26
  "bytebuffer": "^5.0.1",
26
27
  "usb": "^2.14.0"
27
28
  },
28
- "gitHead": "54a4a40baee7e376b9a810dade60007d2c9b00c9"
29
+ "gitHead": "07405d2e3dcdd0ba351ae98b7cf4f61690ef2913"
29
30
  }