@onekeyfe/hd-core 1.2.0-alpha.74 → 1.2.0-alpha.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/__tests__/connectSettings.test.ts +5 -45
  2. package/__tests__/devicePoolBootloaderPath.test.ts +64 -0
  3. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  4. package/__tests__/protocol-v2.test.ts +100 -405
  5. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  6. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  7. package/dist/api/FirmwareUpdateV2.d.ts +0 -10
  8. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  9. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  10. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  11. package/dist/api/FirmwareUpdateV4.d.ts +5 -25
  12. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  13. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  14. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  15. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -8
  16. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  17. package/dist/api/firmware/getBinary.d.ts +0 -7
  18. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  19. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  20. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  21. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  22. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  23. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  24. package/dist/core/index.d.ts.map +1 -1
  25. package/dist/data-manager/DataManager.d.ts +0 -1
  26. package/dist/data-manager/DataManager.d.ts.map +1 -1
  27. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  28. package/dist/device/Device.d.ts +0 -1
  29. package/dist/device/Device.d.ts.map +1 -1
  30. package/dist/device/DeviceConnector.d.ts +1 -1
  31. package/dist/device/DeviceConnector.d.ts.map +1 -1
  32. package/dist/device/DevicePool.d.ts +1 -0
  33. package/dist/device/DevicePool.d.ts.map +1 -1
  34. package/dist/index.d.ts +2 -180
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +1078 -3083
  37. package/dist/inject.d.ts.map +1 -1
  38. package/dist/lowLevelInject.d.ts.map +1 -1
  39. package/dist/topLevelInject.d.ts.map +1 -1
  40. package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -4
  41. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  42. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  43. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  44. package/dist/types/api/export.d.ts +1 -4
  45. package/dist/types/api/export.d.ts.map +1 -1
  46. package/dist/types/api/firmwareUpdate.d.ts +0 -68
  47. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  48. package/dist/types/api/index.d.ts +1 -9
  49. package/dist/types/api/index.d.ts.map +1 -1
  50. package/dist/types/settings.d.ts +0 -13
  51. package/dist/types/settings.d.ts.map +1 -1
  52. package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
  53. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  54. package/package.json +4 -4
  55. package/src/api/CheckAllFirmwareRelease.ts +6 -57
  56. package/src/api/FirmwareUpdate.ts +1 -13
  57. package/src/api/FirmwareUpdateV2.ts +121 -296
  58. package/src/api/FirmwareUpdateV3.ts +57 -263
  59. package/src/api/FirmwareUpdateV4.ts +349 -881
  60. package/src/api/device/DeviceUpdateBootloader.ts +6 -125
  61. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +1 -72
  62. package/src/api/firmware/updateBootloader.ts +4 -19
  63. package/src/api/firmware/uploadFirmware.ts +22 -140
  64. package/src/core/index.ts +16 -0
  65. package/src/data-manager/DataManager.ts +54 -62
  66. package/src/data-manager/connectSettings.ts +0 -11
  67. package/src/device/Device.ts +3 -7
  68. package/src/device/DeviceConnector.ts +2 -2
  69. package/src/device/DevicePool.ts +15 -1
  70. package/src/index.ts +0 -5
  71. package/src/inject.ts +2 -22
  72. package/src/lowLevelInject.ts +1 -5
  73. package/src/topLevelInject.ts +1 -5
  74. package/src/types/api/checkAllFirmwareRelease.ts +0 -4
  75. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  76. package/src/types/api/export.ts +0 -18
  77. package/src/types/api/firmwareUpdate.ts +0 -75
  78. package/src/types/api/index.ts +0 -14
  79. package/src/types/settings.ts +0 -13
  80. package/src/utils/deviceFeaturesCompat.ts +0 -6
  81. package/__tests__/device-initialize-timeout.test.ts +0 -56
  82. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  83. package/__tests__/firmware-update/device-update-bootloader.test.ts +0 -87
  84. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  85. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  86. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  87. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
  88. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  89. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -394
  90. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  91. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -231
  92. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -64
  93. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  94. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  95. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  96. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  97. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  98. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  99. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  100. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  101. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  102. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  103. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  104. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
  105. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  106. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  107. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  108. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  109. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  110. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  111. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  112. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  113. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  114. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  115. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  116. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
  117. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -449
  118. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  119. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  120. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -14,45 +14,18 @@ import { BaseMethod } from './BaseMethod';
