@onekeyfe/hd-core 1.2.2-alpha.1 → 1.2.2-alpha.100
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 +4 -20
- package/__tests__/DeviceCommands.test.ts +0 -13
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +2 -0
- package/__tests__/check-firmware-release-protocol-v2.test.ts +2 -0
- package/__tests__/device-lifecycle-events.test.ts +0 -19
- package/__tests__/deviceUploadNft.test.ts +0 -68
- package/__tests__/evmSignTypedData.test.ts +0 -42
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +12 -825
- package/__tests__/open-wallet-session.test.ts +1 -127
- package/__tests__/protocol-v2-resources.test.ts +4 -7
- package/__tests__/protocol-v2-unlock-policy.test.ts +1 -35
- package/__tests__/protocol-v2.test.ts +27 -710
- package/dist/api/FirmwareUpdateV4.d.ts +0 -4
- package/dist/api/FirmwareUpdateV4.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/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -2
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +2 -2
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +1 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +0 -3
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +5 -21
- package/dist/index.js +402 -1136
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -2
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +0 -3
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/settings.d.ts +2 -2
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +0 -3
- 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/FirmwareUpdateV4.ts +75 -434
- package/src/api/OpenWalletSession.ts +9 -39
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +1 -2
- package/src/api/evm/EVMSignTypedData.ts +0 -1
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +3 -9
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +1 -7
- package/src/api/protocol-v2/DeviceUploadNft.ts +8 -31
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +8 -27
- package/src/api/protocol-v2/helpers.ts +0 -8
- package/src/core/index.ts +10 -121
- package/src/data/messages/messages-protocol-v2.json +1 -111
- package/src/device/Device.ts +1 -3
- package/src/device/DeviceConnector.ts +3 -7
- package/src/events/ui-request.ts +0 -3
- package/src/protocols/protocol-v2/resources.ts +1 -9
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +1 -8
- package/src/protocols/protocol-v2/walletSession.ts +22 -65
- package/src/types/settings.ts +2 -4
- package/src/utils/deviceFeaturesUtils.ts +0 -4
- package/__tests__/pro2HostAssetPackage.test.ts +0 -58
- package/dist/utils/pro2HostAssetPackage.d.ts +0 -8
- package/dist/utils/pro2HostAssetPackage.d.ts.map +0 -1
- package/src/utils/pro2HostAssetPackage.ts +0 -354
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EDeviceType,
|
|
3
|
-
ERRORS,
|
|
4
|
-
HardwareError,
|
|
5
|
-
HardwareErrorCode,
|
|
6
|
-
isBleStaleBondHardwareError,
|
|
7
|
-
wait,
|
|
8
|
-
} from '@onekeyfe/hd-shared';
|
|
1
|
+
import { EDeviceType, ERRORS, HardwareError, HardwareErrorCode, wait } from '@onekeyfe/hd-shared';
|
|
9
2
|
import JSZip from 'jszip';
|
|
10
3
|
import {
|
|
11
4
|
DeviceRebootType,
|
|
@@ -51,7 +44,6 @@ import {
|
|
|
51
44
|
getProtocolV2UnknownErrorText,
|
|
52
45
|
isProtocolV2DeviceDisconnectedError,
|
|
53
46
|
} from './protocol-v2/helpers';
|
|
54
|
-
import { isProtocolV2ResponseTimeout } from './helpers/protocolV2FileWrite';
|
|
55
47
|
import {
|
|
56
48
|
openFirmwareByteSource,
|
|
57
49
|
readFirmwareByteSourceFully,
|
|
@@ -63,7 +55,6 @@ import {
|
|
|
63
55
|
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
64
56
|
validateFirmwareUpdatePreparedPlan,
|
|
65
57
|
} from './firmware/FirmwareUpdatePreparedPlan';
|
|
66
|
-
|
|
67
58
|
import type {
|
|
68
59
|
FirmwareArtifactReference,
|
|
69
60
|
FirmwareUpdateV4Params,
|
|
@@ -93,7 +84,6 @@ const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
|
|
|
93
84
|
const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
|
|
94
85
|
const PROTOCOL_V2_INSTALL_TIMEOUT = 5 * 60 * 1000;
|
|
95
86
|
const PROTOCOL_V2_INSTALL_STATUS_INITIAL_DELAY = 1000;
|
|
96
|
-
const PROTOCOL_V2_INSTALL_FINISHED_AFTER_DISCONNECT_POLLS = 4;
|
|
97
87
|
const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
|
|
98
88
|
const PROTOCOL_V2_TARGET_STATUS_IN_PROGRESS = 1;
|
|
99
89
|
const PROTOCOL_V2_TARGET_STATUS_FINISHED = 2;
|
|
@@ -192,11 +182,6 @@ const getProtocolV2DeviceTransferProgress = (
|
|
|
192
182
|
type ProtocolV2FirmwareUpdateStatusTarget = {
|
|
193
183
|
target_id: number | string;
|
|
194
184
|
status?: number | string;
|
|
195
|
-
progress_percent?: number;
|
|
196
|
-
phase_info?: {
|
|
197
|
-
phase: number | string;
|
|
198
|
-
progress_percent: number;
|
|
199
|
-
};
|
|
200
185
|
payload_version?: number;
|
|
201
186
|
path?: string;
|
|
202
187
|
};
|
|
@@ -374,22 +359,12 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
|
|
|
374
359
|
);
|
|
375
360
|
};
|
|
376
361
|
|
|
377
|
-
const isProtocolV2InstallResponseTimeout = (error: unknown) => {
|
|
378
|
-
if (!error || typeof error !== 'object') return false;
|
|
379
|
-
const { code } = error as { code?: number | string };
|
|
380
|
-
return (
|
|
381
|
-
code === 'response-timeout' ||
|
|
382
|
-
/\bresponse timeout\b/i.test(getProtocolV2UnknownErrorText(error))
|
|
383
|
-
);
|
|
384
|
-
};
|
|
385
|
-
|
|
386
362
|
const isProtocolV2TerminalInstallStatusError = (error: unknown) =>
|
|
387
|
-
|
|
388
|
-
(error
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
error.params?.firmwareUpdateCode === PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE));
|
|
363
|
+
error instanceof HardwareError &&
|
|
364
|
+
(error.errorCode === HardwareErrorCode.ActionCancelled ||
|
|
365
|
+
error.errorCode === HardwareErrorCode.FirmwareError ||
|
|
366
|
+
error.errorCode === HardwareErrorCode.FirmwareVerificationFailed ||
|
|
367
|
+
error.params?.firmwareUpdateCode === PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE);
|
|
393
368
|
|
|
394
369
|
const isProtocolV2TargetStatusFinished = (status: ProtocolV2FirmwareUpdateStatusTarget['status']) =>
|
|
395
370
|
normalizeProtocolV2TargetStatus(status) === PROTOCOL_V2_TARGET_STATUS_FINISHED;
|
|
@@ -426,18 +401,6 @@ const normalizeProtocolV2TargetStatus = (
|
|
|
426
401
|
return undefined;
|
|
427
402
|
};
|
|
428
403
|
|
|
429
|
-
const PROTOCOL_V2_INSTALL_PHASE_BY_DECODED_VALUE = new Map<
|
|
430
|
-
number | string,
|
|
431
|
-
'prepare' | 'install' | 'verify'
|
|
432
|
-
>([
|
|
433
|
-
[0, 'prepare'],
|
|
434
|
-
[1, 'install'],
|
|
435
|
-
[2, 'verify'],
|
|
436
|
-
['FW_MGMT_UPDATER_PHASE_PREPARE', 'prepare'],
|
|
437
|
-
['FW_MGMT_UPDATER_PHASE_INSTALL', 'install'],
|
|
438
|
-
['FW_MGMT_UPDATER_PHASE_VERIFY', 'verify'],
|
|
439
|
-
]);
|
|
440
|
-
|
|
441
404
|
const normalizeProtocolV2Hex = (value?: string) => value?.replace(/^0x/i, '').toLowerCase();
|
|
442
405
|
|
|
443
406
|
const versionArrayToNumber = (version?: IVersionArray) => {
|
|
@@ -495,11 +458,6 @@ const toProtocolV2FiniteNumber = (value: unknown) => {
|
|
|
495
458
|
return undefined;
|
|
496
459
|
};
|
|
497
460
|
|
|
498
|
-
const normalizeProtocolV2ProgressPercent = (value: unknown) => {
|
|
499
|
-
const progress = toProtocolV2FiniteNumber(value);
|
|
500
|
-
return progress === undefined ? undefined : Math.min(100, Math.max(0, progress));
|
|
501
|
-
};
|
|
502
|
-
|
|
503
461
|
export const isProtocolV2FirmwareFingerprintValid = (
|
|
504
462
|
binary: ArrayBuffer | Uint8Array,
|
|
505
463
|
fingerprint: string | undefined
|
|
@@ -572,12 +530,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
572
530
|
|
|
573
531
|
private protocolV2InstallBaselineVersions = new Map<number, string>();
|
|
574
532
|
|
|
575
|
-
private protocolV2InstallNeedsReconnect = false;
|
|
576
|
-
|
|
577
|
-
private protocolV2InstallDisconnectObserved = false;
|
|
578
|
-
|
|
579
|
-
private protocolV2InstallTerminalSuccessObserved = false;
|
|
580
|
-
|
|
581
533
|
private protocolV2LastRuntimeProbeFeatures?: Features;
|
|
582
534
|
|
|
583
535
|
private protocolV2LastTransferProgress?: number;
|
|
@@ -1856,9 +1808,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1856
1808
|
if (!expectedHeaderHash || header.headerHash !== expectedHeaderHash) return false;
|
|
1857
1809
|
return true;
|
|
1858
1810
|
} catch (error) {
|
|
1859
|
-
if (isBleStaleBondHardwareError(error)) {
|
|
1860
|
-
throw error;
|
|
1861
|
-
}
|
|
1862
1811
|
Log.log(`[FirmwareUpdateV4] RESC bundle ${bundle.name} header check failed: `, error);
|
|
1863
1812
|
return false;
|
|
1864
1813
|
}
|
|
@@ -1952,7 +1901,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1952
1901
|
}
|
|
1953
1902
|
lastError = new Error('Protocol V2 device is reachable but is not in bootloader mode');
|
|
1954
1903
|
} catch (error) {
|
|
1955
|
-
if (
|
|
1904
|
+
if (this.isProtocolV2ReconnectIdentityError(error)) {
|
|
1956
1905
|
throw error;
|
|
1957
1906
|
}
|
|
1958
1907
|
shouldReconnect = true;
|
|
@@ -2234,9 +2183,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2234
2183
|
});
|
|
2235
2184
|
return processedSize + source.size;
|
|
2236
2185
|
} catch (error) {
|
|
2237
|
-
if (isBleStaleBondHardwareError(error)) {
|
|
2238
|
-
throw error;
|
|
2239
|
-
}
|
|
2240
2186
|
lastError = error;
|
|
2241
2187
|
if (attempt < PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT) {
|
|
2242
2188
|
await this.recoverProtocolV2FileTransfer();
|
|
@@ -2266,41 +2212,19 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2266
2212
|
}
|
|
2267
2213
|
}
|
|
2268
2214
|
|
|
2269
|
-
private collectProtocolV2LiveTargetIds(
|
|
2270
|
-
statusTargets: ProtocolV2FirmwareUpdateStatusTarget[],
|
|
2271
|
-
expectedTargetIds: Set<number>,
|
|
2272
|
-
liveTargetIds: Set<number>
|
|
2273
|
-
) {
|
|
2274
|
-
statusTargets.forEach(target => {
|
|
2275
|
-
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2276
|
-
if (
|
|
2277
|
-
targetId !== undefined &&
|
|
2278
|
-
expectedTargetIds.has(targetId) &&
|
|
2279
|
-
isProtocolV2TargetStatusInProgress(target.status)
|
|
2280
|
-
) {
|
|
2281
|
-
liveTargetIds.add(targetId);
|
|
2282
|
-
}
|
|
2283
|
-
});
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
2215
|
private assertProtocolV2TargetStatus(
|
|
2287
2216
|
statusTargets: ProtocolV2FirmwareUpdateStatusTarget[],
|
|
2288
2217
|
expectedTargetIds: Set<number>,
|
|
2289
|
-
expectedPaths
|
|
2290
|
-
liveTargetIds?: Set<number>
|
|
2218
|
+
expectedPaths = new Map<number, string>()
|
|
2291
2219
|
) {
|
|
2292
|
-
const resolvedExpectedPaths = expectedPaths ?? new Map<number, string>();
|
|
2293
2220
|
Log.log(
|
|
2294
2221
|
`[FirmwareUpdateV4] DeviceFirmwareUpdateStatus records=${JSON.stringify(statusTargets)}`
|
|
2295
2222
|
);
|
|
2296
|
-
const failedTarget = statusTargets.find(
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
(!liveTargetIds || liveTargetIds.has(targetId))
|
|
2302
|
-
);
|
|
2303
|
-
});
|
|
2223
|
+
const failedTarget = statusTargets.find(
|
|
2224
|
+
target =>
|
|
2225
|
+
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1) &&
|
|
2226
|
+
isProtocolV2TargetStatusFailed(target.status)
|
|
2227
|
+
);
|
|
2304
2228
|
if (failedTarget) {
|
|
2305
2229
|
const failedTargetDetails = JSON.stringify({
|
|
2306
2230
|
targetId: failedTarget.target_id,
|
|
@@ -2317,27 +2241,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2317
2241
|
}
|
|
2318
2242
|
);
|
|
2319
2243
|
}
|
|
2320
|
-
if (liveTargetIds) {
|
|
2321
|
-
const staleFailedTargets = statusTargets.filter(target => {
|
|
2322
|
-
const targetId = normalizeProtocolV2TargetId(target.target_id) ?? -1;
|
|
2323
|
-
return (
|
|
2324
|
-
expectedTargetIds.has(targetId) &&
|
|
2325
|
-
isProtocolV2TargetStatusFailed(target.status) &&
|
|
2326
|
-
!liveTargetIds.has(targetId)
|
|
2327
|
-
);
|
|
2328
|
-
});
|
|
2329
|
-
if (staleFailedTargets.length > 0) {
|
|
2330
|
-
Log.log(
|
|
2331
|
-
`[FirmwareUpdateV4] ignoring stale failed firmware status until those targets start: ${JSON.stringify(
|
|
2332
|
-
staleFailedTargets.map(target => ({
|
|
2333
|
-
targetId: target.target_id,
|
|
2334
|
-
status: target.status,
|
|
2335
|
-
path: target.path,
|
|
2336
|
-
}))
|
|
2337
|
-
)}`
|
|
2338
|
-
);
|
|
2339
|
-
}
|
|
2340
|
-
}
|
|
2341
2244
|
|
|
2342
2245
|
const matchingTargets = statusTargets.filter(target =>
|
|
2343
2246
|
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1)
|
|
@@ -2345,16 +2248,10 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2345
2248
|
const seenTargetIds = new Set<number>();
|
|
2346
2249
|
for (const target of matchingTargets) {
|
|
2347
2250
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2348
|
-
const pathConflictsWithCurrentInstall =
|
|
2349
|
-
targetId !== undefined &&
|
|
2350
|
-
Boolean(target.path) &&
|
|
2351
|
-
Boolean(resolvedExpectedPaths.get(targetId)) &&
|
|
2352
|
-
target.path !== resolvedExpectedPaths.get(targetId) &&
|
|
2353
|
-
(!liveTargetIds || liveTargetIds.has(targetId));
|
|
2354
2251
|
if (
|
|
2355
2252
|
targetId === undefined ||
|
|
2356
2253
|
seenTargetIds.has(targetId) ||
|
|
2357
|
-
|
|
2254
|
+
(target.path && expectedPaths.get(targetId) && target.path !== expectedPaths.get(targetId))
|
|
2358
2255
|
) {
|
|
2359
2256
|
Log.error(`[FirmwareUpdateV4] install status conflicts with target=${target.target_id}`);
|
|
2360
2257
|
throw ERRORS.TypedError(
|
|
@@ -2367,13 +2264,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2367
2264
|
}
|
|
2368
2265
|
seenTargetIds.add(targetId);
|
|
2369
2266
|
}
|
|
2370
|
-
const completedTargets = matchingTargets.filter(target =>
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
isProtocolV2TargetStatusFinished(target.status) &&
|
|
2374
|
-
(!liveTargetIds || (targetId !== undefined && liveTargetIds.has(targetId)))
|
|
2375
|
-
);
|
|
2376
|
-
});
|
|
2267
|
+
const completedTargets = matchingTargets.filter(target =>
|
|
2268
|
+
isProtocolV2TargetStatusFinished(target.status)
|
|
2269
|
+
);
|
|
2377
2270
|
const completedTargetIds = new Set<number>();
|
|
2378
2271
|
completedTargets.forEach(target => {
|
|
2379
2272
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
@@ -2410,54 +2303,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2410
2303
|
}
|
|
2411
2304
|
|
|
2412
2305
|
if (expectedTargetIds.size > 0 && matchingTargets.length > 0) {
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
installTargetId: number;
|
|
2417
|
-
installPhase: 'prepare' | 'install' | 'verify';
|
|
2418
|
-
installPhaseProgress: number;
|
|
2419
|
-
}
|
|
2420
|
-
| undefined;
|
|
2421
|
-
let hasInProgressTarget = false;
|
|
2422
|
-
matchingTargets.forEach(target => {
|
|
2423
|
-
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2424
|
-
if (
|
|
2425
|
-
targetId === undefined ||
|
|
2426
|
-
completedTargetIds.has(targetId) ||
|
|
2427
|
-
!isProtocolV2TargetStatusInProgress(target.status) ||
|
|
2428
|
-
(liveTargetIds && !liveTargetIds.has(targetId))
|
|
2429
|
-
) {
|
|
2430
|
-
return;
|
|
2431
|
-
}
|
|
2432
|
-
hasInProgressTarget = true;
|
|
2433
|
-
detailedProgress += normalizeProtocolV2ProgressPercent(target.progress_percent) ?? 0;
|
|
2434
|
-
const installPhase = target.phase_info
|
|
2435
|
-
? PROTOCOL_V2_INSTALL_PHASE_BY_DECODED_VALUE.get(target.phase_info.phase)
|
|
2436
|
-
: undefined;
|
|
2437
|
-
const installPhaseProgress = normalizeProtocolV2ProgressPercent(
|
|
2438
|
-
target.phase_info?.progress_percent
|
|
2439
|
-
);
|
|
2440
|
-
if (installPhase && installPhaseProgress !== undefined && !installProgressMetadata) {
|
|
2441
|
-
installProgressMetadata = {
|
|
2442
|
-
installTargetId: targetId,
|
|
2443
|
-
installPhase,
|
|
2444
|
-
installPhaseProgress,
|
|
2445
|
-
};
|
|
2446
|
-
}
|
|
2447
|
-
});
|
|
2306
|
+
const hasInProgressTarget = matchingTargets.some(target =>
|
|
2307
|
+
isProtocolV2TargetStatusInProgress(target.status)
|
|
2308
|
+
);
|
|
2448
2309
|
const completedProgress = Math.floor(
|
|
2449
2310
|
(completedTargetIds.size / expectedTargetIds.size) * 100
|
|
2450
2311
|
);
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
);
|
|
2456
|
-
if (installProgressMetadata) {
|
|
2457
|
-
this.postProgressMessage(progress, 'installingFirmware', installProgressMetadata);
|
|
2458
|
-
} else {
|
|
2459
|
-
this.postProgressMessage(progress, 'installingFirmware');
|
|
2460
|
-
}
|
|
2312
|
+
// The protocol exposes no per-target percentage, so report coarse progress by
|
|
2313
|
+
// completed targets and use 1% once work starts to keep the UI responsive.
|
|
2314
|
+
const progress = Math.min(99, Math.max(completedProgress, hasInProgressTarget ? 1 : 0));
|
|
2315
|
+
this.postProgressMessage(progress, 'installingFirmware');
|
|
2461
2316
|
}
|
|
2462
2317
|
|
|
2463
2318
|
return false;
|
|
@@ -2528,37 +2383,14 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2528
2383
|
) {
|
|
2529
2384
|
const expectedTargetIds = new Set(targets.map(target => target.target_id));
|
|
2530
2385
|
const expectedPaths = new Map(targets.map(target => [target.target_id, target.path]));
|
|
2531
|
-
const isBleInstall = this.isBleReconnect();
|
|
2532
2386
|
const startTime = Date.now();
|
|
2533
2387
|
let lastError: unknown;
|
|
2534
|
-
//
|
|
2535
|
-
//
|
|
2536
|
-
let shouldReconnect =
|
|
2537
|
-
this.protocolV2InstallNeedsReconnect = false;
|
|
2388
|
+
// DeviceFirmwareUpdateRequest leaves the current loader link usable for status polling.
|
|
2389
|
+
// Reconnecting here probes DeviceInfo, which loaders reject while installation is active.
|
|
2390
|
+
let shouldReconnect = false;
|
|
2538
2391
|
let deviceInfo: ProtocolV2DeviceInfo | undefined;
|
|
2539
|
-
let
|
|
2540
|
-
let installStatusDisconnectObserved = isBleInstall && this.protocolV2InstallDisconnectObserved;
|
|
2541
|
-
this.protocolV2InstallDisconnectObserved = false;
|
|
2542
|
-
let installReconnectObserved = false;
|
|
2543
|
-
let finishedStatusSnapshotKey: string | undefined;
|
|
2544
|
-
let finishedStatusSnapshotPolls = 0;
|
|
2545
|
-
let fastFinishedInstallProgressReported = false;
|
|
2546
|
-
let installEvidenceObserved = this.protocolV2InstallTerminalSuccessObserved;
|
|
2392
|
+
let installEvidenceObserved = false;
|
|
2547
2393
|
let currentInstallStatusObserved = false;
|
|
2548
|
-
const liveTargetIds = new Set<number>();
|
|
2549
|
-
const recordBleInstallDisconnect = (error: unknown) => {
|
|
2550
|
-
if (
|
|
2551
|
-
!isBleInstall ||
|
|
2552
|
-
!isProtocolV2DeviceDisconnectedError(error) ||
|
|
2553
|
-
isProtocolV2InstallResponseTimeout(error)
|
|
2554
|
-
) {
|
|
2555
|
-
return;
|
|
2556
|
-
}
|
|
2557
|
-
installStatusDisconnectObserved = true;
|
|
2558
|
-
installReconnectObserved = false;
|
|
2559
|
-
finishedStatusSnapshotKey = undefined;
|
|
2560
|
-
finishedStatusSnapshotPolls = 0;
|
|
2561
|
-
};
|
|
2562
2394
|
|
|
2563
2395
|
while (Date.now() - startTime < PROTOCOL_V2_INSTALL_TIMEOUT) {
|
|
2564
2396
|
// A transport release caused by an explicit workflow cancellation must not
|
|
@@ -2566,40 +2398,43 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2566
2398
|
this.throwIfAborted();
|
|
2567
2399
|
try {
|
|
2568
2400
|
if (shouldReconnect) {
|
|
2569
|
-
|
|
2570
|
-
await this.
|
|
2571
|
-
bleInstallLinkReady = isBleInstallReconnect;
|
|
2572
|
-
deviceInfo = isBleInstallReconnect
|
|
2573
|
-
? undefined
|
|
2574
|
-
: await this.verifyProtocolV2ReconnectIdentity();
|
|
2575
|
-
if (isBleInstallReconnect && installStatusDisconnectObserved) {
|
|
2576
|
-
installReconnectObserved = true;
|
|
2577
|
-
}
|
|
2401
|
+
await this.reconnectProtocolV2Device();
|
|
2402
|
+
deviceInfo = await this.verifyProtocolV2ReconnectIdentity();
|
|
2578
2403
|
shouldReconnect = false;
|
|
2579
2404
|
}
|
|
2580
|
-
|
|
2405
|
+
const currentDeviceInfo = deviceInfo;
|
|
2581
2406
|
try {
|
|
2582
2407
|
const statusResponse = await this.device.getCommands().typedCall(
|
|
2583
2408
|
'DeviceFirmwareUpdateStatusGet',
|
|
2584
|
-
'DeviceFirmwareUpdateStatus',
|
|
2409
|
+
['DeviceFirmwareUpdateStatus', 'Success'],
|
|
2585
2410
|
{
|
|
2586
2411
|
fields: {
|
|
2587
2412
|
status: true,
|
|
2588
|
-
progress_percent: true,
|
|
2589
|
-
phase_info: true,
|
|
2590
2413
|
payload_version: true,
|
|
2591
2414
|
path: true,
|
|
2592
2415
|
},
|
|
2593
2416
|
},
|
|
2594
2417
|
{ timeoutMs: PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT }
|
|
2595
2418
|
);
|
|
2596
|
-
if (
|
|
2419
|
+
if (statusResponse.type === 'Success') {
|
|
2597
2420
|
installEvidenceObserved = true;
|
|
2421
|
+
lastError = new Error(
|
|
2422
|
+
'Protocol V2 firmware install acknowledged; waiting for target status'
|
|
2423
|
+
);
|
|
2598
2424
|
}
|
|
2599
|
-
const statusTargets =
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2425
|
+
const statusTargets =
|
|
2426
|
+
statusResponse.type === 'DeviceFirmwareUpdateStatus'
|
|
2427
|
+
? ((statusResponse.message.records ?? []) as ProtocolV2FirmwareUpdateStatusTarget[])
|
|
2428
|
+
: [];
|
|
2429
|
+
const hasInProgressTarget = statusTargets.some(target => {
|
|
2430
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2431
|
+
return (
|
|
2432
|
+
targetId !== undefined &&
|
|
2433
|
+
expectedTargetIds.has(targetId) &&
|
|
2434
|
+
isProtocolV2TargetStatusInProgress(target.status)
|
|
2435
|
+
);
|
|
2436
|
+
});
|
|
2437
|
+
if (hasInProgressTarget) {
|
|
2603
2438
|
currentInstallStatusObserved = true;
|
|
2604
2439
|
}
|
|
2605
2440
|
const hasMatchingTargetStatus = statusTargets.some(target => {
|
|
@@ -2616,101 +2451,18 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2616
2451
|
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2617
2452
|
return targetId !== undefined && expectedTargetIds.has(targetId);
|
|
2618
2453
|
});
|
|
2619
|
-
const matchingFinishedTargetIds = new Set<number>();
|
|
2620
|
-
const matchingFinishedStatus = matchingStatusTargets
|
|
2621
|
-
.map(target => {
|
|
2622
|
-
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
2623
|
-
const expectedPath = targetId === undefined ? undefined : expectedPaths.get(targetId);
|
|
2624
|
-
const expectedVersion =
|
|
2625
|
-
targetId === undefined
|
|
2626
|
-
? undefined
|
|
2627
|
-
: this.getExpectedProtocolV2TargetVersion(targetId);
|
|
2628
|
-
const payloadVersion = toProtocolV2FiniteNumber(target.payload_version);
|
|
2629
|
-
if (
|
|
2630
|
-
targetId === undefined ||
|
|
2631
|
-
matchingFinishedTargetIds.has(targetId) ||
|
|
2632
|
-
!isProtocolV2TargetStatusFinished(target.status) ||
|
|
2633
|
-
(Boolean(target.path) && Boolean(expectedPath) && target.path !== expectedPath) ||
|
|
2634
|
-
(expectedVersion !== undefined &&
|
|
2635
|
-
payloadVersion !== undefined &&
|
|
2636
|
-
payloadVersion !== expectedVersion)
|
|
2637
|
-
) {
|
|
2638
|
-
return undefined;
|
|
2639
|
-
}
|
|
2640
|
-
matchingFinishedTargetIds.add(targetId);
|
|
2641
|
-
return [targetId, target.path ?? null, payloadVersion ?? null] as const;
|
|
2642
|
-
})
|
|
2643
|
-
.filter((target): target is readonly [number, string | null, number | null] => !!target)
|
|
2644
|
-
.sort(([leftTargetId], [rightTargetId]) => leftTargetId - rightTargetId);
|
|
2645
|
-
const hasCompleteMatchingFinishedStatus =
|
|
2646
|
-
matchingFinishedStatus.length === expectedTargetIds.size &&
|
|
2647
|
-
matchingFinishedTargetIds.size === expectedTargetIds.size &&
|
|
2648
|
-
expectedTargetIds.size > 0;
|
|
2649
|
-
if (
|
|
2650
|
-
requireCurrentInstallStatus &&
|
|
2651
|
-
installReconnectObserved &&
|
|
2652
|
-
hasCompleteMatchingFinishedStatus
|
|
2653
|
-
) {
|
|
2654
|
-
const nextSnapshotKey = JSON.stringify(matchingFinishedStatus);
|
|
2655
|
-
if (nextSnapshotKey === finishedStatusSnapshotKey) {
|
|
2656
|
-
finishedStatusSnapshotPolls += 1;
|
|
2657
|
-
} else {
|
|
2658
|
-
finishedStatusSnapshotKey = nextSnapshotKey;
|
|
2659
|
-
finishedStatusSnapshotPolls = 1;
|
|
2660
|
-
}
|
|
2661
|
-
} else {
|
|
2662
|
-
finishedStatusSnapshotKey = undefined;
|
|
2663
|
-
finishedStatusSnapshotPolls = 0;
|
|
2664
|
-
}
|
|
2665
|
-
if (
|
|
2666
|
-
requireCurrentInstallStatus &&
|
|
2667
|
-
installReconnectObserved &&
|
|
2668
|
-
hasCompleteMatchingFinishedStatus &&
|
|
2669
|
-
!currentInstallStatusObserved &&
|
|
2670
|
-
!this.protocolV2InstallTerminalSuccessObserved &&
|
|
2671
|
-
!fastFinishedInstallProgressReported
|
|
2672
|
-
) {
|
|
2673
|
-
// A fast BLE install may finish while disconnected, so IN_PROGRESS can be hidden.
|
|
2674
|
-
// A status response timeout alone is not evidence that the install was accepted.
|
|
2675
|
-
this.postProgressMessage(1, 'installingFirmware');
|
|
2676
|
-
fastFinishedInstallProgressReported = true;
|
|
2677
|
-
}
|
|
2678
|
-
const finishedAfterDisconnectObserved =
|
|
2679
|
-
finishedStatusSnapshotPolls >= PROTOCOL_V2_INSTALL_FINISHED_AFTER_DISCONNECT_POLLS;
|
|
2680
|
-
const hasCurrentInstallEvidence =
|
|
2681
|
-
currentInstallStatusObserved ||
|
|
2682
|
-
this.protocolV2InstallTerminalSuccessObserved ||
|
|
2683
|
-
finishedAfterDisconnectObserved;
|
|
2684
|
-
if (hasCurrentInstallEvidence) {
|
|
2685
|
-
installEvidenceObserved = true;
|
|
2686
|
-
}
|
|
2687
2454
|
const shouldVerifyTargetCompletion =
|
|
2688
|
-
!requireCurrentInstallStatus ||
|
|
2455
|
+
!requireCurrentInstallStatus || currentInstallStatusObserved;
|
|
2689
2456
|
if (
|
|
2690
2457
|
shouldVerifyTargetCompletion &&
|
|
2691
|
-
this.assertProtocolV2TargetStatus(
|
|
2692
|
-
statusTargets,
|
|
2693
|
-
expectedTargetIds,
|
|
2694
|
-
expectedPaths,
|
|
2695
|
-
requireCurrentInstallStatus &&
|
|
2696
|
-
!this.protocolV2InstallTerminalSuccessObserved &&
|
|
2697
|
-
!finishedAfterDisconnectObserved
|
|
2698
|
-
? liveTargetIds
|
|
2699
|
-
: undefined
|
|
2700
|
-
)
|
|
2458
|
+
this.assertProtocolV2TargetStatus(statusTargets, expectedTargetIds, expectedPaths)
|
|
2701
2459
|
) {
|
|
2702
2460
|
return;
|
|
2703
2461
|
}
|
|
2704
2462
|
|
|
2705
|
-
if (!hasCurrentInstallEvidence) {
|
|
2706
|
-
// A successful status poll clears DeviceCommands' cancel action. Keep cancellation
|
|
2707
|
-
// available while UpdateRequest is still waiting for confirmation on the device.
|
|
2708
|
-
this.device.setCancelableAction(() => this.device.getCommands().cancelDevice());
|
|
2709
|
-
}
|
|
2710
|
-
|
|
2711
2463
|
if (
|
|
2712
2464
|
requireCurrentInstallStatus &&
|
|
2713
|
-
!
|
|
2465
|
+
!currentInstallStatusObserved &&
|
|
2714
2466
|
matchingStatusTargets.length > 0
|
|
2715
2467
|
) {
|
|
2716
2468
|
lastError = new Error(
|
|
@@ -2718,18 +2470,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2718
2470
|
);
|
|
2719
2471
|
}
|
|
2720
2472
|
|
|
2721
|
-
if (
|
|
2722
|
-
statusTargets.length === 0 &&
|
|
2723
|
-
!currentDeviceInfo &&
|
|
2724
|
-
bleInstallLinkReady &&
|
|
2725
|
-
installEvidenceObserved
|
|
2726
|
-
) {
|
|
2727
|
-
// BLE install reconnect skips generic probes because loaders may not answer Ping.
|
|
2728
|
-
// Restore the verified identity only after current-install evidence disappears.
|
|
2729
|
-
currentDeviceInfo = await this.verifyProtocolV2ReconnectIdentity();
|
|
2730
|
-
deviceInfo = currentDeviceInfo;
|
|
2731
|
-
}
|
|
2732
|
-
|
|
2733
2473
|
if (statusTargets.length === 0 && currentDeviceInfo) {
|
|
2734
2474
|
const isNormalMode = await this.probeProtocolV2NormalMode(currentDeviceInfo);
|
|
2735
2475
|
if (
|
|
@@ -2747,9 +2487,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2747
2487
|
}
|
|
2748
2488
|
|
|
2749
2489
|
if (statusTargets.length === 0) {
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2490
|
+
if (statusResponse.type !== 'Success') {
|
|
2491
|
+
lastError = new Error(
|
|
2492
|
+
'Protocol V2 firmware update is waiting for user confirmation or target status'
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2753
2495
|
} else {
|
|
2754
2496
|
const missingTargetIds = this.getProtocolV2MissingTargetIds(
|
|
2755
2497
|
statusTargets,
|
|
@@ -2772,22 +2514,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2772
2514
|
// missing endpoint as completion only after the runtime probe confirms App mode.
|
|
2773
2515
|
if (isProtocolV2FirmwareStatusEndpointUnavailable(error)) {
|
|
2774
2516
|
if (!currentDeviceInfo) {
|
|
2775
|
-
if (!bleInstallLinkReady) {
|
|
2776
|
-
throw ERRORS.TypedError(
|
|
2777
|
-
HardwareErrorCode.RuntimeError,
|
|
2778
|
-
'Protocol V2 device identity is unavailable during install polling'
|
|
2779
|
-
);
|
|
2780
|
-
}
|
|
2781
|
-
deviceInfo = await this.verifyProtocolV2ReconnectIdentity();
|
|
2782
|
-
}
|
|
2783
|
-
const reconnectDeviceInfo = currentDeviceInfo ?? deviceInfo;
|
|
2784
|
-
if (!reconnectDeviceInfo) {
|
|
2785
2517
|
throw ERRORS.TypedError(
|
|
2786
2518
|
HardwareErrorCode.RuntimeError,
|
|
2787
2519
|
'Protocol V2 device identity is unavailable during install polling'
|
|
2788
2520
|
);
|
|
2789
2521
|
}
|
|
2790
|
-
const isNormalMode = await this.probeProtocolV2NormalMode(
|
|
2522
|
+
const isNormalMode = await this.probeProtocolV2NormalMode(currentDeviceInfo);
|
|
2791
2523
|
if (
|
|
2792
2524
|
isNormalMode &&
|
|
2793
2525
|
(installEvidenceObserved ||
|
|
@@ -2810,10 +2542,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2810
2542
|
);
|
|
2811
2543
|
}
|
|
2812
2544
|
} else {
|
|
2813
|
-
recordBleInstallDisconnect(error);
|
|
2814
2545
|
shouldReconnect = true;
|
|
2815
2546
|
deviceInfo = undefined;
|
|
2816
|
-
bleInstallLinkReady = false;
|
|
2817
2547
|
lastError = error;
|
|
2818
2548
|
Log.log(
|
|
2819
2549
|
'[FirmwareUpdateV4] DeviceFirmwareUpdateStatusGet unavailable during install: ',
|
|
@@ -2835,10 +2565,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2835
2565
|
) {
|
|
2836
2566
|
throw error;
|
|
2837
2567
|
}
|
|
2838
|
-
recordBleInstallDisconnect(error);
|
|
2839
2568
|
shouldReconnect = true;
|
|
2840
2569
|
deviceInfo = undefined;
|
|
2841
|
-
bleInstallLinkReady = false;
|
|
2842
2570
|
Log.log('Protocol V2 firmware install device readiness probe failed: ', error);
|
|
2843
2571
|
}
|
|
2844
2572
|
await wait(1000);
|
|
@@ -2867,9 +2595,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2867
2595
|
return;
|
|
2868
2596
|
}
|
|
2869
2597
|
} catch (error) {
|
|
2870
|
-
if (isBleStaleBondHardwareError(error)) {
|
|
2871
|
-
throw error;
|
|
2872
|
-
}
|
|
2873
2598
|
Log.log('[FirmwareUpdateV4] unable to confirm App mode before Normal reboot: ', error);
|
|
2874
2599
|
}
|
|
2875
2600
|
await this.protocolV2Reboot(DeviceRebootType.Normal);
|
|
@@ -2961,7 +2686,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2961
2686
|
'Protocol V2 device is still in bootloader mode'
|
|
2962
2687
|
);
|
|
2963
2688
|
} catch (error) {
|
|
2964
|
-
if (
|
|
2689
|
+
if (this.isProtocolV2ReconnectIdentityError(error)) {
|
|
2965
2690
|
throw error;
|
|
2966
2691
|
}
|
|
2967
2692
|
shouldReconnect = true;
|
|
@@ -2979,53 +2704,19 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2979
2704
|
);
|
|
2980
2705
|
}
|
|
2981
2706
|
|
|
2982
|
-
private async reconnectProtocolV2Device(
|
|
2707
|
+
private async reconnectProtocolV2Device() {
|
|
2983
2708
|
if (this.isBleReconnect()) {
|
|
2984
|
-
await this.acquireProtocolV2BleDevice(
|
|
2709
|
+
await this.acquireProtocolV2BleDevice();
|
|
2985
2710
|
return;
|
|
2986
2711
|
}
|
|
2987
2712
|
|
|
2988
2713
|
const deviceDiff = await this.device.deviceConnector?.enumerate();
|
|
2989
2714
|
const devicesDescriptor = deviceDiff?.descriptors ?? [];
|
|
2990
|
-
const env = DataManager.getSettings('env');
|
|
2991
|
-
const isWebUsb = DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env);
|
|
2992
|
-
|
|
2993
|
-
if (isWebUsb && options?.skipProtocolProbe) {
|
|
2994
|
-
const expectedSerialNumber = this.protocolV2ExpectedSerialNumber?.trim();
|
|
2995
|
-
const expectedPath = this.protocolV2ExpectedPath?.trim();
|
|
2996
|
-
const reconnectDescriptor = devicesDescriptor.find(descriptor => {
|
|
2997
|
-
const descriptorPath = descriptor.path?.trim();
|
|
2998
|
-
return (
|
|
2999
|
-
(!!expectedSerialNumber && descriptorPath === expectedSerialNumber) ||
|
|
3000
|
-
(!!expectedPath && descriptorPath === expectedPath)
|
|
3001
|
-
);
|
|
3002
|
-
});
|
|
3003
|
-
if (!reconnectDescriptor?.path) {
|
|
3004
|
-
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
|
|
3005
|
-
}
|
|
3006
|
-
this.device.updateDescriptor(
|
|
3007
|
-
{
|
|
3008
|
-
...reconnectDescriptor,
|
|
3009
|
-
protocolType: PROTOCOL_V2_CONNECT_PROTOCOL,
|
|
3010
|
-
},
|
|
3011
|
-
true
|
|
3012
|
-
);
|
|
3013
|
-
const mainId = await this.device.deviceConnector?.acquire(
|
|
3014
|
-
reconnectDescriptor.path,
|
|
3015
|
-
null,
|
|
3016
|
-
undefined,
|
|
3017
|
-
PROTOCOL_V2_CONNECT_PROTOCOL,
|
|
3018
|
-
undefined,
|
|
3019
|
-
undefined,
|
|
3020
|
-
true
|
|
3021
|
-
);
|
|
3022
|
-
this.device.mainId = typeof mainId === 'string' ? mainId : reconnectDescriptor.path;
|
|
3023
|
-
this.device.commands.disposed = false;
|
|
3024
|
-
this.device.getCommands().mainId = this.device.mainId;
|
|
3025
|
-
return;
|
|
3026
|
-
}
|
|
3027
2715
|
|
|
3028
|
-
if (
|
|
2716
|
+
if (
|
|
2717
|
+
DataManager.isBrowserWebUsb(DataManager.getSettings('env')) &&
|
|
2718
|
+
devicesDescriptor.length === 1
|
|
2719
|
+
) {
|
|
3029
2720
|
const descriptor = devicesDescriptor[0];
|
|
3030
2721
|
if (!this.protocolV2ExpectedSerialNumber && descriptor.path !== this.protocolV2ExpectedPath) {
|
|
3031
2722
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
|
|
@@ -3143,24 +2834,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3143
2834
|
await wait(2000);
|
|
3144
2835
|
}
|
|
3145
2836
|
|
|
3146
|
-
private async acquireProtocolV2BleDevice(
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
if (!skipProtocolProbe) {
|
|
3150
|
-
await connector?.acquire(expectedId, null, true, PROTOCOL_V2_CONNECT_PROTOCOL);
|
|
3151
|
-
return;
|
|
3152
|
-
}
|
|
3153
|
-
await connector?.acquire(
|
|
3154
|
-
expectedId,
|
|
2837
|
+
private async acquireProtocolV2BleDevice() {
|
|
2838
|
+
await this.device.deviceConnector?.acquire(
|
|
2839
|
+
this.device.originalDescriptor.id,
|
|
3155
2840
|
null,
|
|
3156
2841
|
true,
|
|
3157
|
-
PROTOCOL_V2_CONNECT_PROTOCOL
|
|
3158
|
-
undefined,
|
|
3159
|
-
undefined,
|
|
3160
|
-
skipProtocolProbe
|
|
2842
|
+
PROTOCOL_V2_CONNECT_PROTOCOL
|
|
3161
2843
|
);
|
|
3162
|
-
this.device.commands.disposed = false;
|
|
3163
|
-
this.device.getCommands().mainId = expectedId;
|
|
3164
2844
|
}
|
|
3165
2845
|
|
|
3166
2846
|
private async protocolV2StartFirmwareUpdate({
|
|
@@ -3169,12 +2849,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3169
2849
|
targets: Array<{ target_id: number; path: string }>;
|
|
3170
2850
|
}) {
|
|
3171
2851
|
this.protocolV2LastRuntimeProbeFeatures = undefined;
|
|
3172
|
-
this.protocolV2InstallNeedsReconnect = false;
|
|
3173
|
-
this.protocolV2InstallDisconnectObserved = false;
|
|
3174
|
-
this.protocolV2InstallTerminalSuccessObserved = false;
|
|
3175
2852
|
const commands = this.device.getCommands();
|
|
3176
2853
|
await commands.typedCall('DeviceFirmwareUpdateStage', 'Success', { targets });
|
|
3177
|
-
this.device.setCancelableAction(() =>
|
|
2854
|
+
this.device.setCancelableAction(() => commands.cancelDevice());
|
|
3178
2855
|
const interaction = this.device.createProtocolV2UiPhaseMetadata('button', 'start');
|
|
3179
2856
|
this.postMessage(
|
|
3180
2857
|
createUiMessage(UI_REQUEST.REQUEST_BUTTON, {
|
|
@@ -3187,55 +2864,19 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3187
2864
|
...(interaction ? { interaction } : {}),
|
|
3188
2865
|
})
|
|
3189
2866
|
);
|
|
3190
|
-
|
|
3191
|
-
try {
|
|
3192
|
-
await commands.call(
|
|
3193
|
-
'DeviceFirmwareUpdateRequest',
|
|
3194
|
-
{},
|
|
3195
|
-
{
|
|
3196
|
-
returnAfterWrite: true,
|
|
3197
|
-
expectedTypes: ['Success'],
|
|
3198
|
-
onResponseAfterWrite: response => {
|
|
3199
|
-
if (response.type !== 'Success') return;
|
|
3200
|
-
this.protocolV2InstallTerminalSuccessObserved = true;
|
|
3201
|
-
this.device.clearCancelableAction();
|
|
3202
|
-
Log.log('[FirmwareUpdateV4] firmware install completed by device response');
|
|
3203
|
-
},
|
|
3204
|
-
}
|
|
3205
|
-
);
|
|
3206
|
-
Log.log('[FirmwareUpdateV4] firmware install request written; continue with status polling');
|
|
3207
|
-
} catch (error) {
|
|
3208
|
-
this.throwIfAborted();
|
|
3209
|
-
if (!isProtocolV2DeviceDisconnectedError(error)) {
|
|
3210
|
-
throw error;
|
|
3211
|
-
}
|
|
3212
|
-
Log.log(
|
|
3213
|
-
'[FirmwareUpdateV4] transport released while writing install request; continue status polling'
|
|
3214
|
-
);
|
|
3215
|
-
this.protocolV2InstallNeedsReconnect = true;
|
|
3216
|
-
this.protocolV2InstallDisconnectObserved = !isProtocolV2InstallResponseTimeout(error);
|
|
3217
|
-
}
|
|
2867
|
+
await commands.call('DeviceFirmwareUpdateRequest', {}, { returnAfterWrite: true });
|
|
3218
2868
|
}
|
|
3219
2869
|
|
|
3220
2870
|
private async protocolV2Reboot(rebootType: DeviceRebootType) {
|
|
3221
2871
|
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
3222
2872
|
try {
|
|
3223
|
-
const res = await typedCall(
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
{
|
|
3227
|
-
reboot_type: rebootType,
|
|
3228
|
-
},
|
|
3229
|
-
{ timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT }
|
|
3230
|
-
);
|
|
2873
|
+
const res = await typedCall('DeviceReboot', 'Success', {
|
|
2874
|
+
reboot_type: rebootType,
|
|
2875
|
+
});
|
|
3231
2876
|
this.device.markProtocolV2Reboot(rebootType);
|
|
3232
2877
|
return res.message;
|
|
3233
2878
|
} catch (error) {
|
|
3234
|
-
if (
|
|
3235
|
-
isProtocolV2DeviceDisconnectedError(error) ||
|
|
3236
|
-
isProtocolV2ReconnectProbeError(error) ||
|
|
3237
|
-
isProtocolV2ResponseTimeout(error)
|
|
3238
|
-
) {
|
|
2879
|
+
if (isProtocolV2DeviceDisconnectedError(error) || isProtocolV2ReconnectProbeError(error)) {
|
|
3239
2880
|
this.device.markProtocolV2Reboot(rebootType);
|
|
3240
2881
|
return { message: 'Device rebooted successfully' };
|
|
3241
2882
|
}
|