@onekeyfe/hd-core 1.2.0-alpha.40 → 1.2.0-alpha.41
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__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
- package/__tests__/DeviceEventRegistration.test.ts +0 -6
- package/__tests__/connectSettings.test.ts +47 -5
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
- package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
- package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
- package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
- package/__tests__/get-device-state.test.ts +12 -132
- package/__tests__/homescreen.test.ts +1 -41
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/open-wallet-session.test.ts +18 -259
- package/__tests__/protocol-v2-unlock-policy.test.ts +35 -86
- package/__tests__/protocol-v2.test.ts +632 -333
- package/__tests__/public-pro2-api-boundary.test.ts +0 -1
- package/dist/api/BaseMethod.d.ts +1 -3
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +11 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +7 -3
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +22 -5
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
- package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
- package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +8 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/api/firmware/getBinary.d.ts +7 -0
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/progressThrottle.d.ts +3 -0
- package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
- package/dist/api/firmware/updateBootloader.d.ts +2 -0
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +9 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +0 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/core/deviceEventRegistration.d.ts +0 -2
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -0
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +4 -22
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/events/device.d.ts +0 -4
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +2 -27
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +181 -88
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3162 -1614
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +1 -4
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +4 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +69 -0
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +10 -3
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +0 -3
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +0 -4
- package/dist/utils/homescreen.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Wallpaper.d.ts +0 -10
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +10 -8
- package/src/api/CheckAllFirmwareRelease.ts +51 -6
- package/src/api/FirmwareUpdateV2.ts +298 -120
- package/src/api/FirmwareUpdateV3.ts +263 -57
- package/src/api/FirmwareUpdateV4.ts +748 -281
- package/src/api/GetPassphraseState.ts +1 -7
- package/src/api/OpenWalletSession.ts +17 -54
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
- package/src/api/device/DeviceUnlock.ts +1 -1
- package/src/api/device/DeviceUpdateBootloader.ts +122 -6
- package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
- package/src/api/firmware/FirmwareHostBinding.ts +100 -0
- package/src/api/firmware/FirmwarePreparationError.ts +12 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +57 -0
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
- package/src/api/firmware/FirmwareUpdatePlan.ts +745 -0
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
- package/src/api/firmware/progressThrottle.ts +44 -0
- package/src/api/firmware/updateBootloader.ts +19 -4
- package/src/api/firmware/uploadFirmware.ts +140 -22
- package/src/api/helpers/protocolV2FileWrite.ts +4 -11
- package/src/api/index.ts +0 -1
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
- package/src/core/deviceEventRegistration.ts +0 -4
- package/src/core/index.ts +75 -118
- package/src/data/messages/messages-protocol-v2.json +0 -10
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +11 -0
- package/src/device/Device.ts +21 -193
- package/src/events/device.ts +0 -4
- package/src/events/logBlockEvent.ts +0 -1
- package/src/events/ui-request.ts +2 -32
- package/src/index.ts +5 -0
- package/src/inject.ts +22 -3
- package/src/lowLevelInject.ts +5 -1
- package/src/protocols/protocol-v2/features.ts +2 -9
- package/src/protocols/protocol-v2/lockedError.ts +10 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +5 -31
- package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
- package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
- package/src/protocols/protocol-v2/walletSession.ts +18 -93
- package/src/topLevelInject.ts +5 -1
- package/src/types/api/checkAllFirmwareRelease.ts +4 -0
- package/src/types/api/deviceUpdateBootloader.ts +6 -0
- package/src/types/api/export.ts +18 -0
- package/src/types/api/firmwareUpdate.ts +76 -0
- package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
- package/src/types/api/firmwareUpdatePlan.ts +38 -0
- package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
- package/src/types/api/index.ts +14 -2
- package/src/types/api/protocolV2.ts +0 -13
- package/src/types/settings.ts +13 -0
- package/src/utils/deviceFeaturesUtils.ts +0 -4
- package/src/utils/homescreen.ts +6 -32
- package/src/utils/index.ts +1 -6
- package/src/utils/pro2Wallpaper.ts +8 -35
- package/__tests__/deviceUploadNft.test.ts +0 -187
- package/__tests__/pro2Nft.test.ts +0 -108
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -56
- package/__tests__/uiProgressThrottle.test.ts +0 -74
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -30
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
- package/dist/utils/pro2Nft.d.ts +0 -29
- package/dist/utils/pro2Nft.d.ts.map +0 -1
- package/dist/utils/uiProgressThrottle.d.ts +0 -3
- package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
- package/src/api/protocol-v2/DeviceUploadNft.ts +0 -166
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -117
- package/src/utils/pro2Nft.ts +0 -91
- package/src/utils/uiProgressThrottle.ts +0 -63
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
1
|
+
import { EFirmwareType, ERRORS, HardwareError, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
2
|
import semver from 'semver';
|
|
3
3
|
|
|
4
|
+
import { BaseMethod } from './BaseMethod';
|
|
4
5
|
import { UI_REQUEST } from '../constants/ui-request';
|
|
5
6
|
import { DataManager } from '../data-manager';
|
|
6
7
|
import {
|
|
@@ -8,9 +9,18 @@ import {
|
|
|
8
9
|
getBootloaderReleaseInfo,
|
|
9
10
|
getFirmwareReleaseInfo,
|
|
10
11
|
} from './firmware/releaseHelper';
|
|
12
|
+
import {
|
|
13
|
+
buildFirmwareUpdatePlan,
|
|
14
|
+
validateFirmwareUpdatePlanForceTargets,
|
|
15
|
+
} from './firmware/FirmwareUpdatePlan';
|
|
11
16
|
import { getBridgeReleaseInfo } from '../utils/bridgeUpdate';
|
|
12
|
-
import {
|
|
13
|
-
|
|
17
|
+
import {
|
|
18
|
+
LoggerNames,
|
|
19
|
+
getDeviceFirmwareVersion,
|
|
20
|
+
getDeviceType,
|
|
21
|
+
getFirmwareType,
|
|
22
|
+
getLogger,
|
|
23
|
+
} from '../utils';
|
|
14
24
|
|
|
15
25
|
import type {
|
|
16
26
|
AllFirmwareRelease,
|
|
@@ -26,6 +36,7 @@ import type {
|
|
|
26
36
|
IProtocolV2FirmwareComponent,
|
|
27
37
|
IProtocolV2FirmwareComponentTarget,
|
|
28
38
|
} from '../types';
|
|
39
|
+
import type { FirmwareUpdatePlan } from '../types/api/firmwareUpdatePlan';
|
|
29
40
|
|
|
30
41
|
const UPDATE_TARGET_BY_COMPONENT_TARGET: Readonly<
|
|
31
42
|
Partial<Record<IProtocolV2FirmwareComponentTarget, FirmwareUpdateV4Target>>
|
|
@@ -246,6 +257,8 @@ export function buildProtocolV2FirmwareRelease({
|
|
|
246
257
|
};
|
|
247
258
|
}
|
|
248
259
|
|
|
260
|
+
const Log = getLogger(LoggerNames.Method);
|
|
261
|
+
|
|
249
262
|
export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
250
263
|
getSupportedProtocols() {
|
|
251
264
|
return ['V1', 'V2'] as const;
|
|
@@ -263,8 +276,13 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
263
276
|
}
|
|
264
277
|
|
|
265
278
|
const { features } = this.device;
|
|
266
|
-
const {
|
|
267
|
-
|
|
279
|
+
const {
|
|
280
|
+
checkBridgeRelease,
|
|
281
|
+
firmwareType: firmwareTypeParams,
|
|
282
|
+
platform,
|
|
283
|
+
forceUpdateTargets,
|
|
284
|
+
} = this.payload as CheckAllFirmwareReleaseParams;
|
|
285
|
+
const validatedForceUpdateTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
|
|
268
286
|
|
|
269
287
|
if (!features) {
|
|
270
288
|
return Promise.resolve(null);
|
|
@@ -295,6 +313,32 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
295
313
|
firmwareType,
|
|
296
314
|
});
|
|
297
315
|
const bleFirmwareReleaseInfo = getBleFirmwareReleaseInfo(features);
|
|
316
|
+
let firmwareUpdatePlan: FirmwareUpdatePlan | undefined;
|
|
317
|
+
try {
|
|
318
|
+
firmwareUpdatePlan = buildFirmwareUpdatePlan({
|
|
319
|
+
features,
|
|
320
|
+
firmwareType,
|
|
321
|
+
platform: platform ?? 'web',
|
|
322
|
+
firmware: firmwareRelease,
|
|
323
|
+
ble: bleFirmwareReleaseInfo,
|
|
324
|
+
bootloader: bootloaderRelease,
|
|
325
|
+
forceUpdateTargets: validatedForceUpdateTargets,
|
|
326
|
+
});
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (
|
|
329
|
+
validatedForceUpdateTargets.length > 0 ||
|
|
330
|
+
!(error instanceof HardwareError) ||
|
|
331
|
+
error.params?.firmwareUpdateCode !== 'FirmwarePlanInvalid'
|
|
332
|
+
) {
|
|
333
|
+
throw error;
|
|
334
|
+
}
|
|
335
|
+
// A Plan is an optional external-host capability. Release checks remain
|
|
336
|
+
// available for legacy and recovery flows when a Plan cannot be built.
|
|
337
|
+
Log.warn(
|
|
338
|
+
'[CheckAllFirmwareRelease] Optional firmware Plan is unavailable; using the legacy release result'
|
|
339
|
+
);
|
|
340
|
+
firmwareUpdatePlan = undefined;
|
|
341
|
+
}
|
|
298
342
|
|
|
299
343
|
return {
|
|
300
344
|
firmware: firmwareRelease,
|
|
@@ -309,7 +353,8 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
309
353
|
}
|
|
310
354
|
: undefined,
|
|
311
355
|
features,
|
|
312
|
-
|
|
356
|
+
firmwareUpdatePlan,
|
|
357
|
+
} as unknown as AllFirmwareRelease;
|
|
313
358
|
}
|
|
314
359
|
|
|
315
360
|
private async runProtocolV2(): Promise<AllFirmwareRelease> {
|
|
@@ -14,18 +14,44 @@ 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 {
|
|
18
|
-
import {
|
|
17
|
+
import { normalizeFirmwarePreparationError } from './firmware/FirmwarePreparationError';
|
|
18
|
+
import {
|
|
19
|
+
updateResources,
|
|
20
|
+
updateResourcesFromSources,
|
|
21
|
+
uploadFirmwareFromSource,
|
|
22
|
+
} from './firmware/uploadFirmware';
|
|
23
|
+
import { LoggerNames, getDeviceUUID, getLogger, wait } from '../utils';
|
|
19
24
|
import { FirmwareUpdateTipMessage, createUiMessage } from '../events/ui-request';
|
|
20
25
|
import { DeviceModelToTypes } from '../types';
|
|
21
26
|
import { DataManager } from '../data-manager';
|
|
22
27
|
import { DEVICE } from '../events';
|
|
28
|
+
import { type FirmwareByteSource, openFirmwareByteSource } from './firmware/FirmwareArtifactSource';
|
|
29
|
+
import { resolveFirmwareUpdateHostBinding } from './firmware/FirmwareHostBinding';
|
|
30
|
+
import {
|
|
31
|
+
assertFirmwareUpdatePreparedPlanBinding,
|
|
32
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
33
|
+
getFirmwareUpdateResourceName,
|
|
34
|
+
} from './firmware/FirmwareUpdatePreparedPlan';
|
|
23
35
|
|
|
24
36
|
import type { Features, KnownDevice } from '../types';
|
|
25
37
|
import type { FirmwareBinary } from './firmware/getBinary';
|
|
38
|
+
import type {
|
|
39
|
+
FirmwareArtifactReader,
|
|
40
|
+
FirmwareArtifactReference,
|
|
41
|
+
} from '../types/api/firmwareUpdate';
|
|
42
|
+
import type { FirmwareUpdatePreparedPlan } from '../types/api/firmwareUpdatePreparedPlan';
|
|
26
43
|
|
|
27
44
|
type Params = {
|
|
28
45
|
binary?: ArrayBuffer;
|
|
46
|
+
artifact?: FirmwareArtifactReference;
|
|
47
|
+
resourceArtifact?: FirmwareArtifactReference;
|
|
48
|
+
resourceEntries?: Array<{
|
|
49
|
+
entryName: string;
|
|
50
|
+
artifact: FirmwareArtifactReference;
|
|
51
|
+
}>;
|
|
52
|
+
artifactReader?: FirmwareArtifactReader;
|
|
53
|
+
preparedPlan?: FirmwareUpdatePreparedPlan;
|
|
54
|
+
platform?: FirmwareUpdatePreparedPlan['platform'];
|
|
29
55
|
version?: number[];
|
|
30
56
|
updateType: 'firmware' | 'ble';
|
|
31
57
|
forcedUpdateRes?: boolean;
|
|
@@ -106,6 +132,13 @@ const normalizeFirmwareBinary = (binary: unknown): FirmwareBinary | undefined =>
|
|
|
106
132
|
return normalized.buffer;
|
|
107
133
|
};
|
|
108
134
|
|
|
135
|
+
const toArrayBuffer = (binary: FirmwareBinary): ArrayBuffer => {
|
|
136
|
+
if (binary instanceof ArrayBuffer) {
|
|
137
|
+
return binary;
|
|
138
|
+
}
|
|
139
|
+
return new Uint8Array(binary.buffer, binary.byteOffset, binary.byteLength).slice().buffer;
|
|
140
|
+
};
|
|
141
|
+
|
|
109
142
|
export default class FirmwareUpdateV2 extends BaseMethod<Params> {
|
|
110
143
|
checkPromise: Deferred<any> | null = null;
|
|
111
144
|
|
|
@@ -152,6 +185,38 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
|
|
|
152
185
|
binary: payload.binary,
|
|
153
186
|
};
|
|
154
187
|
}
|
|
188
|
+
|
|
189
|
+
if ('artifact' in payload) {
|
|
190
|
+
const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration);
|
|
191
|
+
const target = payload.isUpdateBootloader ? 'bootloader' : payload.updateType;
|
|
192
|
+
const resourceBindings = [
|
|
193
|
+
...(payload.resourceArtifact
|
|
194
|
+
? [{ target: 'resource' as const, artifact: payload.resourceArtifact }]
|
|
195
|
+
: []),
|
|
196
|
+
...(payload.resourceEntries ?? []).map(
|
|
197
|
+
(entry: { entryName: string; artifact: FirmwareArtifactReference }) => ({
|
|
198
|
+
target: 'resource' as const,
|
|
199
|
+
entryName: entry.entryName,
|
|
200
|
+
artifact: entry.artifact,
|
|
201
|
+
})
|
|
202
|
+
),
|
|
203
|
+
];
|
|
204
|
+
assertFirmwareUpdatePreparedPlanBinding({
|
|
205
|
+
preparedPlan: payload.preparedPlan,
|
|
206
|
+
executor: 'v2',
|
|
207
|
+
platform: payload.platform,
|
|
208
|
+
scopeTargets: [target, ...(target === 'firmware' ? (['resource'] as const) : [])],
|
|
209
|
+
bindings: [{ target, artifact: payload.artifact }, ...resourceBindings],
|
|
210
|
+
});
|
|
211
|
+
this.params = {
|
|
212
|
+
...this.params,
|
|
213
|
+
preparedPlan: payload.preparedPlan,
|
|
214
|
+
artifact: payload.artifact,
|
|
215
|
+
resourceArtifact: payload.resourceArtifact,
|
|
216
|
+
resourceEntries: payload.resourceEntries,
|
|
217
|
+
artifactReader: hostBinding.artifactReader,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
155
220
|
}
|
|
156
221
|
|
|
157
222
|
postTipMessage = (message: string) => {
|
|
@@ -341,151 +406,264 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
|
|
|
341
406
|
const { features, commands } = device;
|
|
342
407
|
const deviceType = device.getCurrentDeviceType();
|
|
343
408
|
|
|
409
|
+
// Protocol V2 (Pro2) uses DeviceFirmwareUpdate and must not enter this legacy flow.
|
|
410
|
+
if (device.isProtocolV2()) {
|
|
411
|
+
throw ERRORS.TypedError(
|
|
412
|
+
HardwareErrorCode.RuntimeError,
|
|
413
|
+
'Protocol V2 firmware update must use firmwareUpdateV4'
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
if (params.preparedPlan) {
|
|
417
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
418
|
+
preparedPlan: params.preparedPlan,
|
|
419
|
+
deviceIdentity: getDeviceUUID(features) || undefined,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
344
423
|
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
345
424
|
const firmwareType = params.firmwareType ?? deviceFirmwareType;
|
|
346
425
|
|
|
347
426
|
this.checkVersionForCopyTouchResource(features, firmwareType);
|
|
348
427
|
|
|
349
|
-
let
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (params.binary !== undefined) {
|
|
357
|
-
preparedBinary = normalizeFirmwareBinary(params.binary);
|
|
358
|
-
if (!preparedBinary) {
|
|
359
|
-
throw new Error('firmware binary is empty or invalid');
|
|
428
|
+
let preparedSource: FirmwareByteSource | undefined;
|
|
429
|
+
try {
|
|
430
|
+
const acquireFirmwareSource = async (): Promise<FirmwareByteSource> => {
|
|
431
|
+
try {
|
|
432
|
+
if (preparedSource) {
|
|
433
|
+
return preparedSource;
|
|
360
434
|
}
|
|
361
|
-
return preparedBinary;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (!device.features) {
|
|
365
|
-
throw ERRORS.TypedError(
|
|
366
|
-
HardwareErrorCode.RuntimeError,
|
|
367
|
-
'no features found for this device'
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
435
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
return preparedBinary;
|
|
386
|
-
} catch (err) {
|
|
387
|
-
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateDownloadFailed, err.message ?? err);
|
|
388
|
-
}
|
|
389
|
-
};
|
|
436
|
+
if (params.binary !== undefined) {
|
|
437
|
+
const binary = normalizeFirmwareBinary(params.binary);
|
|
438
|
+
if (!binary) {
|
|
439
|
+
throw new Error('firmware binary is empty or invalid');
|
|
440
|
+
}
|
|
441
|
+
const source = await openFirmwareByteSource({
|
|
442
|
+
binary: toArrayBuffer(binary),
|
|
443
|
+
});
|
|
444
|
+
if (!source) {
|
|
445
|
+
throw new Error('firmware binary is empty or invalid');
|
|
446
|
+
}
|
|
447
|
+
preparedSource = source;
|
|
448
|
+
return source;
|
|
449
|
+
}
|
|
390
450
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
451
|
+
if (params.artifact) {
|
|
452
|
+
const source = await openFirmwareByteSource({
|
|
453
|
+
artifact: params.artifact,
|
|
454
|
+
reader: params.artifactReader,
|
|
455
|
+
});
|
|
456
|
+
if (!source) {
|
|
457
|
+
throw new Error('firmware artifact is not prepared');
|
|
458
|
+
}
|
|
459
|
+
preparedSource = source;
|
|
460
|
+
return source;
|
|
461
|
+
}
|
|
397
462
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
features,
|
|
403
|
-
forcedUpdateRes: params.forcedUpdateRes,
|
|
404
|
-
firmwareType,
|
|
405
|
-
});
|
|
406
|
-
if (resourceUrl) {
|
|
407
|
-
this.postTipMessage('DownloadLatestUiResource');
|
|
408
|
-
const resource = await getSysResourceBinary(resourceUrl);
|
|
409
|
-
this.postTipMessage('DownloadLatestUiResourceSuccess');
|
|
410
|
-
if (resource) {
|
|
411
|
-
await updateResources(
|
|
412
|
-
this.device.getCommands().typedCall.bind(this.device.getCommands()),
|
|
413
|
-
this.postMessage,
|
|
414
|
-
device,
|
|
415
|
-
resource.binary
|
|
463
|
+
if (!device.features) {
|
|
464
|
+
throw ERRORS.TypedError(
|
|
465
|
+
HardwareErrorCode.RuntimeError,
|
|
466
|
+
'no features found for this device'
|
|
416
467
|
);
|
|
417
468
|
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// check if the device commands has been disposed
|
|
422
|
-
this.device?.commands?.checkDisposed();
|
|
423
469
|
|
|
424
|
-
|
|
425
|
-
|
|
470
|
+
if (
|
|
471
|
+
params.artifactReader ||
|
|
472
|
+
DataManager.getSettings('firmwareManifestMode') === 'external-only'
|
|
473
|
+
) {
|
|
474
|
+
throw ERRORS.TypedError(
|
|
475
|
+
HardwareErrorCode.RuntimeError,
|
|
476
|
+
'Firmware must be prepared by the external firmware host',
|
|
477
|
+
{
|
|
478
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
479
|
+
artifactName: 'firmware',
|
|
480
|
+
}
|
|
481
|
+
);
|
|
482
|
+
}
|
|
426
483
|
|
|
427
|
-
|
|
428
|
-
|
|
484
|
+
this.postTipMessage('DownloadFirmware');
|
|
485
|
+
const firmware = await getBinary({
|
|
486
|
+
features: device.features,
|
|
487
|
+
version: params.version,
|
|
488
|
+
updateType: params.updateType,
|
|
489
|
+
isUpdateBootloader: params.isUpdateBootloader,
|
|
490
|
+
firmwareType,
|
|
491
|
+
requestOptions: FIRMWARE_DOWNLOAD_REQUEST_OPTIONS,
|
|
492
|
+
});
|
|
493
|
+
const binary = normalizeFirmwareBinary(firmware.binary);
|
|
494
|
+
if (!binary) {
|
|
495
|
+
throw new Error('downloaded firmware binary is empty or invalid');
|
|
496
|
+
}
|
|
497
|
+
const source = await openFirmwareByteSource({
|
|
498
|
+
binary: toArrayBuffer(binary),
|
|
499
|
+
});
|
|
500
|
+
if (!source) {
|
|
501
|
+
throw new Error('downloaded firmware binary is empty or invalid');
|
|
502
|
+
}
|
|
503
|
+
preparedSource = source;
|
|
504
|
+
this.postTipMessage('DownloadFirmwareSuccess');
|
|
505
|
+
return source;
|
|
506
|
+
} catch (err) {
|
|
507
|
+
throw normalizeFirmwarePreparationError(err);
|
|
508
|
+
}
|
|
509
|
+
};
|
|
429
510
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (bootRes.type === 'CallMethodError') {
|
|
436
|
-
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure);
|
|
511
|
+
if (!device.isBootloader() && features) {
|
|
512
|
+
const serialNo = device.getCurrentSerialNo();
|
|
513
|
+
// should go to bootloader mode manually
|
|
514
|
+
if (this.isEnteredManuallyBoot()) {
|
|
515
|
+
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateManuallyEnterBoot);
|
|
437
516
|
}
|
|
438
|
-
this.postTipMessage('GoToBootloaderSuccess');
|
|
439
|
-
this.checkDeviceToBootloader(this.payload.connectId);
|
|
440
517
|
|
|
441
|
-
//
|
|
442
|
-
|
|
443
|
-
|
|
518
|
+
// All network-backed input must be ready before the first device mutation.
|
|
519
|
+
await acquireFirmwareSource();
|
|
520
|
+
|
|
521
|
+
// check & upgrade firmware resource
|
|
522
|
+
if (this.isSupportResourceUpdate(params.updateType)) {
|
|
523
|
+
this.postTipMessage('CheckLatestUiResource');
|
|
524
|
+
const resourceUrl = DataManager.getSysResourcesLatestRelease({
|
|
525
|
+
features,
|
|
526
|
+
forcedUpdateRes: params.forcedUpdateRes,
|
|
527
|
+
firmwareType,
|
|
528
|
+
});
|
|
529
|
+
if (resourceUrl) {
|
|
530
|
+
this.postTipMessage('DownloadLatestUiResource');
|
|
531
|
+
if (params.resourceEntries?.length) {
|
|
532
|
+
const sources: Array<{
|
|
533
|
+
entryName: string;
|
|
534
|
+
source: FirmwareByteSource;
|
|
535
|
+
}> = [];
|
|
536
|
+
try {
|
|
537
|
+
for (const entry of params.resourceEntries) {
|
|
538
|
+
const resourceName = getFirmwareUpdateResourceName(entry.entryName);
|
|
539
|
+
const source = await openFirmwareByteSource({
|
|
540
|
+
artifact: entry.artifact,
|
|
541
|
+
reader: params.artifactReader,
|
|
542
|
+
});
|
|
543
|
+
if (!source) {
|
|
544
|
+
throw new Error('Firmware resource entry is not prepared');
|
|
545
|
+
}
|
|
546
|
+
sources.push({ entryName: resourceName, source });
|
|
547
|
+
}
|
|
548
|
+
await updateResourcesFromSources(
|
|
549
|
+
this.device.getCommands().typedCall.bind(this.device.getCommands()),
|
|
550
|
+
this.postMessage,
|
|
551
|
+
device,
|
|
552
|
+
sources.map(entry => ({
|
|
553
|
+
entryName: entry.entryName,
|
|
554
|
+
source: entry.source,
|
|
555
|
+
}))
|
|
556
|
+
);
|
|
557
|
+
} finally {
|
|
558
|
+
await Promise.all(
|
|
559
|
+
sources.map(entry => entry.source.close().catch(() => undefined))
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
this.postTipMessage('DownloadLatestUiResourceSuccess');
|
|
563
|
+
} else {
|
|
564
|
+
let resourceBinary: ArrayBuffer | Buffer;
|
|
565
|
+
if (params.resourceArtifact) {
|
|
566
|
+
throw ERRORS.TypedError(
|
|
567
|
+
HardwareErrorCode.RuntimeError,
|
|
568
|
+
'Firmware resource archive must be materialized into prepared entries',
|
|
569
|
+
{
|
|
570
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
571
|
+
artifactName: 'resource',
|
|
572
|
+
}
|
|
573
|
+
);
|
|
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
|
+
resourceBinary = (await getSysResourceBinary(resourceUrl)).binary;
|
|
589
|
+
}
|
|
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
599
|
}
|
|
445
|
-
delete DevicePool.devicesCache[''];
|
|
446
|
-
await this.checkPromise?.promise;
|
|
447
|
-
this.checkPromise = null;
|
|
448
600
|
|
|
449
|
-
//
|
|
601
|
+
// The request may outlive the current transport command instance.
|
|
450
602
|
this.device?.commands?.checkDisposed();
|
|
451
603
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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
|
+
);
|
|
460
639
|
}
|
|
461
|
-
console.log('auto go to bootloader mode failed: ', e);
|
|
462
|
-
return Promise.reject(
|
|
463
|
-
ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateAutoEnterBootFailure)
|
|
464
|
-
);
|
|
465
640
|
}
|
|
466
|
-
}
|
|
467
641
|
|
|
468
|
-
|
|
469
|
-
|
|
642
|
+
// Devices already in bootloader mode still acquire through the same helper.
|
|
643
|
+
const source = await acquireFirmwareSource();
|
|
470
644
|
|
|
471
|
-
|
|
472
|
-
|
|
645
|
+
// check if the device commands has been disposed
|
|
646
|
+
this.device?.commands?.checkDisposed();
|
|
473
647
|
|
|
474
|
-
|
|
648
|
+
await this.device.acquire();
|
|
475
649
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
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
|
+
);
|
|
484
659
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
660
|
+
if (this.connectId) {
|
|
661
|
+
DevicePool.clearDeviceCache(this.connectId);
|
|
662
|
+
}
|
|
488
663
|
|
|
489
|
-
|
|
664
|
+
return response;
|
|
665
|
+
} finally {
|
|
666
|
+
await preparedSource?.close().catch(() => undefined);
|
|
667
|
+
}
|
|
490
668
|
}
|
|
491
669
|
}
|