14
14
  import { validateParams } from './helpers/paramsValidator';
15
15
  import { DevicePool } from '../device/DevicePool';
16
16
  import { getBinary, getInfo, getSysResourceBinary } from './firmware/getBinary';
17
- import { normalizeFirmwarePreparationError } from './firmware/FirmwarePreparationError';
18
- import {
19
- updateResources,
20
- updateResourcesFromSources,
21
- uploadFirmwareFromSource,
22
- } from './firmware/uploadFirmware';
23
- import { BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS } from './firmware/FirmwareUpdateBaseMethod';
24
- import { LoggerNames, getDeviceType, getDeviceUUID, getLogger, wait } from '../utils';
25
- import { resolveDeviceBootloaderMode } from '../utils/deviceFeaturesCompat';
17
+ import { updateResources, uploadFirmware } from './firmware/uploadFirmware';
18
+ import { LoggerNames, getLogger, wait } from '../utils';
26
19
  import { FirmwareUpdateTipMessage, createUiMessage } from '../events/ui-request';
27
20
  import { DeviceModelToTypes } from '../types';
28
21
  import { DataManager } from '../data-manager';
29
22
  import { DEVICE } from '../events';
30
- import { type FirmwareByteSource, openFirmwareByteSource } from './firmware/FirmwareArtifactSource';
31
- import { resolveFirmwareUpdateHostBinding } from './firmware/FirmwareHostBinding';
32
- import {
33
- assertFirmwareUpdatePreparedPlanBinding,
34
- assertFirmwareUpdatePreparedPlanDeviceIdentity,
35
- getFirmwareUpdateResourceName,
36
- } from './firmware/FirmwareUpdatePreparedPlan';
37
23
 
38
24
  import type { Features, KnownDevice } from '../types';
39
25
  import type { FirmwareBinary } from './firmware/getBinary';
40
- import type {
41
- FirmwareArtifactReader,
42
- FirmwareArtifactReference,
43
- } from '../types/api/firmwareUpdate';
44
- import type { FirmwareUpdatePreparedPlan } from '../types/api/firmwareUpdatePreparedPlan';
45
26
 
46
27
  type Params = {
47
28
  binary?: ArrayBuffer;
48
- artifact?: FirmwareArtifactReference;
49
- resourceEntries?: Array<{
50
- entryName: string;
51
- artifact: FirmwareArtifactReference;
52
- }>;
53
- artifactReader?: FirmwareArtifactReader;
54
- preparedPlan?: FirmwareUpdatePreparedPlan;
55
- platform?: FirmwareUpdatePreparedPlan['platform'];
56
29
  version?: number[];
57
30
  updateType: 'firmware' | 'ble';
58
31
  forcedUpdateRes?: boolean;
@@ -133,13 +106,6 @@ const normalizeFirmwareBinary = (binary: unknown): FirmwareBinary | undefined =>
133
106
  return normalized.buffer;
134
107
  };
135
108
 
136
- const toArrayBuffer = (binary: FirmwareBinary): ArrayBuffer => {
137
- if (binary instanceof ArrayBuffer) {
138
- return binary;
139
- }
140
- return new Uint8Array(binary.buffer, binary.byteOffset, binary.byteLength).slice().buffer;
141
- };
142
-
143
109
  export default class FirmwareUpdateV2 extends BaseMethod<Params> {
144
110
  checkPromise: Deferred<any> | null = null;
145
111
 
@@ -186,32 +152,6 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
186
152
  binary: payload.binary,
187
153
  };
188
154
  }
189
-
190
- if ('artifact' in payload) {
191
- const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration);
192
- const target = payload.isUpdateBootloader ? 'bootloader' : payload.updateType;
193
- const resourceBindings = (payload.resourceEntries ?? []).map(
194
- (entry: { entryName: string; artifact: FirmwareArtifactReference }) => ({
195
- target: 'resource' as const,
196
- entryName: entry.entryName,
197
- artifact: entry.artifact,
198
- })
199
- );
200
- assertFirmwareUpdatePreparedPlanBinding({
201
- preparedPlan: payload.preparedPlan,
202
- executor: 'v2',
203
- platform: payload.platform,
204
- scopeTargets: [target, ...(target === 'firmware' ? (['resource'] as const) : [])],
205
- bindings: [{ target, artifact: payload.artifact }, ...resourceBindings],
206
- });
207
- this.params = {
208
- ...this.params,
209
- preparedPlan: payload.preparedPlan,
210
- artifact: payload.artifact,
211
- resourceEntries: payload.resourceEntries,
212
- artifactReader: hostBinding.artifactReader,
213
- };
214
- }
215
155
  }
