@onekeyfe/hd-core 1.2.0-alpha.7 → 1.2.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/device-wallet-session-store.test.ts +131 -0
- package/__tests__/protocol-v2-firmware-targets.test.ts +19 -0
- package/__tests__/protocol-v2.test.ts +742 -536
- package/dist/api/ClearSessionCache.d.ts +9 -0
- package/dist/api/ClearSessionCache.d.ts.map +1 -0
- package/dist/api/FirmwareUpdateV4.d.ts +7 -6
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +1 -1
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts +9 -0
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/device/Device.d.ts +2 -2
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceWalletSessionStore.d.ts +15 -0
- package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -0
- package/dist/index.d.ts +32 -19
- package/dist/index.js +651 -288
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +1 -0
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +13 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdate.d.ts +4 -1
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +6 -1
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +6 -2
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/api/sessionCache.d.ts +10 -0
- package/dist/types/api/sessionCache.d.ts.map +1 -0
- package/dist/types/settings.d.ts +6 -14
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/ClearSessionCache.ts +28 -0
- package/src/api/FileRead.ts +2 -2
- package/src/api/FirmwareUpdateV4.ts +276 -239
- package/src/api/index.ts +3 -0
- package/src/api/protocol-v2/DeviceSessionGet.ts +26 -0
- package/src/api/protocol-v2/DeviceStatusGet.ts +14 -0
- package/src/api/protocol-v2/FilesystemFormat.ts +4 -1
- package/src/api/protocol-v2/helpers.ts +17 -14
- package/src/data/messages/messages-protocol-v2.json +134 -3
- package/src/data/messages/messages.json +8 -0
- package/src/device/Device.ts +64 -56
- package/src/device/DeviceWalletSessionStore.ts +78 -0
- package/src/inject.ts +5 -2
- package/src/protocols/protocol-v2/index.ts +1 -0
- package/src/protocols/protocol-v2/walletSession.ts +83 -0
- package/src/types/api/firmwareUpdate.ts +8 -2
- package/src/types/api/index.ts +10 -3
- package/src/types/api/protocolV2.ts +16 -2
- package/src/types/api/sessionCache.ts +14 -0
- package/src/types/settings.ts +14 -16
- package/src/utils/deviceFeaturesUtils.ts +22 -32
|
@@ -38,7 +38,6 @@ import type {
|
|
|
38
38
|
Features,
|
|
39
39
|
IFirmwareReleaseInfo,
|
|
40
40
|
IProtocolV2FirmwareComponent,
|
|
41
|
-
IProtocolV2ResourceManifestPackage,
|
|
42
41
|
IVersionArray,
|
|
43
42
|
} from '../types';
|
|
44
43
|
|
|
@@ -47,19 +46,20 @@ const Log = getLogger(LoggerNames.Method);
|
|
|
47
46
|
const SESSION_ERROR = 'session not found';
|
|
48
47
|
const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 60 * 1000;
|
|
49
48
|
const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
|
|
50
|
-
const PROTOCOL_V2_START_UPDATE_TIMEOUT = 60 * 1000;
|
|
49
|
+
const PROTOCOL_V2_START_UPDATE_TIMEOUT = 3 * 60 * 1000;
|
|
51
50
|
const PROTOCOL_V2_INSTALL_TIMEOUT = 5 * 60 * 1000;
|
|
52
51
|
const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
|
|
53
52
|
const PROTOCOL_V2_TARGET_STATUS_IN_PROGRESS = 1;
|
|
54
53
|
const PROTOCOL_V2_TARGET_STATUS_FINISHED = 2;
|
|
55
54
|
const PROTOCOL_V2_TARGET_STATUS_FAILED_MIN = 3;
|
|
56
55
|
const PROTOCOL_V2_CONNECT_PROTOCOL = 'V2';
|
|
57
|
-
const PROTOCOL_V2_FIRMWARE_STAGING_VOLUME = '
|
|
56
|
+
const PROTOCOL_V2_FIRMWARE_STAGING_VOLUME = 'vol0:/';
|
|
58
57
|
const PROTOCOL_V2_MIN_FILE_CHUNK_SIZE = 64;
|
|
59
58
|
const PROTOCOL_V2_CONNECT_RETRY_COUNT = 10;
|
|
60
59
|
const PROTOCOL_V2_CONNECT_POLL_INTERVAL = 500;
|
|
61
60
|
const PROTOCOL_V2_CONNECT_SINGLE_TIMEOUT = 75 * 1000;
|
|
62
61
|
const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT = 60 * 1000;
|
|
62
|
+
const PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT = 3;
|
|
63
63
|
const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
|
|
64
64
|
const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
|
|
65
65
|
const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
|
|
@@ -107,6 +107,25 @@ type ProtocolV2InstallTarget = ProtocolV2InstallItem & {
|
|
|
107
107
|
path: string;
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
+
type ProtocolV2FileTransferParams = PROTO.FirmwareUpload & {
|
|
111
|
+
filePath: string;
|
|
112
|
+
processedSize?: number;
|
|
113
|
+
totalSize?: number;
|
|
114
|
+
onTransferredBytes?: (transferredBytes: number) => void;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/** RESC bundle okpkg(FileWrite 直写模式),每个独立同步到 devicePath */
|
|
118
|
+
type ProtocolV2ResourceBundleBinary = {
|
|
119
|
+
name: string;
|
|
120
|
+
binary: ArrayBuffer;
|
|
121
|
+
devicePath: string;
|
|
122
|
+
/** 远端配置模式下的下载 URL(手动模式不填) */
|
|
123
|
+
url?: string;
|
|
124
|
+
version?: IVersionArray;
|
|
125
|
+
payloadHash?: string;
|
|
126
|
+
headerHash?: string;
|
|
127
|
+
};
|
|
128
|
+
|
|
110
129
|
type ProtocolV2RemoteComponentBinary = ProtocolV2RemoteComponentTarget & {
|
|
111
130
|
binary: ArrayBuffer;
|
|
112
131
|
};
|
|
@@ -114,7 +133,7 @@ type ProtocolV2RemoteComponentBinary = ProtocolV2RemoteComponentTarget & {
|
|
|
114
133
|
type ProtocolV2RemoteComponentTarget = {
|
|
115
134
|
fileName: string;
|
|
116
135
|
targetId: number;
|
|
117
|
-
kind: 'bootloader' | 'firmware'
|
|
136
|
+
kind: 'bootloader' | 'firmware';
|
|
118
137
|
};
|
|
119
138
|
|
|
120
139
|
type ProtocolV2OkppHeader = {
|
|
@@ -167,11 +186,6 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS: Readonly<
|
|
|
167
186
|
targetId: ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04,
|
|
168
187
|
kind: 'firmware',
|
|
169
188
|
},
|
|
170
|
-
CRATE: {
|
|
171
|
-
fileName: 'resource.bin',
|
|
172
|
-
targetId: ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_CRATE,
|
|
173
|
-
kind: 'resource',
|
|
174
|
-
},
|
|
175
189
|
};
|
|
176
190
|
|
|
177
191
|
const PROTOCOL_V2_ROMLOADER_UNSUPPORTED_MESSAGE =
|
|
@@ -393,7 +407,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
393
407
|
|
|
394
408
|
validateParams(payload, [
|
|
395
409
|
{ name: 'chunkSize', type: 'number' },
|
|
396
|
-
{ name: 'resourceBinaries', type: 'array', allowEmpty: true },
|
|
397
410
|
{ name: 'forcedUpdateRes', type: 'boolean' },
|
|
398
411
|
{ name: 'bootloaderBinary', type: 'buffer' },
|
|
399
412
|
{ name: 'romloaderBinary', type: 'buffer' },
|
|
@@ -406,6 +419,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
406
419
|
{ name: 'se04Binary', type: 'buffer' },
|
|
407
420
|
{ name: 'firmwareType', type: 'string' },
|
|
408
421
|
{ name: 'platform', type: 'string' },
|
|
422
|
+
{ name: 'resourceBundleFiles', type: 'array', allowEmpty: true },
|
|
409
423
|
]);
|
|
410
424
|
|
|
411
425
|
this.params = {
|
|
@@ -420,7 +434,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
420
434
|
se02Binary: payload.se02Binary,
|
|
421
435
|
se03Binary: payload.se03Binary,
|
|
422
436
|
se04Binary: payload.se04Binary,
|
|
423
|
-
|
|
437
|
+
resourceBundleFiles: payload.resourceBundleFiles,
|
|
424
438
|
firmwareType: payload.firmwareType,
|
|
425
439
|
platform: payload.platform,
|
|
426
440
|
};
|
|
@@ -459,13 +473,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
459
473
|
const deviceFirmwareType = getFirmwareType(deviceFeatures);
|
|
460
474
|
const firmwareType = this.params.firmwareType ?? deviceFirmwareType;
|
|
461
475
|
|
|
462
|
-
let resourceBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
463
476
|
let fwBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
464
477
|
let bootloaderBinary: ArrayBuffer | null = null;
|
|
465
478
|
let installItems: ProtocolV2InstallItem[] | undefined;
|
|
466
479
|
try {
|
|
467
480
|
this.postTipMessage(FirmwareUpdateTipMessage.StartDownloadFirmware);
|
|
468
|
-
resourceBinaryMap = await this.prepareResourceBinaries(firmwareType, deviceFeatures);
|
|
469
481
|
fwBinaryMap = this.collectExplicitTargetBinaries();
|
|
470
482
|
bootloaderBinary = this.prepareBootloaderBinary();
|
|
471
483
|
if (!this.hasExplicitProtocolV2Payload(fwBinaryMap)) {
|
|
@@ -473,7 +485,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
473
485
|
firmwareType,
|
|
474
486
|
deviceFeatures
|
|
475
487
|
);
|
|
476
|
-
resourceBinaryMap = remoteBinaries.resourceBinaryMap;
|
|
477
488
|
bootloaderBinary = remoteBinaries.bootloaderBinary;
|
|
478
489
|
fwBinaryMap = remoteBinaries.fwBinaryMap;
|
|
479
490
|
installItems = remoteBinaries.installItems;
|
|
@@ -483,7 +494,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
483
494
|
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateDownloadFailed, err.message ?? err);
|
|
484
495
|
}
|
|
485
496
|
|
|
486
|
-
|
|
497
|
+
const resourceBundles = this.prepareProtocolV2ResourceBundles(firmwareType, deviceFeatures);
|
|
498
|
+
|
|
499
|
+
if (!bootloaderBinary && fwBinaryMap.length === 0 && !resourceBundles?.length) {
|
|
487
500
|
throw ERRORS.TypedError(
|
|
488
501
|
HardwareErrorCode.FirmwareUpdateDownloadFailed,
|
|
489
502
|
'No firmware to update'
|
|
@@ -493,10 +506,10 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
493
506
|
await this.enterProtocolV2BootloaderMode();
|
|
494
507
|
|
|
495
508
|
await this.executeProtocolV2Update({
|
|
496
|
-
resourceBinaryMap,
|
|
497
509
|
fwBinaryMap,
|
|
498
510
|
bootloaderBinary,
|
|
499
511
|
...(installItems ? { installItems } : undefined),
|
|
512
|
+
...(resourceBundles?.length ? { resourceBundles } : undefined),
|
|
500
513
|
});
|
|
501
514
|
|
|
502
515
|
await this.exitProtocolV2BootloaderToNormal();
|
|
@@ -519,68 +532,26 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
519
532
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Device features not available');
|
|
520
533
|
}
|
|
521
534
|
|
|
522
|
-
private async prepareResourceBinaries(firmwareType: EFirmwareType, features: Features) {
|
|
523
|
-
if (this.params.resourceBinaries?.length) {
|
|
524
|
-
this.params.resourceBinaries.forEach((binary, index) => {
|
|
525
|
-
if (!(binary instanceof ArrayBuffer)) {
|
|
526
|
-
throw ERRORS.TypedError(
|
|
527
|
-
HardwareErrorCode.CallMethodInvalidParameter,
|
|
528
|
-
`Parameter [resourceBinaries.${index}] is of type invalid and should be [buffer].`
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
return this.params.resourceBinaries.map((binary, index) => ({
|
|
534
|
-
fileName: `resource-${index + 1}.bin`,
|
|
535
|
-
binary,
|
|
536
|
-
targetId: ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_CRATE,
|
|
537
|
-
}));
|
|
538
|
-
}
|
|
539
|
-
const resourceUrl = DataManager.getSysResourcesLatestRelease({
|
|
540
|
-
features,
|
|
541
|
-
forcedUpdateRes: this.params.forcedUpdateRes,
|
|
542
|
-
firmwareType,
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
if (resourceUrl) {
|
|
546
|
-
const resource = (await getSysResourceBinary(resourceUrl)).binary;
|
|
547
|
-
return [
|
|
548
|
-
{
|
|
549
|
-
fileName: 'resource.bin',
|
|
550
|
-
binary: resource,
|
|
551
|
-
targetId: ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_CRATE,
|
|
552
|
-
},
|
|
553
|
-
];
|
|
554
|
-
}
|
|
555
|
-
Log.warn('No resource url found');
|
|
556
|
-
return [];
|
|
557
|
-
}
|
|
558
|
-
|
|
559
535
|
private prepareBootloaderBinary(): ArrayBuffer | null {
|
|
560
536
|
return this.params.bootloaderBinary ?? null;
|
|
561
537
|
}
|
|
562
538
|
|
|
563
539
|
private hasExplicitProtocolV2Payload(fwBinaryMap: ProtocolV2TargetBinary[]) {
|
|
564
540
|
return (
|
|
565
|
-
!!this.params.
|
|
541
|
+
!!this.params.resourceBundleFiles?.length ||
|
|
566
542
|
!!this.params.bootloaderBinary ||
|
|
567
543
|
fwBinaryMap.length > 0
|
|
568
544
|
);
|
|
569
545
|
}
|
|
570
546
|
|
|
571
547
|
private buildProtocolV2InstallItems({
|
|
572
|
-
resourceBinaryMap,
|
|
573
548
|
bootloaderBinary,
|
|
574
549
|
fwBinaryMap,
|
|
575
550
|
}: {
|
|
576
|
-
resourceBinaryMap: ProtocolV2TargetBinary[];
|
|
577
551
|
bootloaderBinary: ArrayBuffer | null;
|
|
578
552
|
fwBinaryMap: ProtocolV2TargetBinary[];
|
|
579
553
|
}): ProtocolV2InstallItem[] {
|
|
580
|
-
const installItems: ProtocolV2InstallItem[] =
|
|
581
|
-
...resource,
|
|
582
|
-
kind: 'resource',
|
|
583
|
-
}));
|
|
554
|
+
const installItems: ProtocolV2InstallItem[] = [];
|
|
584
555
|
|
|
585
556
|
if (bootloaderBinary) {
|
|
586
557
|
installItems.push({
|
|
@@ -738,83 +709,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
738
709
|
return parseProtocolV2OkppHeader(headerBytes);
|
|
739
710
|
}
|
|
740
711
|
|
|
741
|
-
private
|
|
742
|
-
pkg: IProtocolV2ResourceManifestPackage,
|
|
743
|
-
manifestVersion?: IVersionArray
|
|
744
|
-
) {
|
|
745
|
-
try {
|
|
746
|
-
const header = await this.readProtocolV2DeviceFileHeader(pkg.path);
|
|
747
|
-
if (!header) return false;
|
|
748
|
-
|
|
749
|
-
const expectedType = pkg.type ?? 'RESC';
|
|
750
|
-
const expectedVersion = pkg.version ?? manifestVersion;
|
|
751
|
-
if (header.type !== expectedType) return false;
|
|
752
|
-
if (expectedVersion && compareProtocolV2Versions(header.version, expectedVersion) !== 0) {
|
|
753
|
-
return false;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
const expectedPayloadHash = normalizeProtocolV2Hex(pkg.payloadHash);
|
|
757
|
-
if (expectedPayloadHash && header.payloadHash !== expectedPayloadHash) return false;
|
|
758
|
-
|
|
759
|
-
const expectedHeaderHash = normalizeProtocolV2Hex(pkg.headerHash);
|
|
760
|
-
if (expectedHeaderHash && header.headerHash !== expectedHeaderHash) return false;
|
|
761
|
-
|
|
762
|
-
return true;
|
|
763
|
-
} catch (error) {
|
|
764
|
-
Log.log(`Protocol V2 resource package check failed for ${pkg.path}: `, error);
|
|
765
|
-
return false;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
private async isProtocolV2ResourceManifestSatisfied(
|
|
770
|
-
manifest: IFirmwareReleaseInfo['resourceManifest']
|
|
771
|
-
) {
|
|
772
|
-
if (!manifest?.packages?.length) return false;
|
|
773
|
-
|
|
774
|
-
for (const pkg of manifest.packages) {
|
|
775
|
-
if (!(await this.isProtocolV2ResourcePackageMatched(pkg, manifest.version))) {
|
|
776
|
-
return false;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
return true;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
private getProtocolV2ResourceManifest(
|
|
783
|
-
release: IFirmwareReleaseInfo,
|
|
784
|
-
component: IProtocolV2FirmwareComponent
|
|
785
|
-
) {
|
|
786
|
-
return component.resourceManifest ?? release.resourceManifest;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
private getProtocolV2ResourceComponentFileName(key: string) {
|
|
790
|
-
const safeKey = key.replace(/[^a-z0-9_-]/gi, '_') || 'resource';
|
|
791
|
-
return `resource-${safeKey}.bin`;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
private async shouldInstallRemoteProtocolV2Component(
|
|
712
|
+
private shouldInstallRemoteProtocolV2Component(
|
|
795
713
|
release: IFirmwareReleaseInfo,
|
|
796
714
|
key: string,
|
|
797
715
|
component: IProtocolV2FirmwareComponent,
|
|
798
716
|
target: ProtocolV2RemoteComponentTarget,
|
|
799
717
|
features: Features
|
|
800
718
|
) {
|
|
801
|
-
if (target.kind === 'resource') {
|
|
802
|
-
if (
|
|
803
|
-
this.params.forcedUpdateRes ||
|
|
804
|
-
features.bootloaderMode ||
|
|
805
|
-
features.mode === 'bootloader'
|
|
806
|
-
) {
|
|
807
|
-
return true;
|
|
808
|
-
}
|
|
809
|
-
const resourceMatched = await this.isProtocolV2ResourceManifestSatisfied(
|
|
810
|
-
this.getProtocolV2ResourceManifest(release, component)
|
|
811
|
-
);
|
|
812
|
-
if (resourceMatched) {
|
|
813
|
-
Log.log(`[FirmwareUpdateV4] skip Protocol V2 resource component ${key}; manifest matched`);
|
|
814
|
-
}
|
|
815
|
-
return !resourceMatched;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
719
|
const versionSatisfied = this.isProtocolV2ComponentVersionSatisfied(
|
|
819
720
|
release,
|
|
820
721
|
component,
|
|
@@ -849,14 +750,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
849
750
|
private async prepareRemoteProtocolV2Binaries(firmwareType: EFirmwareType, features: Features) {
|
|
850
751
|
const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
|
|
851
752
|
|
|
852
|
-
const resourceBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
853
753
|
let bootloaderBinary: ArrayBuffer | null = null;
|
|
854
754
|
const fwBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
855
755
|
const installItems: ProtocolV2InstallItem[] = [];
|
|
856
756
|
|
|
857
757
|
if (!release) {
|
|
858
758
|
return {
|
|
859
|
-
resourceBinaryMap,
|
|
860
759
|
bootloaderBinary,
|
|
861
760
|
fwBinaryMap,
|
|
862
761
|
installItems,
|
|
@@ -867,7 +766,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
867
766
|
|
|
868
767
|
for (const [key, component] of entries) {
|
|
869
768
|
const target = this.getRemoteComponentTarget(key, component);
|
|
870
|
-
const shouldInstall =
|
|
769
|
+
const shouldInstall = this.shouldInstallRemoteProtocolV2Component(
|
|
871
770
|
release,
|
|
872
771
|
key,
|
|
873
772
|
component,
|
|
@@ -876,15 +775,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
876
775
|
);
|
|
877
776
|
if (shouldInstall) {
|
|
878
777
|
const remoteBinary = await this.downloadRemoteProtocolV2Component(key, component);
|
|
879
|
-
if (remoteBinary.kind === '
|
|
880
|
-
const binaryEntry = {
|
|
881
|
-
fileName: this.getProtocolV2ResourceComponentFileName(key),
|
|
882
|
-
binary: remoteBinary.binary,
|
|
883
|
-
targetId: remoteBinary.targetId,
|
|
884
|
-
};
|
|
885
|
-
resourceBinaryMap.push(binaryEntry);
|
|
886
|
-
installItems.push({ ...binaryEntry, kind: remoteBinary.kind });
|
|
887
|
-
} else if (remoteBinary.kind === 'bootloader') {
|
|
778
|
+
if (remoteBinary.kind === 'bootloader') {
|
|
888
779
|
bootloaderBinary = remoteBinary.binary;
|
|
889
780
|
installItems.push({
|
|
890
781
|
fileName: remoteBinary.fileName,
|
|
@@ -905,13 +796,153 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
905
796
|
}
|
|
906
797
|
|
|
907
798
|
return {
|
|
908
|
-
resourceBinaryMap,
|
|
909
799
|
bootloaderBinary,
|
|
910
800
|
fwBinaryMap,
|
|
911
801
|
installItems,
|
|
912
802
|
};
|
|
913
803
|
}
|
|
914
804
|
|
|
805
|
+
// ============================================================
|
|
806
|
+
// RESC bundle 直写增量同步(FileRead 比对 + FilesystemFileWrite 直写)
|
|
807
|
+
// ============================================================
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* 准备 RESC bundle 列表。
|
|
811
|
+
*
|
|
812
|
+
* 两种模式(同 FirmwareUpdateV3 的 binary vs version 模式):
|
|
813
|
+
* - 用户传了 resourceBundleFiles(binary 数组):直接用,不做版本比对。
|
|
814
|
+
* - 用户没传:从远端 config.json 的 release.resourceBundles 拉取,
|
|
815
|
+
* 此时 syncProtocolV2ResourceBundles 会按需下载 + 比对设备已有 header 跳过。
|
|
816
|
+
*/
|
|
817
|
+
private prepareProtocolV2ResourceBundles(
|
|
818
|
+
firmwareType: EFirmwareType,
|
|
819
|
+
features: Features
|
|
820
|
+
): ProtocolV2ResourceBundleBinary[] | undefined {
|
|
821
|
+
// 模式1:用户手动传入 binary,直接安装,不比对
|
|
822
|
+
if (this.params.resourceBundleFiles?.length) {
|
|
823
|
+
return this.params.resourceBundleFiles.map(file => ({
|
|
824
|
+
name: file.devicePath.split('/').pop() ?? file.devicePath,
|
|
825
|
+
binary: file.binary,
|
|
826
|
+
devicePath: file.devicePath,
|
|
827
|
+
}));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// 模式2:远端配置模式,后续按需下载 + 比对
|
|
831
|
+
const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
|
|
832
|
+
if (!release?.resourceBundles?.length) return undefined;
|
|
833
|
+
|
|
834
|
+
return release.resourceBundles.map(bundle => ({
|
|
835
|
+
name: bundle.name,
|
|
836
|
+
binary: new ArrayBuffer(0),
|
|
837
|
+
devicePath: bundle.devicePath,
|
|
838
|
+
url: bundle.url,
|
|
839
|
+
version: bundle.version,
|
|
840
|
+
payloadHash: bundle.payloadHash,
|
|
841
|
+
headerHash: bundle.headerHash,
|
|
842
|
+
})) as ProtocolV2ResourceBundleBinary[];
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* 同步 RESC bundles 到设备。
|
|
847
|
+
*
|
|
848
|
+
* 手动传入模式(有 binary):直接 FileWrite 直写,不比对。
|
|
849
|
+
* 远端配置模式(无 binary,有 url):按需下载 + FileRead 比对跳过已更新的。
|
|
850
|
+
*/
|
|
851
|
+
private async syncProtocolV2ResourceBundles(
|
|
852
|
+
bundles: ProtocolV2ResourceBundleBinary[],
|
|
853
|
+
firmwareSize: number
|
|
854
|
+
): Promise<{ processedSize: number; totalSize: number }> {
|
|
855
|
+
const transferStartTime = Date.now();
|
|
856
|
+
const transferTransport = this.getProtocolV2FirmwareTransferTransport();
|
|
857
|
+
|
|
858
|
+
const isManualMode = bundles.every(b => b.binary.byteLength > 0);
|
|
859
|
+
let bundlesToSync = bundles;
|
|
860
|
+
|
|
861
|
+
// 远端配置模式:按需下载 + 比对跳过
|
|
862
|
+
if (!isManualMode) {
|
|
863
|
+
const filtered: ProtocolV2ResourceBundleBinary[] = [];
|
|
864
|
+
for (const bundle of bundles) {
|
|
865
|
+
// 下载 binary
|
|
866
|
+
if (bundle.binary.byteLength === 0 && bundle.url) {
|
|
867
|
+
Log.log(`[FirmwareUpdateV4] downloading RESC bundle ${bundle.name} from ${bundle.url}`);
|
|
868
|
+
const { binary } = await getSysResourceBinary(bundle.url);
|
|
869
|
+
bundle.binary = binary;
|
|
870
|
+
}
|
|
871
|
+
// 比对设备上已有 header
|
|
872
|
+
const upToDate = await this.isProtocolV2ResourceBundleUpToDate(bundle);
|
|
873
|
+
if (upToDate) {
|
|
874
|
+
Log.log(`[FirmwareUpdateV4] skip RESC bundle ${bundle.name}; already up to date`);
|
|
875
|
+
} else {
|
|
876
|
+
filtered.push(bundle);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
bundlesToSync = filtered;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
if (bundlesToSync.length === 0) {
|
|
883
|
+
Log.log('[FirmwareUpdateV4] all RESC bundles up to date, nothing to sync');
|
|
884
|
+
return { processedSize: 0, totalSize: firmwareSize };
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// FileWrite 直写到设备
|
|
888
|
+
let totalSize = 0;
|
|
889
|
+
for (const b of bundlesToSync) totalSize += b.binary.byteLength;
|
|
890
|
+
|
|
891
|
+
const transferTotalSize = totalSize + firmwareSize;
|
|
892
|
+
let processedSize = 0;
|
|
893
|
+
for (const bundle of bundlesToSync) {
|
|
894
|
+
Log.log(
|
|
895
|
+
`[FirmwareUpdateV4] syncing RESC bundle ${bundle.name} -> ${bundle.devicePath} bytes=${bundle.binary.byteLength}`
|
|
896
|
+
);
|
|
897
|
+
processedSize = await this.protocolV2CommonUpdateProcess({
|
|
898
|
+
payload: bundle.binary,
|
|
899
|
+
filePath: bundle.devicePath,
|
|
900
|
+
processedSize,
|
|
901
|
+
totalSize: transferTotalSize,
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
const elapsedMs = Date.now() - transferStartTime;
|
|
906
|
+
Log.log(
|
|
907
|
+
`[FirmwareUpdateV4] RESC bundle sync finished transport=${transferTransport} bytes=${totalSize} elapsed=${(
|
|
908
|
+
elapsedMs / 1000
|
|
909
|
+
).toFixed(2)}s speed=${formatProtocolV2TransferSpeed(totalSize, elapsedMs)} KB/s`
|
|
910
|
+
);
|
|
911
|
+
return { processedSize, totalSize: transferTotalSize };
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* 比对设备上已有 okpkg 的 OKPP header(仅远端配置模式使用)。
|
|
916
|
+
*/
|
|
917
|
+
private async isProtocolV2ResourceBundleUpToDate(
|
|
918
|
+
bundle: ProtocolV2ResourceBundleBinary
|
|
919
|
+
): Promise<boolean> {
|
|
920
|
+
if (this.params.forcedUpdateRes) return false;
|
|
921
|
+
if (!bundle.version && !bundle.payloadHash) return false;
|
|
922
|
+
|
|
923
|
+
try {
|
|
924
|
+
const header = await this.readProtocolV2DeviceFileHeader(bundle.devicePath);
|
|
925
|
+
if (!header) return false;
|
|
926
|
+
|
|
927
|
+
if (bundle.version) {
|
|
928
|
+
const cmp = compareProtocolV2Versions(header.version, bundle.version);
|
|
929
|
+
if (cmp === undefined || cmp !== 0) return false;
|
|
930
|
+
}
|
|
931
|
+
if (bundle.payloadHash) {
|
|
932
|
+
const expected = normalizeProtocolV2Hex(bundle.payloadHash);
|
|
933
|
+
if (expected && header.payloadHash !== expected) return false;
|
|
934
|
+
}
|
|
935
|
+
if (bundle.headerHash) {
|
|
936
|
+
const expected = normalizeProtocolV2Hex(bundle.headerHash);
|
|
937
|
+
if (expected && header.headerHash !== expected) return false;
|
|
938
|
+
}
|
|
939
|
+
return true;
|
|
940
|
+
} catch (error) {
|
|
941
|
+
Log.log(`[FirmwareUpdateV4] RESC bundle ${bundle.name} header check failed: `, error);
|
|
942
|
+
return false;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
915
946
|
private isProtocolV2BootloaderMode() {
|
|
916
947
|
if (typeof this.device.isBootloader === 'function') {
|
|
917
948
|
return this.device.isBootloader();
|
|
@@ -1014,30 +1045,48 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1014
1045
|
}
|
|
1015
1046
|
|
|
1016
1047
|
private async executeProtocolV2Update({
|
|
1017
|
-
resourceBinaryMap,
|
|
1018
1048
|
fwBinaryMap,
|
|
1019
1049
|
bootloaderBinary,
|
|
1020
1050
|
installItems,
|
|
1051
|
+
resourceBundles,
|
|
1021
1052
|
}: {
|
|
1022
|
-
resourceBinaryMap?: ProtocolV2TargetBinary[];
|
|
1023
1053
|
fwBinaryMap?: ProtocolV2TargetBinary[];
|
|
1024
1054
|
bootloaderBinary?: ArrayBuffer | null;
|
|
1025
1055
|
installItems?: ProtocolV2InstallItem[];
|
|
1056
|
+
resourceBundles?: ProtocolV2ResourceBundleBinary[];
|
|
1026
1057
|
}) {
|
|
1027
1058
|
const orderedInstallItems =
|
|
1028
1059
|
installItems ??
|
|
1029
1060
|
this.buildProtocolV2InstallItems({
|
|
1030
|
-
resourceBinaryMap: resourceBinaryMap ?? [],
|
|
1031
1061
|
bootloaderBinary: bootloaderBinary ?? null,
|
|
1032
1062
|
fwBinaryMap: fwBinaryMap ?? [],
|
|
1033
1063
|
});
|
|
1034
|
-
let totalSize = 0;
|
|
1035
|
-
let processedSize = 0;
|
|
1036
|
-
let transferredSize = 0;
|
|
1037
1064
|
|
|
1038
|
-
|
|
1065
|
+
let firmwareSize = 0;
|
|
1066
|
+
for (const item of orderedInstallItems) firmwareSize += item.binary.byteLength;
|
|
1039
1067
|
|
|
1040
1068
|
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
1069
|
+
|
|
1070
|
+
let processedSize = 0;
|
|
1071
|
+
let totalSize = firmwareSize;
|
|
1072
|
+
if (resourceBundles?.length) {
|
|
1073
|
+
const resourceTransfer = await this.syncProtocolV2ResourceBundles(
|
|
1074
|
+
resourceBundles,
|
|
1075
|
+
firmwareSize
|
|
1076
|
+
);
|
|
1077
|
+
processedSize = resourceTransfer.processedSize;
|
|
1078
|
+
totalSize = resourceTransfer.totalSize;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// 只有 RESC bundle、没有固件 target 时跳过 staging/install 阶段
|
|
1082
|
+
if (orderedInstallItems.length === 0) {
|
|
1083
|
+
Log.log('[FirmwareUpdateV4] no firmware targets to install (RESC bundles only)');
|
|
1084
|
+
if (totalSize > 0) {
|
|
1085
|
+
this.postProgressMessage(100, 'transferData');
|
|
1086
|
+
}
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
let transferredSize = processedSize;
|
|
1041
1090
|
const transferStartTime = Date.now();
|
|
1042
1091
|
const transferTransport = this.getProtocolV2FirmwareTransferTransport();
|
|
1043
1092
|
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
@@ -1064,6 +1113,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1064
1113
|
onTransferredBytes,
|
|
1065
1114
|
});
|
|
1066
1115
|
transferredSize = processedSize;
|
|
1116
|
+
await this.verifyProtocolV2StagedFile(filePath, item.binary.byteLength);
|
|
1067
1117
|
|
|
1068
1118
|
stagedInstallTargets.push({
|
|
1069
1119
|
...item,
|
|
@@ -1093,44 +1143,32 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1093
1143
|
|
|
1094
1144
|
this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
|
|
1095
1145
|
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
};
|
|
1104
|
-
|
|
1105
|
-
for (const item of stagedInstallTargets) {
|
|
1106
|
-
const target = {
|
|
1107
|
-
target_id: item.targetId,
|
|
1108
|
-
path: item.path,
|
|
1109
|
-
};
|
|
1110
|
-
if (item.kind === 'resource') {
|
|
1111
|
-
await flushFirmwareTargets();
|
|
1112
|
-
const resourceTargets = [target];
|
|
1113
|
-
Log.log(
|
|
1114
|
-
`[FirmwareUpdateV4] DeviceFirmwareUpdateRequest resources=${JSON.stringify(
|
|
1115
|
-
resourceTargets
|
|
1116
|
-
)}`
|
|
1117
|
-
);
|
|
1118
|
-
const startResponse = await this.protocolV2StartFirmwareUpdate({
|
|
1119
|
-
targets: resourceTargets,
|
|
1120
|
-
});
|
|
1121
|
-
await this.waitForProtocolV2FirmwareUpdateComplete(resourceTargets, startResponse);
|
|
1122
|
-
} else {
|
|
1123
|
-
firmwareTargets.push(target);
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
await flushFirmwareTargets();
|
|
1146
|
+
const allTargets = stagedInstallTargets.map(item => ({
|
|
1147
|
+
target_id: item.targetId,
|
|
1148
|
+
path: item.path,
|
|
1149
|
+
}));
|
|
1150
|
+
Log.log(`[FirmwareUpdateV4] DeviceFirmwareUpdateRequest targets=${JSON.stringify(allTargets)}`);
|
|
1151
|
+
const startResponse = await this.protocolV2StartFirmwareUpdate({ targets: allTargets });
|
|
1152
|
+
await this.waitForProtocolV2FirmwareUpdateComplete(allTargets, startResponse);
|
|
1128
1153
|
}
|
|
1129
1154
|
|
|
1130
1155
|
private getProtocolV2InstallItemStagingPath(item: ProtocolV2InstallItem) {
|
|
1131
1156
|
return `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${item.fileName}`;
|
|
1132
1157
|
}
|
|
1133
1158
|
|
|
1159
|
+
private async verifyProtocolV2StagedFile(path: string, expectedSize: number) {
|
|
1160
|
+
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
1161
|
+
const response = await typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path });
|
|
1162
|
+
const actualSize = toProtocolV2FiniteNumber(response.message?.size);
|
|
1163
|
+
if (!response.message?.exist || response.message?.directory || actualSize !== expectedSize) {
|
|
1164
|
+
throw ERRORS.TypedError(
|
|
1165
|
+
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1166
|
+
`staged file verification failed: path=${path} exist=${!!response.message
|
|
1167
|
+
?.exist} expected=${expectedSize} actual=${actualSize ?? 'unknown'}`
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1134
1172
|
private async queryProtocolV2FirmwareUpdateStatus() {
|
|
1135
1173
|
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
1136
1174
|
return typedCall(
|
|
@@ -1389,18 +1427,37 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1389
1427
|
await this.device.initialize();
|
|
1390
1428
|
}
|
|
1391
1429
|
|
|
1392
|
-
private async protocolV2CommonUpdateProcess({
|
|
1430
|
+
private async protocolV2CommonUpdateProcess(params: ProtocolV2FileTransferParams) {
|
|
1431
|
+
let lastError: unknown;
|
|
1432
|
+
for (let attempt = 1; attempt <= PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT; attempt += 1) {
|
|
1433
|
+
try {
|
|
1434
|
+
return await this.protocolV2WriteWholeFile(params);
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
lastError = error;
|
|
1437
|
+
Log.error(
|
|
1438
|
+
`Protocol V2 file transfer failed path=${params.filePath} attempt=${attempt}/${PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT}; restarting from offset 0`,
|
|
1439
|
+
error
|
|
1440
|
+
);
|
|
1441
|
+
if (attempt === PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT) {
|
|
1442
|
+
break;
|
|
1443
|
+
}
|
|
1444
|
+
await this.recoverProtocolV2FileTransfer();
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
throw ERRORS.TypedError(
|
|
1449
|
+
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1450
|
+
`transfer data error: ${getProtocolV2UnknownErrorText(lastError)}`
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
private async protocolV2WriteWholeFile({
|
|
1393
1455
|
payload,
|
|
1394
1456
|
filePath,
|
|
1395
1457
|
processedSize,
|
|
1396
1458
|
totalSize,
|
|
1397
1459
|
onTransferredBytes,
|
|
1398
|
-
}:
|
|
1399
|
-
filePath: string;
|
|
1400
|
-
processedSize?: number;
|
|
1401
|
-
totalSize?: number;
|
|
1402
|
-
onTransferredBytes?: (transferredBytes: number) => void;
|
|
1403
|
-
}) {
|
|
1460
|
+
}: ProtocolV2FileTransferParams) {
|
|
1404
1461
|
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
1405
1462
|
let offset = 0;
|
|
1406
1463
|
const getUploadProgress = (fileOffset: number) => {
|
|
@@ -1421,7 +1478,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1421
1478
|
totalSize ?? payload.byteLength
|
|
1422
1479
|
);
|
|
1423
1480
|
|
|
1424
|
-
const writeRes = await this.
|
|
1481
|
+
const writeRes = await this.fileWriteChunk(
|
|
1425
1482
|
filePath,
|
|
1426
1483
|
payload.byteLength,
|
|
1427
1484
|
offset,
|
|
@@ -1462,7 +1519,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1462
1519
|
return env ?? 'unknown';
|
|
1463
1520
|
}
|
|
1464
1521
|
|
|
1465
|
-
private async
|
|
1522
|
+
private async fileWriteChunk(
|
|
1466
1523
|
filePath: string,
|
|
1467
1524
|
totalFileSize: number,
|
|
1468
1525
|
offset: number,
|
|
@@ -1470,57 +1527,37 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1470
1527
|
overwrite: boolean,
|
|
1471
1528
|
progress: number | null
|
|
1472
1529
|
): Promise<TypedResponseMessage<'FilesystemFile'>> {
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
if (writeRes.type
|
|
1487
|
-
if ((writeRes as any).
|
|
1488
|
-
|
|
1489
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, SESSION_ERROR);
|
|
1490
|
-
}
|
|
1530
|
+
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
1531
|
+
const writeRes = await typedCall('FilesystemFileWrite', 'FilesystemFile', {
|
|
1532
|
+
file: {
|
|
1533
|
+
path: filePath,
|
|
1534
|
+
offset,
|
|
1535
|
+
total_size: totalFileSize,
|
|
1536
|
+
data: chunk,
|
|
1537
|
+
},
|
|
1538
|
+
overwrite,
|
|
1539
|
+
append: false,
|
|
1540
|
+
ui_percentage: progress ?? undefined,
|
|
1541
|
+
});
|
|
1542
|
+
if (writeRes.type !== 'FilesystemFile') {
|
|
1543
|
+
if ((writeRes as any).type === 'CallMethodError') {
|
|
1544
|
+
if (((writeRes as any).message.error ?? '').indexOf(SESSION_ERROR) > -1) {
|
|
1545
|
+
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, SESSION_ERROR);
|
|
1491
1546
|
}
|
|
1492
|
-
throw ERRORS.TypedError(
|
|
1493
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1494
|
-
'transfer data error'
|
|
1495
|
-
);
|
|
1496
1547
|
}
|
|
1497
|
-
|
|
1498
|
-
}
|
|
1548
|
+
throw ERRORS.TypedError(HardwareErrorCode.EmmcFileWriteFirmwareError, 'transfer data error');
|
|
1549
|
+
}
|
|
1550
|
+
return writeRes;
|
|
1551
|
+
}
|
|
1499
1552
|
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
Log.error(`fileWrite error: `, error);
|
|
1507
|
-
retryCount--;
|
|
1508
|
-
if (retryCount === 0) {
|
|
1509
|
-
throw ERRORS.TypedError(
|
|
1510
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1511
|
-
'transfer data error'
|
|
1512
|
-
);
|
|
1513
|
-
}
|
|
1514
|
-
const env = DataManager.getSettings('env');
|
|
1515
|
-
if (DataManager.isBleConnect(env)) {
|
|
1516
|
-
await wait(3000);
|
|
1517
|
-
await this.acquireProtocolV2BleDevice();
|
|
1518
|
-
await this.device.initialize();
|
|
1519
|
-
}
|
|
1520
|
-
await wait(2000);
|
|
1521
|
-
}
|
|
1553
|
+
private async recoverProtocolV2FileTransfer() {
|
|
1554
|
+
const env = DataManager.getSettings('env');
|
|
1555
|
+
if (DataManager.isBleConnect(env)) {
|
|
1556
|
+
await wait(3000);
|
|
1557
|
+
await this.acquireProtocolV2BleDevice();
|
|
1558
|
+
await this.device.initialize();
|
|
1522
1559
|
}
|
|
1523
|
-
|
|
1560
|
+
await wait(2000);
|
|
1524
1561
|
}
|
|
1525
1562
|
|
|
1526
1563
|
private async acquireProtocolV2BleDevice() {
|