216
156
 
217
157
  postTipMessage = (message: string) => {
@@ -247,10 +187,6 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
247
187
  this.checkPromise = createDeferred();
248
188
  const env = DataManager.getSettings('env');
249
189
  const isBleReconnect = connectId && DataManager.isBleConnect(env);
250
- // Tracks the in-flight BLE probe so interval ticks never overlap: a superseded
251
- // Initialize left pending on the V1 transport is exactly what later times out
252
- // and used to tear down the connection mid-firmware-upload.
253
- let bleProbeInFlight = false;
254
190
 
255
191
  Log.log('FirmwareUpdateV2 [checkDeviceToBootloader] isBleReconnect: ', isBleReconnect);
256
192
 
@@ -298,8 +234,6 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
298
234
  }
299
235
 
300
236
  if (isBleReconnect) {
301
- if (bleProbeInFlight) return;
302
- bleProbeInFlight = true;
303
237
  try {
304
238
  await this.device.deviceConnector?.acquire(
305
239
  this.device.originalDescriptor.id,
@@ -307,10 +241,7 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
307
241
  true,
308
242
  this.payload.connectProtocol ?? this.device.originalDescriptor.protocolType
309
243
  );
310
- // Bound each probe so a request the rebooting device never received
311
- // frees the slot for the next tick instead of hanging into the
312
- // 30s reboot budget.
313
- await this.device.initialize({ timeoutMs: BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS });
244
+ await this.device.initialize();
314
245
  if (this.device.isBootloader()) {
315
246
  clearInterval(intervalTimer);
316
247
  this.checkPromise?.resolve(true);
@@ -318,8 +249,6 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
318
249
  } catch (e) {
319
250
  // ignore error because of device is not connected
320
251
  Log.log('catch Bluetooth error when device is restarting: ', e);
321
- } finally {
322
- bleProbeInFlight = false;
323
252
  }
324
253
  } else {
325
254
  await this._checkDeviceInBootloaderMode(connectId, intervalTimer, timeoutTimer);
@@ -415,255 +344,151 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
415
344
  const { features, commands } = device;
416
345
  const deviceType = device.getCurrentDeviceType();
417
346
 
418
- // Protocol V2 (Pro2) uses DeviceFirmwareUpdate and must not enter this legacy flow.
419
- if (device.isProtocolV2()) {
420
- throw ERRORS.TypedError(
421
- HardwareErrorCode.RuntimeError,
422
- 'Protocol V2 firmware update must use firmwareUpdateV4'
423
- );
424
- }
425
- if (params.preparedPlan) {
426
- assertFirmwareUpdatePreparedPlanDeviceIdentity({
427
- preparedPlan: params.preparedPlan,
428
- deviceIdentity: getDeviceUUID(features) || undefined,
429
- bootloaderMode: resolveDeviceBootloaderMode(features),
430
- deviceModel: String(getDeviceType(features)),
431
- });
432
- }
433
-
434
347
  const deviceFirmwareType = device.getCurrentFirmwareType();
435
348
  const firmwareType = params.firmwareType ?? deviceFirmwareType;
436
349
 
437
350
  this.checkVersionForCopyTouchResource(features, firmwareType);
438
351
 
439
- let preparedSource: FirmwareByteSource | undefined;
440
- try {
441
- const acquireFirmwareSource = async (): Promise<FirmwareByteSource> => {
442
- try {
443
- if (preparedSource) {
444
- return preparedSource;
445
- }
352
+ let preparedBinary: FirmwareBinary | undefined;
353
+ const acquireFirmwareBinary = async (): Promise<FirmwareBinary> => {
354
+ try {
355
+ if (preparedBinary) {
356
+ return preparedBinary;
357
+ }
446
358
 
447
- if (params.binary !== undefined) {
448
- const binary = normalizeFirmwareBinary(params.binary);
449
- if (!binary) {
450
- throw new Error('firmware binary is empty or invalid');
451
- }
452
- const source = await openFirmwareByteSource({
453
- binary: toArrayBuffer(binary),
454
- });
455
- if (!source) {
456
- throw new Error('firmware binary is empty or invalid');
457
- }
458
- preparedSource = source;
459
- return source;
359
+ if (params.binary !== undefined) {
360
+ preparedBinary = normalizeFirmwareBinary(params.binary);
361
+ if (!preparedBinary) {
362
+ throw new Error('firmware binary is empty or invalid');
460
363
  }
364
+ return preparedBinary;
365
+ }
461
366
 
462
- if (params.artifact) {
463
- const source = await openFirmwareByteSource({
464
- artifact: params.artifact,
465
- reader: params.artifactReader,
466
- });
467
- if (!source) {
468
- throw new Error('firmware artifact is not prepared');
469
- }
470
- preparedSource = source;
471
- return source;
472
- }
367
+ if (!device.features) {
368
+ throw ERRORS.TypedError(
369
+ HardwareErrorCode.RuntimeError,
370
+ 'no features found for this device'
371
+ );
372
+ }
473
373
 
474
- if (!device.features) {
475
- throw ERRORS.TypedError(
476
- HardwareErrorCode.RuntimeError,
477
- 'no features found for this device'
478
- );
479
- }
374
+ this.postTipMessage('DownloadFirmware');
375
+ const firmware = await getBinary({
376
+ features: device.features,
377
+ version: params.version,
378
+ updateType: params.updateType,
379
+ isUpdateBootloader: params.isUpdateBootloader,
380
+ firmwareType,
381
+ requestOptions: FIRMWARE_DOWNLOAD_REQUEST_OPTIONS,
382
+ });
383
+ preparedBinary = normalizeFirmwareBinary(firmware.binary);
384
+ if (!preparedBinary) {
385
+ throw new Error('downloaded firmware binary is empty or invalid');
386
+ }
387
+ this.postTipMessage('DownloadFirmwareSuccess');
388
+ return preparedBinary;
389
+ } catch (err) {
390
+ throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateDownloadFailed, err.message ?? err);
391
+ }
392
+ };
480
393
 
481
- if (
482
- params.artifactReader ||
483
- DataManager.getSettings('firmwareManifestMode') === 'external-only'
484
- ) {
485
- throw ERRORS.TypedError(
486
- HardwareErrorCode.RuntimeError,
487
- 'Firmware must be prepared by the external firmware host',
488
- {
489
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
490
- artifactName: 'firmware',
491
- }
492
- );
493
- }
394
+ if (!device.isBootloader() && features) {
395
+ const serialNo = device.getCurrentSerialNo();
396
+ // should go to bootloader mode manually
397
+ if (this.isEnteredManuallyBoot()) {
398
+ return Promise.reject(ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateManuallyEnterBoot));
399
+ }
494
400
 
495
- this.postTipMessage('DownloadFirmware');
496
- const firmware = await getBinary({
497
- features: device.features,
498
- version: params.version,
499
- updateType: params.updateType,
500
- isUpdateBootloader: params.isUpdateBootloader,
501
- firmwareType,
502
- requestOptions: FIRMWARE_DOWNLOAD_REQUEST_OPTIONS,
503
- });
504
- const binary = normalizeFirmwareBinary(firmware.binary);
505
- if (!binary) {
506
- throw new Error('downloaded firmware binary is empty or invalid');
507
- }
508
- const source = await openFirmwareByteSource({
509
- binary: toArrayBuffer(binary),
510
- });
511
- if (!source) {
512
- throw new Error('downloaded firmware binary is empty or invalid');
401
+ // check & upgrade firmware resource
402
+ if (this.isSupportResourceUpdate(params.updateType)) {
403
+ this.postTipMessage('CheckLatestUiResource');
404
+ const resourceUrl = DataManager.getSysResourcesLatestRelease({
405
+ features,
406
+ forcedUpdateRes: params.forcedUpdateRes,
407
+ firmwareType,
408
+ });
409
+ if (resourceUrl) {
410
+ this.postTipMessage('DownloadLatestUiResource');
411
+ const resource = await getSysResourceBinary(resourceUrl);
412
+ this.postTipMessage('DownloadLatestUiResourceSuccess');
413
+ if (resource) {
414
+ await updateResources(
415
+ this.device.getCommands().typedCall.bind(this.device.getCommands()),
416
+ this.postMessage,
417
+ device,
418
+ resource.binary
419
+ );
513
420
  }
514
- preparedSource = source;
515
- this.postTipMessage('DownloadFirmwareSuccess');
516
- return source;
517
- } catch (err) {
518
- throw normalizeFirmwarePreparationError(err);
519
421
  }
520
- };
422
+ }
521
423
 
522
- if (!device.isBootloader() && features) {
523
- const serialNo = device.getCurrentSerialNo();
524
- // should go to bootloader mode manually
525
- if (this.isEnteredManuallyBoot()) {
526
- throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateManuallyEnterBoot);
424
+ // check if the device commands has been disposed
425
+ this.device?.commands?.checkDisposed();
426
+
427
+ // A failed firmware download must leave the device in normal mode.
428
+ await acquireFirmwareBinary();
429
+
430
+ // The request may outlive the current transport command instance.
431
+ this.device?.commands?.checkDisposed();
432
+
433
+ // auto go to bootloader mode
434
+ try {
435
+ this.postTipMessage('AutoRebootToBootloader');
436
+ const bootRes = await commands.typedCall('DeviceBackToBoot', 'Success');
437
+ // @ts-expect-error
438
+ if (bootRes.type === 'CallMethodError') {
439
+ throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure);
527
440
  }
441
+ this.postTipMessage('GoToBootloaderSuccess');
442
+ this.checkDeviceToBootloader(this.payload.connectId);
528
443
 
529
- // All network-backed input must be ready before the first device mutation.
530
- await acquireFirmwareSource();
531
-
532
- // check & upgrade firmware resource
533
- if (this.isSupportResourceUpdate(params.updateType)) {
534
- this.postTipMessage('CheckLatestUiResource');
535
- const resourceUrl = DataManager.getSysResourcesLatestRelease({
536
- features,
537
- forcedUpdateRes: params.forcedUpdateRes,
538
- firmwareType,
539
- });
540
- if (resourceUrl) {
541
- this.postTipMessage('DownloadLatestUiResource');
542
- if (params.resourceEntries?.length) {
543
- const sources: Array<{
544
- entryName: string;
545
- source: FirmwareByteSource;
546
- }> = [];
547
- try {
548
- for (const entry of params.resourceEntries) {
549
- const resourceName = getFirmwareUpdateResourceName(entry.entryName);
550
- const source = await openFirmwareByteSource({
551
- artifact: entry.artifact,
552
- reader: params.artifactReader,
553
- });
554
- if (!source) {
555
- throw new Error('Firmware resource entry is not prepared');
556
- }
557
- sources.push({ entryName: resourceName, source });
558
- }
559
- await updateResourcesFromSources(
560
- this.device.getCommands().typedCall.bind(this.device.getCommands()),
561
- this.postMessage,
562
- device,
563
- sources.map(entry => ({
564
- entryName: entry.entryName,
565
- source: entry.source,
566
- }))
567
- );
568
- } finally {
569
- await Promise.all(
570
- sources.map(entry => entry.source.close().catch(() => undefined))
571
- );
572
- }
573
- this.postTipMessage('DownloadLatestUiResourceSuccess');
574
- } else {
575
- if (
576
- params.artifactReader ||
577
- DataManager.getSettings('firmwareManifestMode') === 'external-only'
578
- ) {
579
- throw ERRORS.TypedError(
580
- HardwareErrorCode.RuntimeError,
581
- 'Firmware resource must be prepared by the external firmware host',
582
- {
583
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
584
- artifactName: 'resource',
585
- }
586
- );
587
- }
588
- const resourceBinary: ArrayBuffer | Buffer = (await getSysResourceBinary(resourceUrl))
589
- .binary;
590
- this.postTipMessage('DownloadLatestUiResourceSuccess');
591
- await updateResources(
592
- this.device.getCommands().typedCall.bind(this.device.getCommands()),
593
- this.postMessage,
594
- device,
595
- resourceBinary
596
- );
597
- }
598
- }
444
+ // force clean classic device cache so that the device can initialize again
445
+ if (DeviceModelToTypes.model_classic.includes(deviceType)) {
446
+ DevicePool.clearDeviceCache(serialNo);
599
447
  }
448
+ delete DevicePool.devicesCache[''];
449
+ await this.checkPromise?.promise;
450
+ this.checkPromise = null;
600
451
 
601
- // The request may outlive the current transport command instance.
452
+ // check if the device commands has been disposed
602
453
  this.device?.commands?.checkDisposed();
603
454
 
604
- // auto go to bootloader mode
605
- try {
606
- this.postTipMessage('AutoRebootToBootloader');
607
- const bootRes = await commands.typedCall('DeviceBackToBoot', 'Success');
608
- // @ts-expect-error
609
- if (bootRes.type === 'CallMethodError') {
610
- throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure);
611
- }
612
- this.postTipMessage('GoToBootloaderSuccess');
613
- this.checkDeviceToBootloader(this.payload.connectId);
614
-
615
- // force clean classic device cache so that the device can initialize again
616
- if (DeviceModelToTypes.model_classic.includes(deviceType)) {
617
- DevicePool.clearDeviceCache(serialNo);
618
- }
619
- delete DevicePool.devicesCache[''];
620
- await this.checkPromise?.promise;
621
- this.checkPromise = null;
622
-
623
- // check if the device commands has been disposed
624
- this.device?.commands?.checkDisposed();
625
-
626
- /**
627
- * Touch 1 with bootloader v2.5.0 issue: BLE chip need more time for looking up name, here change the delay time to 3000ms after rebooting.
628
- */
629
- const isTouch = DeviceModelToTypes.model_touch.includes(deviceType);
630
- await wait(isTouch ? 3000 : 1500);
631
- } catch (e) {
632
- if (e instanceof HardwareError) {
633
- return Promise.reject(e);
634
- }
635
- console.log('auto go to bootloader mode failed: ', e);
636
- return Promise.reject(
637
- ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure)
638
- );
455
+ /**
456
+ * Touch 1 with bootloader v2.5.0 issue: BLE chip need more time for looking up name, here change the delay time to 3000ms after rebooting.
457
+ */
458
+ const isTouch = DeviceModelToTypes.model_touch.includes(deviceType);
459
+ await wait(isTouch ? 3000 : 1500);
460
+ } catch (e) {
461
+ if (e instanceof HardwareError) {
462
+ return Promise.reject(e);
639
463
  }
464
+ console.log('auto go to bootloader mode failed: ', e);
465
+ return Promise.reject(
466
+ ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure)
467
+ );
640
468
  }
469
+ }
641
470
 
642
- // Devices already in bootloader mode still acquire through the same helper.
643
- const source = await acquireFirmwareSource();
644
-
645
- // check if the device commands has been disposed
646
- this.device?.commands?.checkDisposed();
471
+ // Devices already in bootloader mode still acquire through the same helper.
472
+ const binary = await acquireFirmwareBinary();
647
473
 
648
- await this.device.acquire();
474
+ // check if the device commands has been disposed
475
+ this.device?.commands?.checkDisposed();
649
476
 
650
- const response = await uploadFirmwareFromSource(
651
- params.updateType,
652
- this.device.getCommands().typedCall.bind(this.device.getCommands()),
653
- this.postMessage,
654
- device,
655
- source,
656
- true,
657
- params.isUpdateBootloader
658
- );
477
+ await this.device.acquire();
659
478
 
660
- if (this.connectId) {
661
- DevicePool.clearDeviceCache(this.connectId);
662
- }
479
+ const response = await uploadFirmware(
480
+ params.updateType,
481
+ this.device.getCommands().typedCall.bind(this.device.getCommands()),
482
+ this.postMessage,
483
+ device,
484
+ { payload: binary, rebootOnSuccess: true },
485
+ params.isUpdateBootloader
486
+ );
663
487
 
664
- return response;
665
- } finally {
666
- await preparedSource?.close().catch(() => undefined);
488
+ if (this.connectId) {
489
+ DevicePool.clearDeviceCache(this.connectId);
667
490
  }
491
+
492
+ return response;
668
493
  }
669
494
  }