@onekeyfe/hd-core 1.2.0-alpha.6 → 1.2.0-alpha.61
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 +390 -0
- package/__tests__/DeviceCommands.test.ts +563 -0
- package/__tests__/DeviceEventRegistration.test.ts +49 -0
- package/__tests__/chain-params-onekey-compatibility.test.ts +229 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +477 -0
- package/__tests__/connectSettings.test.ts +19 -0
- package/__tests__/core-dispose.test.ts +34 -0
- package/__tests__/core-error-output.test.ts +39 -0
- package/__tests__/core-initialization.test.ts +23 -0
- package/__tests__/device-connector-protocol.test.ts +81 -0
- package/__tests__/device-features-state.test.ts +78 -0
- package/__tests__/device-identity.test.ts +52 -0
- package/__tests__/device-lifecycle-events.test.ts +351 -0
- package/__tests__/device-pool-state.test.ts +166 -0
- package/__tests__/device-settings.test.ts +437 -0
- package/__tests__/device-state-contract.test.ts +28 -0
- package/__tests__/device-state-events.test.ts +286 -0
- package/__tests__/device-state-mapper.test.ts +273 -0
- package/__tests__/device-state-projector.test.ts +94 -0
- package/__tests__/device-state-store.test.ts +82 -0
- package/__tests__/device-utils.test.ts +154 -0
- package/__tests__/device-wallet-session-store.test.ts +478 -0
- package/__tests__/deviceFeaturesUtils.test.ts +39 -0
- package/__tests__/deviceSettings.test.ts +113 -0
- package/__tests__/deviceUploadNft.test.ts +316 -0
- package/__tests__/evmLedgerLegacySafety.test.ts +12 -6
- package/__tests__/evmSignTransaction.test.ts +69 -0
- package/__tests__/evmSignTypedData.test.ts +80 -0
- package/__tests__/filesystemValidation.test.ts +53 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
- package/__tests__/get-device-state.test.ts +578 -0
- package/__tests__/homescreen.test.ts +64 -0
- package/__tests__/kaspa-public-types.type-test.ts +16 -0
- package/__tests__/kaspa-use-tweak-pro2.test.ts +20 -0
- package/__tests__/kaspaSignTransaction.test.ts +578 -0
- package/__tests__/known-device-public-types.type-test.ts +3 -0
- package/__tests__/logBlockEvent.test.ts +128 -1
- package/__tests__/method-protocol-support.test.ts +132 -0
- package/__tests__/networkUtils.test.ts +406 -0
- package/__tests__/open-wallet-session-error-response.test.ts +43 -0
- package/__tests__/open-wallet-session.test.ts +1899 -0
- package/__tests__/pro2Nft.test.ts +108 -0
- package/__tests__/pro2Wallpaper.test.ts +39 -0
- package/__tests__/protocol-binding.test.ts +89 -0
- package/__tests__/protocol-v2-bootloader-mode.test.ts +37 -0
- package/__tests__/protocol-v2-firmware-targets.test.ts +37 -0
- package/__tests__/protocol-v2-ping.test.ts +28 -0
- package/__tests__/protocol-v2-resources.test.ts +340 -0
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
- package/__tests__/protocol-v2-unlock-policy.test.ts +245 -0
- package/__tests__/protocol-v2.test.ts +6478 -2536
- package/__tests__/protocolV2FileWrite.test.ts +244 -0
- package/__tests__/protocolV2UiInteraction.test.ts +329 -0
- package/__tests__/public-device-state-api.test.ts +275 -0
- package/__tests__/public-pro2-api-boundary.test.ts +107 -0
- package/__tests__/refresh-device-state.test.ts +101 -0
- package/__tests__/request-context-logging.test.ts +16 -0
- package/__tests__/search-devices.test.ts +145 -0
- package/__tests__/tron-sign-message-init.test.ts +74 -0
- package/__tests__/uiProgressThrottle.test.ts +74 -0
- package/__tests__/uiPromiseRegistry.test.ts +115 -0
- package/dist/api/BaseMethod.d.ts +16 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts +25 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CipherKeyValue.d.ts +1 -0
- package/dist/api/CipherKeyValue.d.ts.map +1 -1
- package/dist/api/ClearSessionCache.d.ts +9 -0
- package/dist/api/ClearSessionCache.d.ts.map +1 -0
- package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
- package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/api/DirList.d.ts +1 -0
- package/dist/api/DirList.d.ts.map +1 -1
- package/dist/api/DirMake.d.ts +1 -0
- package/dist/api/DirMake.d.ts.map +1 -1
- package/dist/api/DirRemove.d.ts +1 -0
- package/dist/api/DirRemove.d.ts.map +1 -1
- package/dist/api/FileDelete.d.ts +1 -0
- package/dist/api/FileDelete.d.ts.map +1 -1
- package/dist/api/FileRead.d.ts +1 -0
- package/dist/api/FileRead.d.ts.map +1 -1
- package/dist/api/FileWrite.d.ts +2 -0
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +2 -2
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +26 -16
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceState.d.ts +8 -0
- package/dist/api/GetDeviceState.d.ts.map +1 -0
- package/dist/api/GetFeatures.d.ts +1 -1
- package/dist/api/GetFeatures.d.ts.map +1 -1
- package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts +2 -6
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts +8 -0
- package/dist/api/OpenWalletSession.d.ts.map +1 -0
- package/dist/api/PathInfo.d.ts +1 -0
- package/dist/api/PathInfo.d.ts.map +1 -1
- package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +3 -0
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts +17 -0
- package/dist/api/UploadPortfolio.d.ts.map +1 -0
- package/dist/api/alephium/AlephiumGetAddress.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
- package/dist/api/algo/AlgoGetAddress.d.ts +1 -0
- package/dist/api/algo/AlgoGetAddress.d.ts.map +1 -1
- package/dist/api/algo/AlgoSignTransaction.d.ts +1 -0
- package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +1 -0
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/aptos/AptosGetAddress.d.ts +1 -0
- package/dist/api/aptos/AptosGetAddress.d.ts.map +1 -1
- package/dist/api/aptos/AptosGetPublicKey.d.ts +1 -0
- package/dist/api/aptos/AptosGetPublicKey.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignInMessage.d.ts +1 -0
- package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignMessage.d.ts +1 -0
- package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignTransaction.d.ts +1 -0
- package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
- package/dist/api/benfen/BenfenGetAddress.d.ts.map +1 -1
- package/dist/api/benfen/BenfenGetPublicKey.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCGetAddress.d.ts +1 -0
- package/dist/api/btc/BTCGetAddress.d.ts.map +1 -1
- package/dist/api/btc/BTCGetPublicKey.d.ts +1 -0
- package/dist/api/btc/BTCGetPublicKey.d.ts.map +1 -1
- package/dist/api/btc/BTCSignMessage.d.ts +1 -0
- package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
- package/dist/api/btc/BTCSignPsbt.d.ts +1 -0
- package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
- package/dist/api/btc/BTCSignTransaction.d.ts +1 -0
- package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCVerifyMessage.d.ts +1 -0
- package/dist/api/btc/BTCVerifyMessage.d.ts.map +1 -1
- package/dist/api/btc/helpers/versionLimit.d.ts +2 -0
- package/dist/api/btc/helpers/versionLimit.d.ts.map +1 -1
- package/dist/api/cardano/CardanoGetAddress.d.ts +1 -0
- package/dist/api/cardano/CardanoGetAddress.d.ts.map +1 -1
- package/dist/api/cardano/CardanoGetPublicKey.d.ts +1 -0
- package/dist/api/cardano/CardanoGetPublicKey.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignMessage.d.ts +1 -0
- package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignTransaction.d.ts +1 -0
- package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxGetAddress.d.ts +2 -0
- package/dist/api/conflux/ConfluxGetAddress.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessage.d.ts +2 -0
- package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts +2 -0
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignTransaction.d.ts +2 -0
- package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosGetAddress.d.ts +1 -0
- package/dist/api/cosmos/CosmosGetAddress.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosGetPublicKey.d.ts +1 -0
- package/dist/api/cosmos/CosmosGetPublicKey.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosSignTransaction.d.ts +1 -0
- package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
- package/dist/api/device/DeviceCancel.d.ts +1 -0
- package/dist/api/device/DeviceCancel.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.d.ts +1 -0
- package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
- package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
- package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
- package/dist/api/device/DeviceLock.d.ts +1 -0
- package/dist/api/device/DeviceLock.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBoardloader.d.ts +1 -0
- package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBootloader.d.ts +1 -0
- package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts +1 -0
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceSupportFeatures.d.ts +1 -0
- package/dist/api/device/DeviceSupportFeatures.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +3 -2
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts +1 -0
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/device/PreInitialize.d.ts +1 -0
- package/dist/api/device/PreInitialize.d.ts.map +1 -1
- package/dist/api/dynex/DnxGetAddress.d.ts.map +1 -1
- package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMGetAddress.d.ts +1 -0
- package/dist/api/evm/EVMGetAddress.d.ts.map +1 -1
- package/dist/api/evm/EVMGetPublicKey.d.ts +1 -0
- package/dist/api/evm/EVMGetPublicKey.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessage.d.ts +1 -0
- package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTransaction.d.ts +1 -0
- package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts +1 -0
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/evm/EVMVerifyMessage.d.ts +1 -0
- package/dist/api/evm/EVMVerifyMessage.d.ts.map +1 -1
- package/dist/api/evm/protocol.d.ts +3 -0
- package/dist/api/evm/protocol.d.ts.map +1 -0
- package/dist/api/filecoin/FilecoinGetAddress.d.ts +1 -0
- package/dist/api/filecoin/FilecoinGetAddress.d.ts.map +1 -1
- package/dist/api/filecoin/FilecoinSignTransaction.d.ts +1 -0
- package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -3
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +8 -4
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/filesystemValidation.d.ts +3 -0
- package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
- package/dist/api/helpers/paramsValidator.d.ts +1 -0
- package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +42 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -0
- package/dist/api/index.d.ts +9 -25
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaGetAddress.d.ts +4 -0
- package/dist/api/kaspa/KaspaGetAddress.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +9 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
- package/dist/api/lightning/LnurlAuth.d.ts +0 -4
- package/dist/api/lightning/LnurlAuth.d.ts.map +1 -1
- package/dist/api/near/NearGetAddress.d.ts +1 -0
- package/dist/api/near/NearGetAddress.d.ts.map +1 -1
- package/dist/api/near/NearSignTransaction.d.ts +1 -0
- package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
- package/dist/api/nem/NEMGetAddress.d.ts +1 -0
- package/dist/api/nem/NEMGetAddress.d.ts.map +1 -1
- package/dist/api/nem/NEMSignTransaction.d.ts +1 -0
- package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
- package/dist/api/neo/NeoGetAddress.d.ts.map +1 -1
- package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
- package/dist/api/nervos/NervosGetAddress.d.ts.map +1 -1
- package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
- package/dist/api/nexa/NexaGetAddress.d.ts.map +1 -1
- package/dist/api/nexa/NexaSignTransaction.d.ts +1 -0
- package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
- package/dist/api/nostr/NostrDecryptMessage.d.ts +1 -0
- package/dist/api/nostr/NostrDecryptMessage.d.ts.map +1 -1
- package/dist/api/nostr/NostrEncryptMessage.d.ts +1 -0
- package/dist/api/nostr/NostrEncryptMessage.d.ts.map +1 -1
- package/dist/api/nostr/NostrGetPublicKey.d.ts +1 -0
- package/dist/api/nostr/NostrGetPublicKey.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignEvent.d.ts +1 -0
- package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignSchnorr.d.ts +1 -0
- package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotGetAddress.d.ts +2 -1
- package/dist/api/polkadot/PolkadotGetAddress.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotSignTransaction.d.ts +1 -0
- package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
- package/dist/api/polkadot/networks.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +7 -0
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceReboot.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts +7 -0
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +27 -0
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts +1 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
- package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts +1 -0
- package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -1
- package/dist/api/protocol-v2/Ping.d.ts +3 -0
- package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +1 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.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/api/scdo/ScdoGetAddress.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
- package/dist/api/solana/SolGetAddress.d.ts +1 -0
- package/dist/api/solana/SolGetAddress.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts +2 -1
- package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts +2 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts +3 -2
- package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinGetAddress.d.ts +1 -0
- package/dist/api/starcoin/StarcoinGetAddress.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinGetPublicKey.d.ts +1 -0
- package/dist/api/starcoin/StarcoinGetPublicKey.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignMessage.d.ts +1 -0
- package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignTransaction.d.ts +1 -0
- package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinVerifyMessage.d.ts +1 -0
- package/dist/api/starcoin/StarcoinVerifyMessage.d.ts.map +1 -1
- package/dist/api/stellar/StellarGetAddress.d.ts +1 -2
- package/dist/api/stellar/StellarGetAddress.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -2
- package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
- package/dist/api/sui/SuiGetAddress.d.ts +2 -1
- package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts +2 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts +2 -1
- package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +2 -1
- package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
- package/dist/api/ton/TonGetAddress.d.ts +2 -1
- package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
- package/dist/api/ton/TonSignData.d.ts +1 -0
- package/dist/api/ton/TonSignData.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts +2 -1
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/api/ton/TonSignProof.d.ts +2 -1
- package/dist/api/ton/TonSignProof.d.ts.map +1 -1
- package/dist/api/tron/TronGetAddress.d.ts +1 -0
- package/dist/api/tron/TronGetAddress.d.ts.map +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +6 -1
- package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
- package/dist/api/tron/TronSignTransaction.d.ts +2 -1
- package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
- package/dist/api/utils.d.ts +2 -1
- package/dist/api/utils.d.ts.map +1 -1
- package/dist/api/xrp/XrpGetAddress.d.ts +1 -0
- package/dist/api/xrp/XrpGetAddress.d.ts.map +1 -1
- package/dist/api/xrp/XrpSignTransaction.d.ts +1 -0
- package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/deviceEventRegistration.d.ts +13 -0
- package/dist/core/deviceEventRegistration.d.ts.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/uiPromiseRegistry.d.ts +6 -0
- package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +9 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +71 -17
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +8 -6
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +3 -2
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/device/DeviceFeaturesState.d.ts +3 -0
- package/dist/device/DeviceFeaturesState.d.ts.map +1 -0
- package/dist/device/DevicePool.d.ts +5 -2
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts +13 -0
- package/dist/device/DeviceStateMapper.d.ts.map +1 -0
- package/dist/device/DeviceStateProjector.d.ts +7 -0
- package/dist/device/DeviceStateProjector.d.ts.map +1 -0
- package/dist/device/DeviceStateStore.d.ts +21 -0
- package/dist/device/DeviceStateStore.d.ts.map +1 -0
- package/dist/device/DeviceWalletSessionStore.d.ts +27 -0
- package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -0
- package/dist/device/cloneDeviceState.d.ts +2 -0
- package/dist/device/cloneDeviceState.d.ts.map +1 -0
- package/dist/device/deviceIdentity.d.ts +5 -0
- package/dist/device/deviceIdentity.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +9 -3
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/deviceProfile/index.d.ts +0 -1
- package/dist/deviceProfile/index.d.ts.map +1 -1
- package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts +7 -0
- package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -0
- package/dist/events/device.d.ts +16 -2
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts +2 -0
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-promise.d.ts +4 -2
- package/dist/events/ui-promise.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +50 -4
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/events/ui-response.d.ts +10 -2
- package/dist/events/ui-response.d.ts.map +1 -1
- package/dist/index.d.ts +1593 -773
- package/dist/index.js +8507 -3894
- package/dist/inject.d.ts +6 -1
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
- package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/features.d.ts +21 -17
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +3 -2
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +30 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +17 -0
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +42 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +2 -0
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +27 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -0
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +27 -4
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
- package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/types/api/deviceSettings.d.ts +11 -2
- package/dist/types/api/deviceSettings.d.ts.map +1 -1
- package/dist/types/api/deviceUnlock.d.ts +6 -2
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +4 -2
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +8 -1
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/getDeviceState.d.ts +12 -0
- package/dist/types/api/getDeviceState.d.ts.map +1 -0
- package/dist/types/api/getFeatures.d.ts.map +1 -1
- package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts +2 -10
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +23 -30
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/kaspaSignTransaction.d.ts +42 -4
- package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +35 -0
- package/dist/types/api/openWalletSession.d.ts.map +1 -0
- package/dist/types/api/protocolV2.d.ts +18 -84
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/api/sessionCache.d.ts +13 -0
- package/dist/types/api/sessionCache.d.ts.map +1 -0
- package/dist/types/device.d.ts +134 -10
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +44 -21
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/assets.d.ts +2 -1
- package/dist/utils/assets.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
- package/dist/utils/deviceFeaturesUtils.d.ts +10 -3
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts +9 -9
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts +38 -7
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/deviceVersionUtils.d.ts +7 -5
- package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
- package/dist/utils/homescreen.d.ts +4 -0
- package/dist/utils/homescreen.d.ts.map +1 -1
- package/dist/utils/index.d.ts +6 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/networkUtils.d.ts +10 -1
- package/dist/utils/networkUtils.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/pro2Nft.d.ts +31 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -0
- package/dist/utils/pro2Wallpaper.d.ts +22 -0
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -0
- package/dist/utils/tracing.d.ts.map +1 -1
- package/dist/utils/uiProgressThrottle.d.ts +3 -0
- package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +53 -20
- package/src/api/CheckAllFirmwareRelease.ts +340 -1
- package/src/api/CheckBootloaderRelease.ts +1 -2
- package/src/api/CheckFirmwareRelease.ts +1 -2
- package/src/api/CipherKeyValue.ts +4 -0
- package/src/api/ClearSessionCache.ts +32 -0
- package/src/api/DetectDeviceConnectProtocol.ts +18 -0
- package/src/api/DirList.ts +9 -4
- package/src/api/DirMake.ts +7 -4
- package/src/api/DirRemove.ts +7 -4
- package/src/api/FileDelete.ts +7 -4
- package/src/api/FileRead.ts +15 -9
- package/src/api/FileWrite.ts +26 -181
- package/src/api/FirmwareUpdate.ts +17 -14
- package/src/api/FirmwareUpdateV2.ts +137 -54
- package/src/api/FirmwareUpdateV3.ts +9 -13
- package/src/api/FirmwareUpdateV4.ts +805 -626
- package/src/api/GetDeviceState.ts +59 -0
- package/src/api/GetFeatures.ts +6 -4
- package/src/api/GetOnekeyFeatures.ts +1 -75
- package/src/api/GetPassphraseState.ts +36 -21
- package/src/api/OpenWalletSession.ts +268 -0
- package/src/api/PathInfo.ts +9 -4
- package/src/api/PromptWebDeviceAccess.ts +2 -7
- package/src/api/SearchDevices.ts +31 -4
- package/src/api/UploadPortfolio.ts +40 -0
- package/src/api/alephium/AlephiumGetAddress.ts +0 -4
- package/src/api/alephium/AlephiumSignMessage.ts +0 -4
- package/src/api/alephium/AlephiumSignTransaction.ts +2 -6
- package/src/api/algo/AlgoGetAddress.ts +4 -0
- package/src/api/algo/AlgoSignTransaction.ts +4 -0
- package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +45 -32
- package/src/api/aptos/AptosGetAddress.ts +4 -0
- package/src/api/aptos/AptosGetPublicKey.ts +4 -0
- package/src/api/aptos/AptosSignInMessage.ts +4 -0
- package/src/api/aptos/AptosSignMessage.ts +4 -0
- package/src/api/aptos/AptosSignTransaction.ts +4 -0
- package/src/api/benfen/BenfenGetAddress.ts +11 -7
- package/src/api/benfen/BenfenGetPublicKey.ts +0 -4
- package/src/api/benfen/BenfenSignMessage.ts +0 -4
- package/src/api/benfen/BenfenSignTransaction.ts +0 -4
- package/src/api/btc/BTCGetAddress.ts +8 -1
- package/src/api/btc/BTCGetPublicKey.ts +9 -2
- package/src/api/btc/BTCSignMessage.ts +8 -1
- package/src/api/btc/BTCSignPsbt.ts +4 -0
- package/src/api/btc/BTCSignTransaction.ts +8 -1
- package/src/api/btc/BTCVerifyMessage.ts +8 -1
- package/src/api/btc/helpers/versionLimit.ts +7 -4
- package/src/api/cardano/CardanoGetAddress.ts +4 -0
- package/src/api/cardano/CardanoGetPublicKey.ts +4 -0
- package/src/api/cardano/CardanoSignMessage.ts +5 -1
- package/src/api/cardano/CardanoSignTransaction.ts +5 -1
- package/src/api/conflux/ConfluxGetAddress.ts +6 -0
- package/src/api/conflux/ConfluxSignMessage.ts +6 -0
- package/src/api/conflux/ConfluxSignMessageCIP23.ts +6 -0
- package/src/api/conflux/ConfluxSignTransaction.ts +8 -5
- package/src/api/cosmos/CosmosGetAddress.ts +4 -0
- package/src/api/cosmos/CosmosGetPublicKey.ts +4 -0
- package/src/api/cosmos/CosmosSignTransaction.ts +4 -0
- package/src/api/device/DeviceCancel.ts +5 -0
- package/src/api/device/DeviceChangePin.ts +28 -0
- package/src/api/device/DeviceFullyUploadResource.ts +4 -5
- package/src/api/device/DeviceLock.ts +5 -0
- package/src/api/device/DeviceRebootToBoardloader.ts +5 -0
- package/src/api/device/DeviceRebootToBootloader.ts +5 -0
- package/src/api/device/DeviceSettings.ts +195 -1
- package/src/api/device/DeviceSupportFeatures.ts +4 -0
- package/src/api/device/DeviceUnlock.ts +21 -3
- package/src/api/device/DeviceUpdateBootloader.ts +1 -2
- package/src/api/device/DeviceWipe.ts +25 -0
- package/src/api/device/PreInitialize.ts +4 -0
- package/src/api/dynex/DnxGetAddress.ts +0 -6
- package/src/api/dynex/DnxSignTransaction.ts +0 -6
- package/src/api/evm/EVMGetAddress.ts +6 -2
- package/src/api/evm/EVMGetPublicKey.ts +6 -2
- package/src/api/evm/EVMSignMessage.ts +6 -2
- package/src/api/evm/EVMSignMessageEIP712.ts +1 -11
- package/src/api/evm/EVMSignTransaction.ts +6 -2
- package/src/api/evm/EVMSignTypedData.ts +42 -50
- package/src/api/evm/EVMVerifyMessage.ts +6 -2
- package/src/api/evm/legacyV1/getAddress.ts +2 -2
- package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
- package/src/api/evm/legacyV1/signMessage.ts +2 -2
- package/src/api/evm/legacyV1/signTypedData.ts +2 -2
- package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
- package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
- package/src/api/evm/protocol.ts +6 -0
- package/src/api/filecoin/FilecoinGetAddress.ts +4 -0
- package/src/api/filecoin/FilecoinSignTransaction.ts +4 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +30 -15
- package/src/api/firmware/getBinary.ts +8 -3
- package/src/api/firmware/uploadFirmware.ts +17 -4
- package/src/api/helpers/batchGetPublickeys.ts +2 -2
- package/src/api/helpers/filesystemValidation.ts +61 -0
- package/src/api/helpers/paramsValidator.ts +1 -1
- package/src/api/helpers/protocolV2FileWrite.ts +338 -0
- package/src/api/index.ts +10 -26
- package/src/api/kaspa/KaspaGetAddress.ts +7 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +369 -29
- package/src/api/kaspa/helpers/TransferSerialize.ts +17 -7
- package/src/api/lightning/LnurlAuth.ts +0 -4
- package/src/api/near/NearGetAddress.ts +4 -0
- package/src/api/near/NearSignTransaction.ts +4 -0
- package/src/api/nem/NEMGetAddress.ts +4 -0
- package/src/api/nem/NEMSignTransaction.ts +4 -0
- package/src/api/neo/NeoGetAddress.ts +0 -4
- package/src/api/neo/NeoSignTransaction.ts +0 -4
- package/src/api/nervos/NervosGetAddress.ts +0 -4
- package/src/api/nervos/NervosSignTransaction.ts +2 -6
- package/src/api/nexa/NexaGetAddress.ts +0 -4
- package/src/api/nexa/NexaSignTransaction.ts +3 -5
- package/src/api/nostr/NostrDecryptMessage.ts +4 -0
- package/src/api/nostr/NostrEncryptMessage.ts +4 -0
- package/src/api/nostr/NostrGetPublicKey.ts +4 -0
- package/src/api/nostr/NostrSignEvent.ts +4 -0
- package/src/api/nostr/NostrSignSchnorr.ts +4 -0
- package/src/api/polkadot/PolkadotGetAddress.ts +4 -0
- package/src/api/polkadot/PolkadotSignTransaction.ts +4 -0
- package/src/api/polkadot/networks.ts +3 -3
- package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +5 -2
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +5 -2
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +8 -5
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +10 -6
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +21 -0
- package/src/api/protocol-v2/DeviceInfoGet.ts +8 -15
- package/src/api/protocol-v2/DeviceReboot.ts +7 -3
- package/src/api/protocol-v2/DeviceStatusGet.ts +19 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +197 -0
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +134 -0
- package/src/api/protocol-v2/FilesystemFormat.ts +9 -3
- package/src/api/protocol-v2/FilesystemPermissionFix.ts +5 -2
- package/src/api/protocol-v2/Ping.ts +37 -3
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +8 -3
- package/src/api/protocol-v2/helpers.ts +17 -17
- package/src/api/scdo/ScdoGetAddress.ts +0 -4
- package/src/api/scdo/ScdoSignMessage.ts +0 -4
- package/src/api/scdo/ScdoSignTransaction.ts +0 -4
- package/src/api/solana/SolGetAddress.ts +4 -0
- package/src/api/solana/SolSignMessage.ts +5 -1
- package/src/api/solana/SolSignOffchainMessage.ts +5 -1
- package/src/api/solana/SolSignTransaction.ts +6 -2
- package/src/api/starcoin/StarcoinGetAddress.ts +4 -0
- package/src/api/starcoin/StarcoinGetPublicKey.ts +4 -0
- package/src/api/starcoin/StarcoinSignMessage.ts +4 -0
- package/src/api/starcoin/StarcoinSignTransaction.ts +4 -0
- package/src/api/starcoin/StarcoinVerifyMessage.ts +4 -0
- package/src/api/stellar/StellarGetAddress.ts +1 -10
- package/src/api/stellar/StellarSignTransaction.ts +1 -14
- package/src/api/sui/SuiGetAddress.ts +5 -1
- package/src/api/sui/SuiGetPublicKey.ts +5 -1
- package/src/api/sui/SuiSignMessage.ts +5 -1
- package/src/api/sui/SuiSignTransaction.ts +5 -1
- package/src/api/ton/TonGetAddress.ts +5 -1
- package/src/api/ton/TonSignData.ts +5 -1
- package/src/api/ton/TonSignMessage.ts +5 -1
- package/src/api/ton/TonSignProof.ts +5 -1
- package/src/api/tron/TronGetAddress.ts +4 -0
- package/src/api/tron/TronSignMessage.ts +19 -8
- package/src/api/tron/TronSignTransaction.ts +5 -1
- package/src/api/utils.ts +7 -3
- package/src/api/xrp/XrpGetAddress.ts +4 -0
- package/src/api/xrp/XrpSignTransaction.ts +5 -1
- package/src/constants/index.ts +1 -4
- package/src/core/RequestQueue.ts +1 -0
- package/src/core/deviceEventRegistration.ts +27 -0
- package/src/core/index.ts +365 -152
- package/src/core/uiPromiseRegistry.ts +63 -0
- package/src/data/messages/messages-protocol-v2.json +1138 -441
- package/src/data/messages/messages.json +286 -1
- package/src/data-manager/DataManager.ts +88 -16
- package/src/data-manager/TransportManager.ts +7 -1
- package/src/data-manager/connectSettings.ts +4 -0
- package/src/device/Device.ts +891 -295
- package/src/device/DeviceCommands.ts +193 -158
- package/src/device/DeviceConnector.ts +43 -20
- package/src/device/DeviceFeaturesState.ts +25 -0
- package/src/device/DevicePool.ts +86 -22
- package/src/device/DeviceStateMapper.ts +374 -0
- package/src/device/DeviceStateProjector.ts +94 -0
- package/src/device/DeviceStateStore.ts +201 -0
- package/src/device/DeviceWalletSessionStore.ts +144 -0
- package/src/device/cloneDeviceState.ts +39 -0
- package/src/device/deviceIdentity.ts +18 -0
- package/src/deviceProfile/buildDeviceFeatures.ts +223 -189
- package/src/deviceProfile/index.ts +0 -1
- package/src/deviceProfile/protocolV2DeviceIdentity.ts +35 -0
- package/src/events/device.ts +22 -1
- package/src/events/logBlockEvent.ts +80 -2
- package/src/events/ui-promise.ts +4 -2
- package/src/events/ui-request.ts +61 -4
- package/src/events/ui-response.ts +12 -2
- package/src/inject.ts +73 -43
- package/src/lowLevelInject.ts +6 -3
- package/src/protocols/protocol-v2/deviceSession.ts +24 -0
- package/src/protocols/protocol-v2/features.ts +100 -33
- package/src/protocols/protocol-v2/firmware.ts +3 -1
- package/src/protocols/protocol-v2/index.ts +8 -1
- package/src/protocols/protocol-v2/resources.ts +390 -0
- package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +65 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +250 -0
- package/src/protocols/protocol-v2/unlockPolicy.ts +1 -0
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +118 -0
- package/src/protocols/protocol-v2/walletSession.ts +463 -0
- package/src/topLevelInject.ts +6 -3
- package/src/types/api/checkAllFirmwareRelease.ts +48 -4
- package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
- package/src/types/api/deviceSettings.ts +26 -2
- package/src/types/api/deviceUnlock.ts +13 -2
- package/src/types/api/export.ts +9 -0
- package/src/types/api/firmwareUpdate.ts +26 -5
- package/src/types/api/getDeviceState.ts +19 -0
- package/src/types/api/getFeatures.ts +3 -0
- package/src/types/api/getOnekeyFeatures.ts +3 -0
- package/src/types/api/getPassphraseState.ts +9 -11
- package/src/types/api/index.ts +38 -64
- package/src/types/api/kaspaSignTransaction.ts +60 -4
- package/src/types/api/openWalletSession.ts +54 -0
- package/src/types/api/protocolV2.ts +33 -141
- package/src/types/api/sessionCache.ts +19 -0
- package/src/types/device.ts +200 -10
- package/src/types/params.ts +9 -2
- package/src/types/settings.ts +76 -24
- package/src/utils/assets.ts +4 -1
- package/src/utils/deviceFeaturesCompat.ts +185 -0
- package/src/utils/deviceFeaturesUtils.ts +65 -47
- package/src/utils/deviceInfoUtils.ts +29 -69
- package/src/utils/deviceSettings.ts +174 -39
- package/src/utils/deviceVersionUtils.ts +25 -44
- package/src/utils/findDefectiveBatchDevice.ts +3 -3
- package/src/utils/homescreen.ts +36 -0
- package/src/utils/index.ts +27 -3
- package/src/utils/networkUtils.ts +274 -16
- package/src/utils/pro2Nft.ts +142 -0
- package/src/utils/pro2Wallpaper.ts +130 -0
- package/src/utils/tracing.ts +3 -1
- package/src/utils/uiProgressThrottle.ts +63 -0
- package/tsconfig.type-tests.json +12 -0
- package/dist/api/GetDeviceInfo.d.ts +0 -9
- package/dist/api/GetDeviceInfo.d.ts.map +0 -1
- package/dist/api/firmware/progressThrottle.d.ts +0 -3
- package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
- package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +0 -13
- package/dist/api/protocol-v2/FilesystemDiskControl.d.ts.map +0 -1
- package/dist/deviceProfile/buildDeviceProfile.d.ts +0 -21
- package/dist/deviceProfile/buildDeviceProfile.d.ts.map +0 -1
- package/dist/types/api/getDeviceInfo.d.ts +0 -87
- package/dist/types/api/getDeviceInfo.d.ts.map +0 -1
- package/src/api/GetDeviceInfo.ts +0 -145
- package/src/api/firmware/progressThrottle.ts +0 -44
- package/src/api/protocol-v2/FilesystemDiskControl.ts +0 -50
- package/src/deviceProfile/buildDeviceProfile.ts +0 -352
- package/src/types/api/getDeviceInfo.ts +0 -101
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { ERRORS, HardwareError, HardwareErrorCode, wait } from '@onekeyfe/hd-shared';
|
|
1
|
+
import { EDeviceType, ERRORS, HardwareError, HardwareErrorCode, wait } from '@onekeyfe/hd-shared';
|
|
2
2
|
import {
|
|
3
3
|
DeviceRebootType,
|
|
4
4
|
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
5
5
|
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
6
6
|
} from '@onekeyfe/hd-transport';
|
|
7
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
7
8
|
|
|
8
9
|
import { FirmwareUpdateTipMessage, UI_REQUEST } from '../events/ui-request';
|
|
10
|
+
import { validateProtocolV2FilesystemPath } from './helpers/filesystemValidation';
|
|
11
|
+
import { writeProtocolV2File } from './helpers/protocolV2FileWrite';
|
|
9
12
|
import { validateParams } from './helpers/paramsValidator';
|
|
10
13
|
import {
|
|
11
14
|
LoggerNames,
|
|
@@ -25,41 +28,51 @@ import {
|
|
|
25
28
|
} from '../protocols/protocol-v2';
|
|
26
29
|
import { requestProtocolV2DeviceInfo } from '../protocols/protocol-v2/features';
|
|
27
30
|
import {
|
|
28
|
-
|
|
31
|
+
PROTOCOL_V2_RESOURCE_DEVICE_PATHS,
|
|
32
|
+
buildProtocolV2ResourceUpdatePlan,
|
|
33
|
+
isProtocolV2ResourceFileValid,
|
|
34
|
+
readProtocolV2ResourceInventory,
|
|
35
|
+
} from '../protocols/protocol-v2/resources';
|
|
36
|
+
import {
|
|
29
37
|
getProtocolV2UnknownErrorText,
|
|
30
38
|
isProtocolV2DeviceDisconnectedError,
|
|
31
39
|
} from './protocol-v2/helpers';
|
|
32
40
|
|
|
33
|
-
import type { FirmwareUpdateV4Params } from '../types/api/firmwareUpdate';
|
|
41
|
+
import type { FirmwareUpdateV4Params, FirmwareUpdateV4Target } from '../types/api/firmwareUpdate';
|
|
34
42
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
43
|
+
import type { ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
|
|
35
44
|
import type { PROTO } from '../constants';
|
|
36
45
|
import type { TypedResponseMessage } from '../device/DeviceCommands';
|
|
37
46
|
import type {
|
|
38
47
|
Features,
|
|
39
48
|
IFirmwareReleaseInfo,
|
|
40
49
|
IProtocolV2FirmwareComponent,
|
|
41
|
-
|
|
50
|
+
IProtocolV2Resource,
|
|
51
|
+
IProtocolV2ResourceFile,
|
|
42
52
|
IVersionArray,
|
|
43
53
|
} from '../types';
|
|
44
54
|
|
|
45
55
|
const Log = getLogger(LoggerNames.Method);
|
|
46
56
|
|
|
47
|
-
const
|
|
48
|
-
const
|
|
57
|
+
const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
|
|
58
|
+
const PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT = 3 * 60 * 1000;
|
|
49
59
|
const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
|
|
50
|
-
const
|
|
51
|
-
const
|
|
60
|
+
const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
|
|
61
|
+
const PROTOCOL_V2_START_UPDATE_TIMEOUT = 3 * 60 * 1000;
|
|
62
|
+
const PROTOCOL_V2_INSTALL_TIMEOUT = 8 * 60 * 1000;
|
|
63
|
+
const PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT = 30 * 1000;
|
|
52
64
|
const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
|
|
53
65
|
const PROTOCOL_V2_TARGET_STATUS_IN_PROGRESS = 1;
|
|
54
66
|
const PROTOCOL_V2_TARGET_STATUS_FINISHED = 2;
|
|
55
67
|
const PROTOCOL_V2_TARGET_STATUS_FAILED_MIN = 3;
|
|
56
68
|
const PROTOCOL_V2_CONNECT_PROTOCOL = 'V2';
|
|
57
|
-
const PROTOCOL_V2_FIRMWARE_STAGING_VOLUME = '
|
|
69
|
+
const PROTOCOL_V2_FIRMWARE_STAGING_VOLUME = 'vol0:/';
|
|
58
70
|
const PROTOCOL_V2_MIN_FILE_CHUNK_SIZE = 64;
|
|
59
71
|
const PROTOCOL_V2_CONNECT_RETRY_COUNT = 10;
|
|
60
72
|
const PROTOCOL_V2_CONNECT_POLL_INTERVAL = 500;
|
|
61
73
|
const PROTOCOL_V2_CONNECT_SINGLE_TIMEOUT = 75 * 1000;
|
|
62
|
-
const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT =
|
|
74
|
+
const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT = 30 * 1000;
|
|
75
|
+
const PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT = 3;
|
|
63
76
|
const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
|
|
64
77
|
const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
|
|
65
78
|
const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
|
|
@@ -94,10 +107,7 @@ type ProtocolV2FirmwareUpdateStatusTarget = {
|
|
|
94
107
|
path?: string;
|
|
95
108
|
};
|
|
96
109
|
|
|
97
|
-
type ProtocolV2FirmwareUpdateStartResponse =
|
|
98
|
-
| TypedResponseMessage<'Success'>
|
|
99
|
-
| TypedResponseMessage<'DeviceFirmwareUpdateStatus'>
|
|
100
|
-
| undefined;
|
|
110
|
+
type ProtocolV2FirmwareUpdateStartResponse = TypedResponseMessage<'Success'>;
|
|
101
111
|
|
|
102
112
|
type ProtocolV2TargetBinary = { fileName: string; binary: ArrayBuffer; targetId: number };
|
|
103
113
|
type ProtocolV2InstallItem = ProtocolV2TargetBinary & {
|
|
@@ -107,6 +117,20 @@ type ProtocolV2InstallTarget = ProtocolV2InstallItem & {
|
|
|
107
117
|
path: string;
|
|
108
118
|
};
|
|
109
119
|
|
|
120
|
+
type ProtocolV2FileTransferParams = PROTO.FirmwareUpload & {
|
|
121
|
+
filePath: string;
|
|
122
|
+
processedSize?: number;
|
|
123
|
+
totalSize?: number;
|
|
124
|
+
onTransferredBytes?: (transferredBytes: number) => void;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/** Protocol V2 resource file written independently to devicePath through FileWrite. */
|
|
128
|
+
type ProtocolV2ResourceBundleBinary = {
|
|
129
|
+
name: string;
|
|
130
|
+
binary: ArrayBuffer;
|
|
131
|
+
devicePath: string;
|
|
132
|
+
};
|
|
133
|
+
|
|
110
134
|
type ProtocolV2RemoteComponentBinary = ProtocolV2RemoteComponentTarget & {
|
|
111
135
|
binary: ArrayBuffer;
|
|
112
136
|
};
|
|
@@ -114,7 +138,7 @@ type ProtocolV2RemoteComponentBinary = ProtocolV2RemoteComponentTarget & {
|
|
|
114
138
|
type ProtocolV2RemoteComponentTarget = {
|
|
115
139
|
fileName: string;
|
|
116
140
|
targetId: number;
|
|
117
|
-
kind: 'bootloader' | 'firmware'
|
|
141
|
+
kind: 'bootloader' | 'firmware';
|
|
118
142
|
};
|
|
119
143
|
|
|
120
144
|
type ProtocolV2OkppHeader = {
|
|
@@ -167,18 +191,24 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS: Readonly<
|
|
|
167
191
|
targetId: ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04,
|
|
168
192
|
kind: 'firmware',
|
|
169
193
|
},
|
|
170
|
-
CRATE: {
|
|
171
|
-
fileName: 'resource.bin',
|
|
172
|
-
targetId: ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_CRATE,
|
|
173
|
-
kind: 'resource',
|
|
174
|
-
},
|
|
175
194
|
};
|
|
176
195
|
|
|
196
|
+
const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map<number, FirmwareUpdateV4Target>([
|
|
197
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
|
|
198
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
|
|
199
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2, 'app_v2'],
|
|
200
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_COPROCESSOR, 'coprocessor'],
|
|
201
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE01, 'se01'],
|
|
202
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE02, 'se02'],
|
|
203
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE03, 'se03'],
|
|
204
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04, 'se04'],
|
|
205
|
+
]);
|
|
206
|
+
|
|
177
207
|
const PROTOCOL_V2_ROMLOADER_UNSUPPORTED_MESSAGE =
|
|
178
208
|
'FW_MGMT_TARGET_ROMLOADER is not accepted by the current Pro2 bootloader update request. Flash romloader with the loader-specific flow instead of firmwareUpdateV4.';
|
|
179
209
|
|
|
180
|
-
// hd-transport
|
|
181
|
-
//
|
|
210
|
+
// hd-transport historically decodes scalar enums as enum-name strings.
|
|
211
|
+
// Map them back to firmware protocol values before internal comparisons.
|
|
182
212
|
const PROTOCOL_V2_TARGET_ID_BY_DECODED_NAME = new Map<string, number>(
|
|
183
213
|
Object.entries(ProtocolV2FirmwareTargetType).map(([key, value]) => [key, value])
|
|
184
214
|
);
|
|
@@ -204,25 +234,12 @@ const isProtocolV2ReconnectProbeError = (error: unknown) => {
|
|
|
204
234
|
);
|
|
205
235
|
};
|
|
206
236
|
|
|
207
|
-
const
|
|
208
|
-
const message = getProtocolV2UnknownErrorText(error).toLowerCase();
|
|
209
|
-
return (
|
|
210
|
-
isProtocolV2DeviceDisconnectedError(error) ||
|
|
211
|
-
isProtocolV2ReconnectProbeError(error) ||
|
|
212
|
-
message.includes('libusb_transfer_timed_out') ||
|
|
213
|
-
(message.includes('response timeout') && message.includes('devicefirmwareupdatestatusget')) ||
|
|
214
|
-
message.includes('device not found') ||
|
|
215
|
-
message.includes('transportnotfound')
|
|
216
|
-
);
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const isProtocolV2StartUpdateTransientError = (error: unknown) => {
|
|
237
|
+
const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
|
|
220
238
|
const message = getProtocolV2UnknownErrorText(error).toLowerCase();
|
|
221
239
|
return (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
message.includes('
|
|
225
|
-
(message.includes('response timeout') && message.includes('devicefirmwareupdaterequest'))
|
|
240
|
+
message.includes('handler not registered') ||
|
|
241
|
+
message.includes('message handler not found') ||
|
|
242
|
+
message.includes('unsupported message')
|
|
226
243
|
);
|
|
227
244
|
};
|
|
228
245
|
|
|
@@ -263,25 +280,6 @@ const normalizeProtocolV2TargetStatus = (
|
|
|
263
280
|
|
|
264
281
|
const normalizeProtocolV2Hex = (value?: string) => value?.replace(/^0x/i, '').toLowerCase();
|
|
265
282
|
|
|
266
|
-
const versionArrayToNumber = (version?: IVersionArray) => {
|
|
267
|
-
if (!version) return undefined;
|
|
268
|
-
return version[0] * 0x10000 + version[1] * 0x100 + version[2];
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
const versionStringToArray = (version?: string | null): IVersionArray | undefined => {
|
|
272
|
-
if (!version) return undefined;
|
|
273
|
-
const parts = version.split('.').map(part => Number(part));
|
|
274
|
-
if (parts.length !== 3 || parts.some(part => !Number.isFinite(part))) return undefined;
|
|
275
|
-
return parts as IVersionArray;
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
const compareProtocolV2Versions = (current?: IVersionArray, target?: IVersionArray) => {
|
|
279
|
-
const currentNumber = versionArrayToNumber(current);
|
|
280
|
-
const targetNumber = versionArrayToNumber(target);
|
|
281
|
-
if (currentNumber === undefined || targetNumber === undefined) return undefined;
|
|
282
|
-
return currentNumber - targetNumber;
|
|
283
|
-
};
|
|
284
|
-
|
|
285
283
|
const bytesToHex = (bytes: Uint8Array) =>
|
|
286
284
|
Array.from(bytes)
|
|
287
285
|
.map(byte => byte.toString(16).padStart(2, '0'))
|
|
@@ -361,6 +359,43 @@ const parseProtocolV2OkppHeader = (bytes: Uint8Array): ProtocolV2OkppHeader | nu
|
|
|
361
359
|
};
|
|
362
360
|
};
|
|
363
361
|
|
|
362
|
+
export const isProtocolV2FirmwareFingerprintValid = (
|
|
363
|
+
binary: ArrayBuffer | Uint8Array,
|
|
364
|
+
fingerprint: string | undefined
|
|
365
|
+
) => {
|
|
366
|
+
const expectedFingerprint = normalizeProtocolV2Hex(fingerprint);
|
|
367
|
+
if (!expectedFingerprint) return true;
|
|
368
|
+
return bytesToHex(sha256(toProtocolV2Bytes(binary))) === expectedFingerprint;
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
export const assertProtocolV2ReconnectIdentity = (
|
|
372
|
+
expectedSerialNumber?: string,
|
|
373
|
+
actualSerialNumber?: string,
|
|
374
|
+
expectedPath?: string,
|
|
375
|
+
actualPath?: string
|
|
376
|
+
) => {
|
|
377
|
+
if (expectedSerialNumber && actualSerialNumber) {
|
|
378
|
+
if (actualSerialNumber !== expectedSerialNumber) {
|
|
379
|
+
throw ERRORS.TypedError(
|
|
380
|
+
HardwareErrorCode.DeviceNotFound,
|
|
381
|
+
`Protocol V2 reconnect physical identity mismatch: expected ${expectedSerialNumber}, received ${actualSerialNumber}`
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (expectedPath && actualPath && expectedPath === actualPath) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
throw ERRORS.TypedError(
|
|
392
|
+
HardwareErrorCode.DeviceNotFound,
|
|
393
|
+
`Protocol V2 reconnect physical identity unavailable: expected path ${
|
|
394
|
+
expectedPath ?? 'unknown'
|
|
395
|
+
}, received ${actualPath ?? 'unknown'}`
|
|
396
|
+
);
|
|
397
|
+
};
|
|
398
|
+
|
|
364
399
|
/**
|
|
365
400
|
* FirmwareUpdateV4 is the complete Protocol V2 firmware update flow.
|
|
366
401
|
*
|
|
@@ -370,9 +405,18 @@ const parseProtocolV2OkppHeader = (bytes: Uint8Array): ProtocolV2OkppHeader | nu
|
|
|
370
405
|
* - completion waits for target status to finish, reboots to normal, then polls DeviceInfo
|
|
371
406
|
*/
|
|
372
407
|
export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareUpdateV4Params> {
|
|
408
|
+
private protocolV2ExpectedSerialNumber?: string;
|
|
409
|
+
|
|
410
|
+
private protocolV2ExpectedPath?: string;
|
|
411
|
+
|
|
412
|
+
getSupportedProtocols() {
|
|
413
|
+
return ['V2'] as const;
|
|
414
|
+
}
|
|
415
|
+
|
|
373
416
|
init() {
|
|
374
417
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
375
418
|
this.requireDeviceMode = [];
|
|
419
|
+
this.unlockPolicy = 'unlock-before-run';
|
|
376
420
|
this.useDevicePassphraseState = false;
|
|
377
421
|
this.skipForceUpdateCheck = true;
|
|
378
422
|
|
|
@@ -393,7 +437,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
393
437
|
|
|
394
438
|
validateParams(payload, [
|
|
395
439
|
{ name: 'chunkSize', type: 'number' },
|
|
396
|
-
{ name: 'resourceBinaries', type: 'array', allowEmpty: true },
|
|
397
440
|
{ name: 'forcedUpdateRes', type: 'boolean' },
|
|
398
441
|
{ name: 'bootloaderBinary', type: 'buffer' },
|
|
399
442
|
{ name: 'romloaderBinary', type: 'buffer' },
|
|
@@ -405,7 +448,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
405
448
|
{ name: 'se03Binary', type: 'buffer' },
|
|
406
449
|
{ name: 'se04Binary', type: 'buffer' },
|
|
407
450
|
{ name: 'firmwareType', type: 'string' },
|
|
451
|
+
{ name: 'targetsToUpdate', type: 'array', allowEmpty: true },
|
|
408
452
|
{ name: 'platform', type: 'string' },
|
|
453
|
+
{ name: 'resourceFiles', type: 'array', allowEmpty: true },
|
|
409
454
|
]);
|
|
410
455
|
|
|
411
456
|
this.params = {
|
|
@@ -420,8 +465,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
420
465
|
se02Binary: payload.se02Binary,
|
|
421
466
|
se03Binary: payload.se03Binary,
|
|
422
467
|
se04Binary: payload.se04Binary,
|
|
423
|
-
|
|
468
|
+
resourceFiles: payload.resourceFiles,
|
|
424
469
|
firmwareType: payload.firmwareType,
|
|
470
|
+
targetsToUpdate: payload.targetsToUpdate,
|
|
425
471
|
platform: payload.platform,
|
|
426
472
|
};
|
|
427
473
|
}
|
|
@@ -429,10 +475,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
429
475
|
private getProtocolV2FirmwareChunkSize() {
|
|
430
476
|
const payloadChunkSize = Number(this.params?.chunkSize);
|
|
431
477
|
const env = DataManager.getSettings('env');
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
478
|
+
const isBle = this.params?.platform === 'native' || (env && DataManager.isBleConnect(env));
|
|
479
|
+
let maxChunkSize = PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
480
|
+
if (isBle) {
|
|
481
|
+
maxChunkSize = PROTOCOL_V2_BLE_FILE_CHUNK_SIZE;
|
|
482
|
+
}
|
|
436
483
|
if (!Number.isFinite(payloadChunkSize) || payloadChunkSize <= 0) {
|
|
437
484
|
return maxChunkSize;
|
|
438
485
|
}
|
|
@@ -443,62 +490,101 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
443
490
|
}
|
|
444
491
|
|
|
445
492
|
async run() {
|
|
446
|
-
if (!this.device.isProtocolV2()) {
|
|
447
|
-
throw ERRORS.TypedError(
|
|
448
|
-
HardwareErrorCode.RuntimeError,
|
|
449
|
-
'firmwareUpdateV4 requires a Protocol V2 device'
|
|
450
|
-
);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
493
|
Log.debug('FirmwareUpdateV4 strategy: Protocol V2');
|
|
454
494
|
return this.runProtocolV2();
|
|
455
495
|
}
|
|
456
496
|
|
|
457
497
|
private async runProtocolV2() {
|
|
498
|
+
await this.captureProtocolV2PhysicalIdentity();
|
|
458
499
|
const deviceFeatures = await this.getProtocolV2DeviceFeatures();
|
|
459
500
|
const deviceFirmwareType = getFirmwareType(deviceFeatures);
|
|
460
501
|
const firmwareType = this.params.firmwareType ?? deviceFirmwareType;
|
|
502
|
+
const needsRemoteResources =
|
|
503
|
+
!this.params.resourceFiles?.length && !!this.params.targetsToUpdate?.includes('resource');
|
|
461
504
|
|
|
462
|
-
let resourceBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
463
505
|
let fwBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
464
506
|
let bootloaderBinary: ArrayBuffer | null = null;
|
|
465
507
|
let installItems: ProtocolV2InstallItem[] | undefined;
|
|
508
|
+
let resourceBundles: ProtocolV2ResourceBundleBinary[] | undefined;
|
|
466
509
|
try {
|
|
467
510
|
this.postTipMessage(FirmwareUpdateTipMessage.StartDownloadFirmware);
|
|
468
|
-
|
|
511
|
+
resourceBundles = this.prepareExplicitProtocolV2ResourceFiles();
|
|
469
512
|
fwBinaryMap = this.collectExplicitTargetBinaries();
|
|
470
513
|
bootloaderBinary = this.prepareBootloaderBinary();
|
|
471
|
-
|
|
514
|
+
const needsRemoteFirmware = !this.hasExplicitProtocolV2Payload(fwBinaryMap);
|
|
515
|
+
const needsRemoteBootResources = !!this.params.targetsToUpdate?.includes('boot_resources');
|
|
516
|
+
if (needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) {
|
|
517
|
+
// Remote updates must use a freshly fetched config before any reboot or file write.
|
|
518
|
+
await DataManager.forceReloadData({
|
|
519
|
+
requireResources: needsRemoteResources || needsRemoteBootResources,
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
if (needsRemoteFirmware) {
|
|
472
523
|
const remoteBinaries = await this.prepareRemoteProtocolV2Binaries(
|
|
473
524
|
firmwareType,
|
|
474
525
|
deviceFeatures
|
|
475
526
|
);
|
|
476
|
-
resourceBinaryMap = remoteBinaries.resourceBinaryMap;
|
|
477
527
|
bootloaderBinary = remoteBinaries.bootloaderBinary;
|
|
478
528
|
fwBinaryMap = remoteBinaries.fwBinaryMap;
|
|
479
529
|
installItems = remoteBinaries.installItems;
|
|
480
530
|
}
|
|
481
|
-
this.
|
|
531
|
+
const bootResourceFiles = await this.prepareProtocolV2BootResources();
|
|
532
|
+
if (bootResourceFiles?.length) {
|
|
533
|
+
resourceBundles = [...(resourceBundles ?? []), ...bootResourceFiles];
|
|
534
|
+
}
|
|
535
|
+
if (!needsRemoteResources) {
|
|
536
|
+
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
537
|
+
}
|
|
482
538
|
} catch (err) {
|
|
539
|
+
if (err instanceof HardwareError && err.errorCode === HardwareErrorCode.NetworkError) {
|
|
540
|
+
throw err;
|
|
541
|
+
}
|
|
483
542
|
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateDownloadFailed, err.message ?? err);
|
|
484
543
|
}
|
|
485
544
|
|
|
486
|
-
if (
|
|
545
|
+
if (
|
|
546
|
+
!bootloaderBinary &&
|
|
547
|
+
fwBinaryMap.length === 0 &&
|
|
548
|
+
!installItems?.length &&
|
|
549
|
+
!resourceBundles?.length &&
|
|
550
|
+
!needsRemoteResources
|
|
551
|
+
) {
|
|
487
552
|
throw ERRORS.TypedError(
|
|
488
553
|
HardwareErrorCode.FirmwareUpdateDownloadFailed,
|
|
489
554
|
'No firmware to update'
|
|
490
555
|
);
|
|
491
556
|
}
|
|
492
557
|
|
|
493
|
-
await this.enterProtocolV2BootloaderMode();
|
|
558
|
+
const enteredBootloader = await this.enterProtocolV2BootloaderMode();
|
|
559
|
+
|
|
560
|
+
if (needsRemoteResources) {
|
|
561
|
+
try {
|
|
562
|
+
const stableResources = await this.prepareProtocolV2ResourceBundles();
|
|
563
|
+
resourceBundles = [...(resourceBundles ?? []), ...(stableResources ?? [])];
|
|
564
|
+
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
565
|
+
} catch (err) {
|
|
566
|
+
if (enteredBootloader) {
|
|
567
|
+
try {
|
|
568
|
+
await this.exitProtocolV2BootloaderToNormal();
|
|
569
|
+
} catch (restoreError) {
|
|
570
|
+
Log.warn(
|
|
571
|
+
'[FirmwareUpdateV4] failed to restore App mode after resource preparation error:',
|
|
572
|
+
restoreError
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateDownloadFailed, err.message ?? err);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
494
579
|
|
|
495
580
|
await this.executeProtocolV2Update({
|
|
496
|
-
resourceBinaryMap,
|
|
497
581
|
fwBinaryMap,
|
|
498
582
|
bootloaderBinary,
|
|
499
583
|
...(installItems ? { installItems } : undefined),
|
|
584
|
+
...(resourceBundles?.length ? { resourceBundles } : undefined),
|
|
500
585
|
});
|
|
501
586
|
|
|
587
|
+
this.postTipMessage(FirmwareUpdateTipMessage.SwitchFirmwareReconnectDevice);
|
|
502
588
|
await this.exitProtocolV2BootloaderToNormal();
|
|
503
589
|
|
|
504
590
|
const versions = await this.waitForProtocolV2FinalFeatures();
|
|
@@ -519,41 +605,46 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
519
605
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Device features not available');
|
|
520
606
|
}
|
|
521
607
|
|
|
522
|
-
private
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
throw ERRORS.TypedError(
|
|
527
|
-
HardwareErrorCode.CallMethodInvalidParameter,
|
|
528
|
-
`Parameter [resourceBinaries.${index}] is of type invalid and should be [buffer].`
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
});
|
|
608
|
+
private getProtocolV2SerialNumber(deviceInfo: ProtocolV2DeviceInfo) {
|
|
609
|
+
const serialNumber = deviceInfo.hw?.serial_no?.trim();
|
|
610
|
+
return serialNumber || undefined;
|
|
611
|
+
}
|
|
532
612
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
613
|
+
private assertProtocolV2DeviceInfoIdentity(deviceInfo: ProtocolV2DeviceInfo) {
|
|
614
|
+
assertProtocolV2ReconnectIdentity(
|
|
615
|
+
this.protocolV2ExpectedSerialNumber,
|
|
616
|
+
this.getProtocolV2SerialNumber(deviceInfo),
|
|
617
|
+
this.protocolV2ExpectedPath,
|
|
618
|
+
this.device.originalDescriptor.path
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private getProtocolV2DeviceInfoTimeout() {
|
|
623
|
+
return this.isBleReconnect()
|
|
624
|
+
? this.payload.protocolV2DeviceInfoTimeoutMs ?? PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT
|
|
625
|
+
: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
private async requestProtocolV2PhysicalIdentity() {
|
|
629
|
+
return requestProtocolV2DeviceInfo({
|
|
630
|
+
commands: this.device.getCommands(),
|
|
631
|
+
timeoutMs: this.getProtocolV2DeviceInfoTimeout(),
|
|
543
632
|
});
|
|
633
|
+
}
|
|
544
634
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
635
|
+
private async captureProtocolV2PhysicalIdentity() {
|
|
636
|
+
const deviceInfo = await this.requestProtocolV2PhysicalIdentity();
|
|
637
|
+
const serialNumber = this.getProtocolV2SerialNumber(deviceInfo);
|
|
638
|
+
const path = this.device.originalDescriptor.path?.trim() || undefined;
|
|
639
|
+
assertProtocolV2ReconnectIdentity(serialNumber, serialNumber, path, path);
|
|
640
|
+
this.protocolV2ExpectedSerialNumber = serialNumber;
|
|
641
|
+
this.protocolV2ExpectedPath = path;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
private async verifyProtocolV2ReconnectIdentity() {
|
|
645
|
+
const deviceInfo = await this.requestProtocolV2PhysicalIdentity();
|
|
646
|
+
this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
|
|
647
|
+
return deviceInfo;
|
|
557
648
|
}
|
|
558
649
|
|
|
559
650
|
private prepareBootloaderBinary(): ArrayBuffer | null {
|
|
@@ -562,25 +653,20 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
562
653
|
|
|
563
654
|
private hasExplicitProtocolV2Payload(fwBinaryMap: ProtocolV2TargetBinary[]) {
|
|
564
655
|
return (
|
|
565
|
-
!!this.params.
|
|
656
|
+
!!this.params.resourceFiles?.length ||
|
|
566
657
|
!!this.params.bootloaderBinary ||
|
|
567
658
|
fwBinaryMap.length > 0
|
|
568
659
|
);
|
|
569
660
|
}
|
|
570
661
|
|
|
571
662
|
private buildProtocolV2InstallItems({
|
|
572
|
-
resourceBinaryMap,
|
|
573
663
|
bootloaderBinary,
|
|
574
664
|
fwBinaryMap,
|
|
575
665
|
}: {
|
|
576
|
-
resourceBinaryMap: ProtocolV2TargetBinary[];
|
|
577
666
|
bootloaderBinary: ArrayBuffer | null;
|
|
578
667
|
fwBinaryMap: ProtocolV2TargetBinary[];
|
|
579
668
|
}): ProtocolV2InstallItem[] {
|
|
580
|
-
const installItems: ProtocolV2InstallItem[] =
|
|
581
|
-
...resource,
|
|
582
|
-
kind: 'resource',
|
|
583
|
-
}));
|
|
669
|
+
const installItems: ProtocolV2InstallItem[] = [];
|
|
584
670
|
|
|
585
671
|
if (bootloaderBinary) {
|
|
586
672
|
installItems.push({
|
|
@@ -630,203 +716,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
630
716
|
return target;
|
|
631
717
|
}
|
|
632
718
|
|
|
633
|
-
private getProtocolV2ComponentTargetVersion(
|
|
634
|
-
release: IFirmwareReleaseInfo,
|
|
635
|
-
component: IProtocolV2FirmwareComponent,
|
|
636
|
-
target: ProtocolV2RemoteComponentTarget
|
|
637
|
-
) {
|
|
638
|
-
if (component.version) return component.version;
|
|
639
|
-
if (target.targetId === ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER) {
|
|
640
|
-
return release.bootloaderVersion;
|
|
641
|
-
}
|
|
642
|
-
if (
|
|
643
|
-
target.targetId === ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1 ||
|
|
644
|
-
target.targetId === ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2
|
|
645
|
-
) {
|
|
646
|
-
return release.version;
|
|
647
|
-
}
|
|
648
|
-
return undefined;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
private getProtocolV2ComponentCurrentVersion(
|
|
652
|
-
features: Features,
|
|
653
|
-
target: ProtocolV2RemoteComponentTarget
|
|
654
|
-
) {
|
|
655
|
-
switch (target.targetId) {
|
|
656
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER:
|
|
657
|
-
return getDeviceBootloaderVersion(features);
|
|
658
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1:
|
|
659
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2:
|
|
660
|
-
return getDeviceFirmwareVersion(features);
|
|
661
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_COPROCESSOR:
|
|
662
|
-
return getDeviceBLEFirmwareVersion(features);
|
|
663
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE01:
|
|
664
|
-
return versionStringToArray(features.se01Version);
|
|
665
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE02:
|
|
666
|
-
return versionStringToArray(features.se02Version);
|
|
667
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE03:
|
|
668
|
-
return versionStringToArray(features.se03Version);
|
|
669
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04:
|
|
670
|
-
return versionStringToArray(features.se04Version);
|
|
671
|
-
default:
|
|
672
|
-
return undefined;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
private isProtocolV2ComponentVersionSatisfied(
|
|
677
|
-
release: IFirmwareReleaseInfo,
|
|
678
|
-
component: IProtocolV2FirmwareComponent,
|
|
679
|
-
target: ProtocolV2RemoteComponentTarget,
|
|
680
|
-
features: Features
|
|
681
|
-
) {
|
|
682
|
-
const targetVersion = this.getProtocolV2ComponentTargetVersion(release, component, target);
|
|
683
|
-
if (!targetVersion) return false;
|
|
684
|
-
|
|
685
|
-
const currentVersion = this.getProtocolV2ComponentCurrentVersion(features, target);
|
|
686
|
-
const compareResult = compareProtocolV2Versions(currentVersion, targetVersion);
|
|
687
|
-
return compareResult !== undefined && compareResult >= 0;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
private getProtocolV2ResourceFilePath(path: string) {
|
|
691
|
-
if (path.startsWith('vol')) return path;
|
|
692
|
-
if (path.startsWith('/')) return `vol0:${path}`;
|
|
693
|
-
return `vol0:/${path}`;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
private async readProtocolV2DeviceFileHeader(path: string) {
|
|
697
|
-
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
698
|
-
const filePath = this.getProtocolV2ResourceFilePath(path);
|
|
699
|
-
const pathInfoRes = await typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', {
|
|
700
|
-
path: filePath,
|
|
701
|
-
});
|
|
702
|
-
const fileSize = toProtocolV2FiniteNumber(pathInfoRes.message?.size);
|
|
703
|
-
if (
|
|
704
|
-
!pathInfoRes.message?.exist ||
|
|
705
|
-
pathInfoRes.message?.directory ||
|
|
706
|
-
fileSize === undefined ||
|
|
707
|
-
fileSize < PROTOCOL_V2_OKPP_HEADER_SIZE
|
|
708
|
-
) {
|
|
709
|
-
return null;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
713
|
-
const chunks: Uint8Array[] = [];
|
|
714
|
-
let offset = 0;
|
|
715
|
-
while (offset < PROTOCOL_V2_OKPP_HEADER_SIZE) {
|
|
716
|
-
const readLen = Math.min(chunkSize, PROTOCOL_V2_OKPP_HEADER_SIZE - offset);
|
|
717
|
-
const res = await typedCall('FilesystemFileRead', 'FilesystemFile', {
|
|
718
|
-
file: {
|
|
719
|
-
path: filePath,
|
|
720
|
-
offset,
|
|
721
|
-
total_size: 0,
|
|
722
|
-
},
|
|
723
|
-
chunk_len: readLen,
|
|
724
|
-
ui_percentage: undefined,
|
|
725
|
-
});
|
|
726
|
-
const data = toProtocolV2Bytes(res.message?.data);
|
|
727
|
-
if (data.byteLength === 0) return null;
|
|
728
|
-
chunks.push(data);
|
|
729
|
-
offset += data.byteLength;
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
const headerBytes = new Uint8Array(offset);
|
|
733
|
-
let cursor = 0;
|
|
734
|
-
chunks.forEach(chunk => {
|
|
735
|
-
headerBytes.set(chunk, cursor);
|
|
736
|
-
cursor += chunk.byteLength;
|
|
737
|
-
});
|
|
738
|
-
return parseProtocolV2OkppHeader(headerBytes);
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
private async isProtocolV2ResourcePackageMatched(
|
|
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(
|
|
795
|
-
release: IFirmwareReleaseInfo,
|
|
796
|
-
key: string,
|
|
797
|
-
component: IProtocolV2FirmwareComponent,
|
|
798
|
-
target: ProtocolV2RemoteComponentTarget,
|
|
799
|
-
features: Features
|
|
800
|
-
) {
|
|
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
|
-
const versionSatisfied = this.isProtocolV2ComponentVersionSatisfied(
|
|
819
|
-
release,
|
|
820
|
-
component,
|
|
821
|
-
target,
|
|
822
|
-
features
|
|
823
|
-
);
|
|
824
|
-
if (versionSatisfied) {
|
|
825
|
-
Log.log(`[FirmwareUpdateV4] skip Protocol V2 component ${key}; version is up to date`);
|
|
826
|
-
}
|
|
827
|
-
return !versionSatisfied;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
719
|
private async downloadRemoteProtocolV2Component(
|
|
831
720
|
key: string,
|
|
832
721
|
component: IProtocolV2FirmwareComponent
|
|
@@ -840,6 +729,22 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
840
729
|
}
|
|
841
730
|
|
|
842
731
|
const { binary } = await getSysResourceBinary(component.url);
|
|
732
|
+
if (!isProtocolV2FirmwareFingerprintValid(binary, component.fingerprint)) {
|
|
733
|
+
throw ERRORS.TypedError(
|
|
734
|
+
HardwareErrorCode.RuntimeError,
|
|
735
|
+
`Protocol V2 firmware fingerprint mismatch: ${key}/${component.target}`
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
const expectedPayloadHash = normalizeProtocolV2Hex(component.payloadHash);
|
|
739
|
+
if (expectedPayloadHash) {
|
|
740
|
+
const header = parseProtocolV2OkppHeader(toProtocolV2Bytes(binary));
|
|
741
|
+
if (!header || header.payloadHash !== expectedPayloadHash) {
|
|
742
|
+
throw ERRORS.TypedError(
|
|
743
|
+
HardwareErrorCode.RuntimeError,
|
|
744
|
+
`Protocol V2 firmware payload hash mismatch: ${key}/${component.target}`
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
843
748
|
return {
|
|
844
749
|
...target,
|
|
845
750
|
binary,
|
|
@@ -849,14 +754,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
849
754
|
private async prepareRemoteProtocolV2Binaries(firmwareType: EFirmwareType, features: Features) {
|
|
850
755
|
const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
|
|
851
756
|
|
|
852
|
-
const resourceBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
853
757
|
let bootloaderBinary: ArrayBuffer | null = null;
|
|
854
758
|
const fwBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
855
759
|
const installItems: ProtocolV2InstallItem[] = [];
|
|
856
760
|
|
|
857
761
|
if (!release) {
|
|
858
762
|
return {
|
|
859
|
-
resourceBinaryMap,
|
|
860
763
|
bootloaderBinary,
|
|
861
764
|
fwBinaryMap,
|
|
862
765
|
installItems,
|
|
@@ -864,27 +767,17 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
864
767
|
}
|
|
865
768
|
|
|
866
769
|
const entries = this.getRemoteComponentEntries(release);
|
|
770
|
+
const targetsToUpdate = new Set(this.params.targetsToUpdate ?? []);
|
|
867
771
|
|
|
868
772
|
for (const [key, component] of entries) {
|
|
869
|
-
const
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
features
|
|
876
|
-
);
|
|
877
|
-
if (shouldInstall) {
|
|
773
|
+
const targetName = component.target?.toUpperCase();
|
|
774
|
+
const target = PROTOCOL_V2_REMOTE_COMPONENT_TARGETS[targetName];
|
|
775
|
+
const updateTarget = target
|
|
776
|
+
? PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId)
|
|
777
|
+
: undefined;
|
|
778
|
+
if (updateTarget && targetsToUpdate.has(updateTarget)) {
|
|
878
779
|
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') {
|
|
780
|
+
if (remoteBinary.kind === 'bootloader') {
|
|
888
781
|
bootloaderBinary = remoteBinary.binary;
|
|
889
782
|
installItems.push({
|
|
890
783
|
fileName: remoteBinary.fileName,
|
|
@@ -905,32 +798,205 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
905
798
|
}
|
|
906
799
|
|
|
907
800
|
return {
|
|
908
|
-
resourceBinaryMap,
|
|
909
801
|
bootloaderBinary,
|
|
910
802
|
fwBinaryMap,
|
|
911
803
|
installItems,
|
|
912
804
|
};
|
|
913
805
|
}
|
|
914
806
|
|
|
807
|
+
private getProtocolV2DeviceType(): EDeviceType.Pro2 | EDeviceType.Neo {
|
|
808
|
+
const deviceType = this.device.getCurrentDeviceType();
|
|
809
|
+
if (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo) return deviceType;
|
|
810
|
+
throw new Error(`Unsupported Protocol V2 device type: ${deviceType}`);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
private async prepareProtocolV2BootResources(): Promise<
|
|
814
|
+
ProtocolV2ResourceBundleBinary[] | undefined
|
|
815
|
+
> {
|
|
816
|
+
if (!this.params.targetsToUpdate?.includes('boot_resources')) return undefined;
|
|
817
|
+
const resource = DataManager.getProtocolV2BootResources(this.getProtocolV2DeviceType());
|
|
818
|
+
if (!resource) throw new Error('Missing Protocol V2 boot resources configuration');
|
|
819
|
+
|
|
820
|
+
const files: ProtocolV2ResourceBundleBinary[] = [];
|
|
821
|
+
for (const file of resource.files) {
|
|
822
|
+
Log.log(`[FirmwareUpdateV4] downloading boot resource ${file.devicePath}`);
|
|
823
|
+
const { binary } = await getSysResourceBinary(file.url);
|
|
824
|
+
if (!isProtocolV2ResourceFileValid(binary, file)) {
|
|
825
|
+
throw new Error(`Boot resource file verification failed: ${file.devicePath}`);
|
|
826
|
+
}
|
|
827
|
+
files.push({
|
|
828
|
+
name: file.name ?? file.devicePath.split('/').pop() ?? file.devicePath,
|
|
829
|
+
binary,
|
|
830
|
+
devicePath: file.devicePath,
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
return files;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
private prepareExplicitProtocolV2ResourceFiles(): ProtocolV2ResourceBundleBinary[] | undefined {
|
|
837
|
+
const files = this.params.resourceFiles ?? [];
|
|
838
|
+
if (!files?.length) return undefined;
|
|
839
|
+
|
|
840
|
+
const prepared = files.map((file, index) => {
|
|
841
|
+
const devicePath = validateProtocolV2FilesystemPath(
|
|
842
|
+
file.devicePath,
|
|
843
|
+
`resourceFiles[${index}].devicePath`
|
|
844
|
+
);
|
|
845
|
+
const descriptor = file as typeof file &
|
|
846
|
+
Pick<Partial<IProtocolV2ResourceFile>, 'size' | 'fileHash'>;
|
|
847
|
+
if (descriptor.size !== undefined && descriptor.size !== file.binary.byteLength) {
|
|
848
|
+
throw new Error(`resourceFiles[${index}] size mismatch`);
|
|
849
|
+
}
|
|
850
|
+
if (
|
|
851
|
+
descriptor.fileHash &&
|
|
852
|
+
!isProtocolV2ResourceFileValid(file.binary, {
|
|
853
|
+
size: file.binary.byteLength,
|
|
854
|
+
fileHash: descriptor.fileHash,
|
|
855
|
+
})
|
|
856
|
+
) {
|
|
857
|
+
throw new Error(`resourceFiles[${index}] SHA-256 mismatch`);
|
|
858
|
+
}
|
|
859
|
+
return {
|
|
860
|
+
name: devicePath.split('/').pop() ?? devicePath,
|
|
861
|
+
binary: file.binary,
|
|
862
|
+
devicePath,
|
|
863
|
+
};
|
|
864
|
+
});
|
|
865
|
+
if (new Set(prepared.map(file => file.devicePath)).size !== prepared.length) {
|
|
866
|
+
throw new Error('resourceFiles contain duplicate devicePath values');
|
|
867
|
+
}
|
|
868
|
+
return prepared;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
private async prepareProtocolV2ResourceBundles(): Promise<
|
|
872
|
+
ProtocolV2ResourceBundleBinary[] | undefined
|
|
873
|
+
> {
|
|
874
|
+
if (!this.params.targetsToUpdate?.includes('resource')) {
|
|
875
|
+
return undefined;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
const resources = DataManager.getProtocolV2Resources(this.getProtocolV2DeviceType());
|
|
879
|
+
if (!resources?.length) {
|
|
880
|
+
throw new Error('Missing Pro2 stable resource configuration');
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
const inventory = this.params.forcedUpdateRes
|
|
884
|
+
? undefined
|
|
885
|
+
: await readProtocolV2ResourceInventory({
|
|
886
|
+
commands: this.device.getCommands(),
|
|
887
|
+
resources,
|
|
888
|
+
chunkSize: this.getProtocolV2FirmwareChunkSize(),
|
|
889
|
+
timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
|
|
890
|
+
});
|
|
891
|
+
const plan = buildProtocolV2ResourceUpdatePlan({
|
|
892
|
+
resources,
|
|
893
|
+
inventory,
|
|
894
|
+
mode: 'bootloader-recovery',
|
|
895
|
+
forced: this.params.forcedUpdateRes,
|
|
896
|
+
});
|
|
897
|
+
Log.log(
|
|
898
|
+
`[FirmwareUpdateV4] Protocol V2 resource plan mode=bootloader-recovery status=${plan.status} count=${plan.resources.length}`
|
|
899
|
+
);
|
|
900
|
+
|
|
901
|
+
const bundles: ProtocolV2ResourceBundleBinary[] = [];
|
|
902
|
+
for (const resource of plan.resources) {
|
|
903
|
+
bundles.push(await this.downloadProtocolV2Resource(resource));
|
|
904
|
+
}
|
|
905
|
+
return bundles;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
private async downloadProtocolV2Resource(
|
|
909
|
+
resource: IProtocolV2Resource
|
|
910
|
+
): Promise<ProtocolV2ResourceBundleBinary> {
|
|
911
|
+
Log.log(`[FirmwareUpdateV4] downloading Pro2 resource ${resource.type}`);
|
|
912
|
+
const { binary } = await getSysResourceBinary(resource.url);
|
|
913
|
+
if (!isProtocolV2ResourceFileValid(binary, resource)) {
|
|
914
|
+
throw new Error(`Pro2 resource file verification failed: ${resource.type}`);
|
|
915
|
+
}
|
|
916
|
+
return {
|
|
917
|
+
name: `${resource.type}.okpkg`,
|
|
918
|
+
binary,
|
|
919
|
+
devicePath: PROTOCOL_V2_RESOURCE_DEVICE_PATHS[resource.type],
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
private async syncProtocolV2ResourceBundles(
|
|
924
|
+
bundles: ProtocolV2ResourceBundleBinary[],
|
|
925
|
+
firmwareSize: number
|
|
926
|
+
): Promise<{ processedSize: number; totalSize: number }> {
|
|
927
|
+
const transferStartTime = Date.now();
|
|
928
|
+
const transferTransport = this.getProtocolV2FirmwareTransferTransport();
|
|
929
|
+
|
|
930
|
+
// Write directly to the device through FileWrite.
|
|
931
|
+
let totalSize = 0;
|
|
932
|
+
for (const b of bundles) totalSize += b.binary.byteLength;
|
|
933
|
+
|
|
934
|
+
const transferTotalSize = totalSize + firmwareSize;
|
|
935
|
+
let processedSize = 0;
|
|
936
|
+
for (const bundle of bundles) {
|
|
937
|
+
Log.log(
|
|
938
|
+
`[FirmwareUpdateV4] syncing resource ${bundle.name} -> ${bundle.devicePath} bytes=${bundle.binary.byteLength}`
|
|
939
|
+
);
|
|
940
|
+
processedSize = await this.protocolV2CommonUpdateProcess({
|
|
941
|
+
payload: bundle.binary,
|
|
942
|
+
filePath: bundle.devicePath,
|
|
943
|
+
processedSize,
|
|
944
|
+
totalSize: transferTotalSize,
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
const elapsedMs = Date.now() - transferStartTime;
|
|
949
|
+
Log.log(
|
|
950
|
+
`[FirmwareUpdateV4] resource sync finished transport=${transferTransport} bytes=${totalSize} elapsed=${(
|
|
951
|
+
elapsedMs / 1000
|
|
952
|
+
).toFixed(2)}s speed=${formatProtocolV2TransferSpeed(totalSize, elapsedMs)} KB/s`
|
|
953
|
+
);
|
|
954
|
+
return { processedSize, totalSize: transferTotalSize };
|
|
955
|
+
}
|
|
956
|
+
|
|
915
957
|
private isProtocolV2BootloaderMode() {
|
|
916
958
|
if (typeof this.device.isBootloader === 'function') {
|
|
917
|
-
return this.device.isBootloader();
|
|
959
|
+
return !!this.device.isBootloader();
|
|
918
960
|
}
|
|
919
|
-
return
|
|
961
|
+
return (
|
|
962
|
+
this.device.features?.mode === 'bootloader' ||
|
|
963
|
+
(this.device.features?.mode == null && !!this.device.features?.bootloaderMode)
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
private isProtocolV2RomloaderMode() {
|
|
968
|
+
const deviceType = this.device.getCurrentDeviceType();
|
|
969
|
+
if (
|
|
970
|
+
!this.device.isProtocolV2() ||
|
|
971
|
+
(deviceType !== EDeviceType.Pro2 && deviceType !== EDeviceType.Neo)
|
|
972
|
+
) {
|
|
973
|
+
return false;
|
|
974
|
+
}
|
|
975
|
+
if (typeof this.device.isRomloader === 'function') {
|
|
976
|
+
return this.device.isRomloader();
|
|
977
|
+
}
|
|
978
|
+
return this.device.features?.mode === 'romloader';
|
|
920
979
|
}
|
|
921
980
|
|
|
922
981
|
async enterProtocolV2BootloaderMode() {
|
|
982
|
+
// romloader is the first update environment and forwards targets to bootloader.
|
|
983
|
+
// It rejects DeviceRebootType.Bootloader, so reuse the current connection.
|
|
984
|
+
if (this.isProtocolV2RomloaderMode()) {
|
|
985
|
+
Log.debug('Protocol V2 device is in romloader mode; start firmware update directly');
|
|
986
|
+
return false;
|
|
987
|
+
}
|
|
923
988
|
if (this.isProtocolV2BootloaderMode()) {
|
|
924
|
-
Log.debug('Protocol V2 device is already in bootloader mode, skip reboot
|
|
989
|
+
Log.debug('Protocol V2 device is already in bootloader mode, skip reboot');
|
|
990
|
+
this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
|
|
925
991
|
return false;
|
|
926
992
|
}
|
|
927
993
|
|
|
928
994
|
try {
|
|
929
995
|
this.postTipMessage(FirmwareUpdateTipMessage.AutoRebootToBootloader);
|
|
930
996
|
await this.protocolV2Reboot(DeviceRebootType.Bootloader);
|
|
931
|
-
this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
|
|
932
997
|
await wait(1000);
|
|
933
998
|
await this.waitForProtocolV2BootloaderMode();
|
|
999
|
+
this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
|
|
934
1000
|
return true;
|
|
935
1001
|
} catch (error) {
|
|
936
1002
|
if (error instanceof HardwareError) {
|
|
@@ -947,20 +1013,32 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
947
1013
|
) {
|
|
948
1014
|
const startTime = Date.now();
|
|
949
1015
|
let lastError: unknown;
|
|
1016
|
+
let shouldReconnect = true;
|
|
950
1017
|
|
|
951
1018
|
while (Date.now() - startTime < timeout) {
|
|
952
1019
|
try {
|
|
953
|
-
|
|
1020
|
+
if (shouldReconnect) {
|
|
1021
|
+
await this.reconnectProtocolV2Device();
|
|
1022
|
+
shouldReconnect = false;
|
|
1023
|
+
}
|
|
954
1024
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
955
1025
|
commands: this.device.getCommands(),
|
|
956
|
-
timeoutMs:
|
|
1026
|
+
timeoutMs: this.getProtocolV2DeviceInfoTimeout(),
|
|
957
1027
|
});
|
|
958
|
-
|
|
959
|
-
|
|
1028
|
+
this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
|
|
1029
|
+
const features = await this.device.probeProtocolV2RuntimeState(
|
|
1030
|
+
deviceInfo,
|
|
1031
|
+
PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
|
|
1032
|
+
);
|
|
1033
|
+
if (features?.mode === 'bootloader') {
|
|
960
1034
|
return features;
|
|
961
1035
|
}
|
|
962
1036
|
lastError = new Error('Protocol V2 device is reachable but is not in bootloader mode');
|
|
963
1037
|
} catch (error) {
|
|
1038
|
+
if (this.isProtocolV2ReconnectIdentityError(error)) {
|
|
1039
|
+
throw error;
|
|
1040
|
+
}
|
|
1041
|
+
shouldReconnect = true;
|
|
964
1042
|
lastError = error;
|
|
965
1043
|
Log.log('Protocol V2 bootloader mode not ready, polling reconnect: ', error);
|
|
966
1044
|
}
|
|
@@ -976,8 +1054,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
976
1054
|
}
|
|
977
1055
|
|
|
978
1056
|
/**
|
|
979
|
-
*
|
|
980
|
-
*
|
|
1057
|
+
* Collect explicit target binaries grouped by DeviceFirmwareTargetType.
|
|
1058
|
+
* Filenames are display-only staging paths because target_id is explicit.
|
|
981
1059
|
*/
|
|
982
1060
|
private collectExplicitTargetBinaries() {
|
|
983
1061
|
const entries: ProtocolV2TargetBinary[] = [];
|
|
@@ -1014,30 +1092,48 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1014
1092
|
}
|
|
1015
1093
|
|
|
1016
1094
|
private async executeProtocolV2Update({
|
|
1017
|
-
resourceBinaryMap,
|
|
1018
1095
|
fwBinaryMap,
|
|
1019
1096
|
bootloaderBinary,
|
|
1020
1097
|
installItems,
|
|
1098
|
+
resourceBundles,
|
|
1021
1099
|
}: {
|
|
1022
|
-
resourceBinaryMap?: ProtocolV2TargetBinary[];
|
|
1023
1100
|
fwBinaryMap?: ProtocolV2TargetBinary[];
|
|
1024
1101
|
bootloaderBinary?: ArrayBuffer | null;
|
|
1025
1102
|
installItems?: ProtocolV2InstallItem[];
|
|
1103
|
+
resourceBundles?: ProtocolV2ResourceBundleBinary[];
|
|
1026
1104
|
}) {
|
|
1027
1105
|
const orderedInstallItems =
|
|
1028
1106
|
installItems ??
|
|
1029
1107
|
this.buildProtocolV2InstallItems({
|
|
1030
|
-
resourceBinaryMap: resourceBinaryMap ?? [],
|
|
1031
1108
|
bootloaderBinary: bootloaderBinary ?? null,
|
|
1032
1109
|
fwBinaryMap: fwBinaryMap ?? [],
|
|
1033
1110
|
});
|
|
1034
|
-
let totalSize = 0;
|
|
1035
|
-
let processedSize = 0;
|
|
1036
|
-
let transferredSize = 0;
|
|
1037
1111
|
|
|
1038
|
-
|
|
1112
|
+
let firmwareSize = 0;
|
|
1113
|
+
for (const item of orderedInstallItems) firmwareSize += item.binary.byteLength;
|
|
1039
1114
|
|
|
1040
1115
|
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
1116
|
+
|
|
1117
|
+
let processedSize = 0;
|
|
1118
|
+
let totalSize = firmwareSize;
|
|
1119
|
+
if (resourceBundles?.length) {
|
|
1120
|
+
const resourceTransfer = await this.syncProtocolV2ResourceBundles(
|
|
1121
|
+
resourceBundles,
|
|
1122
|
+
firmwareSize
|
|
1123
|
+
);
|
|
1124
|
+
processedSize = resourceTransfer.processedSize;
|
|
1125
|
+
totalSize = resourceTransfer.totalSize;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
// Skip staging and installation when the update contains resource files only.
|
|
1129
|
+
if (orderedInstallItems.length === 0) {
|
|
1130
|
+
Log.log('[FirmwareUpdateV4] no firmware targets to install (resource files only)');
|
|
1131
|
+
if (totalSize > 0) {
|
|
1132
|
+
this.postProgressMessage(100, 'transferData');
|
|
1133
|
+
}
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
let transferredSize = processedSize;
|
|
1041
1137
|
const transferStartTime = Date.now();
|
|
1042
1138
|
const transferTransport = this.getProtocolV2FirmwareTransferTransport();
|
|
1043
1139
|
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
@@ -1064,6 +1160,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1064
1160
|
onTransferredBytes,
|
|
1065
1161
|
});
|
|
1066
1162
|
transferredSize = processedSize;
|
|
1163
|
+
await this.verifyProtocolV2StagedFile(filePath, item.binary.byteLength);
|
|
1067
1164
|
|
|
1068
1165
|
stagedInstallTargets.push({
|
|
1069
1166
|
...item,
|
|
@@ -1093,203 +1190,289 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1093
1190
|
|
|
1094
1191
|
this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
|
|
1095
1192
|
|
|
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();
|
|
1193
|
+
const allTargets = stagedInstallTargets.map(item => ({
|
|
1194
|
+
target_id: item.targetId,
|
|
1195
|
+
path: item.path,
|
|
1196
|
+
}));
|
|
1197
|
+
Log.log(`[FirmwareUpdateV4] DeviceFirmwareUpdateRequest targets=${JSON.stringify(allTargets)}`);
|
|
1198
|
+
await this.protocolV2StartFirmwareUpdate({ targets: allTargets });
|
|
1199
|
+
await this.waitForProtocolV2FirmwareUpdateComplete(allTargets);
|
|
1128
1200
|
}
|
|
1129
1201
|
|
|
1130
1202
|
private getProtocolV2InstallItemStagingPath(item: ProtocolV2InstallItem) {
|
|
1131
1203
|
return `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${item.fileName}`;
|
|
1132
1204
|
}
|
|
1133
1205
|
|
|
1134
|
-
private async
|
|
1206
|
+
private async verifyProtocolV2StagedFile(path: string, expectedSize: number) {
|
|
1135
1207
|
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
private async pingProtocolV2Device() {
|
|
1147
|
-
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
1148
|
-
await typedCall(
|
|
1149
|
-
'Ping',
|
|
1150
|
-
'Success',
|
|
1151
|
-
{ message: 'firmware-update' },
|
|
1152
|
-
{
|
|
1153
|
-
timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
|
|
1154
|
-
}
|
|
1155
|
-
);
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
private isProtocolV2NormalModeFeatures(features?: Features | null) {
|
|
1159
|
-
return !!features && !features.bootloaderMode && features.mode !== 'bootloader';
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
private async probeProtocolV2NormalMode() {
|
|
1163
|
-
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
1164
|
-
commands: this.device.getCommands(),
|
|
1165
|
-
timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
|
|
1166
|
-
request: PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
|
|
1167
|
-
});
|
|
1168
|
-
const features = this.device.updateProtocolV2Features(deviceInfo);
|
|
1169
|
-
if (this.isProtocolV2NormalModeFeatures(features)) {
|
|
1170
|
-
Log.log('Protocol V2 firmware install finished; device is back in normal mode');
|
|
1171
|
-
return true;
|
|
1208
|
+
const response = await typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path });
|
|
1209
|
+
const actualSize = toProtocolV2FiniteNumber(response.message?.size);
|
|
1210
|
+
if (!response.message?.exist || response.message?.directory || actualSize !== expectedSize) {
|
|
1211
|
+
throw ERRORS.TypedError(
|
|
1212
|
+
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1213
|
+
`staged file verification failed: path=${path} exist=${!!response.message
|
|
1214
|
+
?.exist} expected=${expectedSize} actual=${actualSize ?? 'unknown'}`
|
|
1215
|
+
);
|
|
1172
1216
|
}
|
|
1173
|
-
return false;
|
|
1174
1217
|
}
|
|
1175
1218
|
|
|
1176
1219
|
private assertProtocolV2TargetStatus(
|
|
1177
1220
|
statusTargets: ProtocolV2FirmwareUpdateStatusTarget[],
|
|
1178
1221
|
expectedTargetIds: Set<number>
|
|
1179
1222
|
) {
|
|
1223
|
+
Log.log(
|
|
1224
|
+
`[FirmwareUpdateV4] DeviceFirmwareUpdateStatus records=${JSON.stringify(statusTargets)}`
|
|
1225
|
+
);
|
|
1180
1226
|
const failedTarget = statusTargets.find(
|
|
1181
1227
|
target =>
|
|
1182
1228
|
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1) &&
|
|
1183
1229
|
isProtocolV2TargetStatusFailed(target.status)
|
|
1184
1230
|
);
|
|
1185
1231
|
if (failedTarget) {
|
|
1232
|
+
const failedTargetDetails = JSON.stringify({
|
|
1233
|
+
targetId: failedTarget.target_id,
|
|
1234
|
+
status: failedTarget.status,
|
|
1235
|
+
payloadVersion: failedTarget.payload_version,
|
|
1236
|
+
path: failedTarget.path,
|
|
1237
|
+
});
|
|
1238
|
+
Log.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
|
|
1186
1239
|
throw ERRORS.TypedError(
|
|
1187
1240
|
HardwareErrorCode.FirmwareError,
|
|
1188
|
-
`Protocol V2 firmware target
|
|
1241
|
+
`Protocol V2 firmware target failed: target=${failedTarget.target_id} status=${
|
|
1242
|
+
failedTarget.status ?? 'unknown'
|
|
1243
|
+
} payloadVersion=${failedTarget.payload_version ?? 'unknown'} path=${
|
|
1244
|
+
failedTarget.path ?? 'unknown'
|
|
1245
|
+
}`
|
|
1189
1246
|
);
|
|
1190
1247
|
}
|
|
1191
1248
|
|
|
1192
|
-
const
|
|
1193
|
-
target
|
|
1194
|
-
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1) &&
|
|
1195
|
-
isProtocolV2TargetStatusFinished(target.status)
|
|
1249
|
+
const matchingTargets = statusTargets.filter(target =>
|
|
1250
|
+
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1)
|
|
1196
1251
|
);
|
|
1197
|
-
|
|
1252
|
+
const completedTargetIds = new Set<number>();
|
|
1253
|
+
matchingTargets.forEach(target => {
|
|
1254
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
1255
|
+
if (targetId !== undefined && isProtocolV2TargetStatusFinished(target.status)) {
|
|
1256
|
+
completedTargetIds.add(targetId);
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
const allExpectedTargetsCompleted =
|
|
1260
|
+
expectedTargetIds.size > 0 &&
|
|
1261
|
+
Array.from(expectedTargetIds).every(targetId => completedTargetIds.has(targetId));
|
|
1262
|
+
if (allExpectedTargetsCompleted) {
|
|
1263
|
+
this.postProgressMessage(100, 'installingFirmware');
|
|
1198
1264
|
return true;
|
|
1199
1265
|
}
|
|
1200
1266
|
|
|
1201
|
-
|
|
1202
|
-
target =>
|
|
1203
|
-
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1) &&
|
|
1267
|
+
if (expectedTargetIds.size > 0 && matchingTargets.length > 0) {
|
|
1268
|
+
const hasInProgressTarget = matchingTargets.some(target =>
|
|
1204
1269
|
isProtocolV2TargetStatusInProgress(target.status)
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1270
|
+
);
|
|
1271
|
+
const completedProgress = Math.floor(
|
|
1272
|
+
(completedTargetIds.size / expectedTargetIds.size) * 100
|
|
1273
|
+
);
|
|
1274
|
+
// The protocol exposes no per-target percentage, so report coarse progress by
|
|
1275
|
+
// completed targets and use 1% once work starts to keep the UI responsive.
|
|
1276
|
+
const progress = Math.min(99, Math.max(completedProgress, hasInProgressTarget ? 1 : 0));
|
|
1277
|
+
this.postProgressMessage(progress, 'installingFirmware');
|
|
1208
1278
|
}
|
|
1209
1279
|
|
|
1210
1280
|
return false;
|
|
1211
1281
|
}
|
|
1212
1282
|
|
|
1213
|
-
private
|
|
1214
|
-
|
|
1215
|
-
|
|
1283
|
+
private getProtocolV2MissingTargetIds(
|
|
1284
|
+
statusTargets: ProtocolV2FirmwareUpdateStatusTarget[],
|
|
1285
|
+
expectedTargetIds: Set<number>
|
|
1216
1286
|
) {
|
|
1217
|
-
const
|
|
1218
|
-
|
|
1219
|
-
const
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
return;
|
|
1287
|
+
const reportedTargetIds = new Set<number>();
|
|
1288
|
+
statusTargets.forEach(target => {
|
|
1289
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
1290
|
+
if (targetId !== undefined) {
|
|
1291
|
+
reportedTargetIds.add(targetId);
|
|
1223
1292
|
}
|
|
1224
|
-
}
|
|
1293
|
+
});
|
|
1294
|
+
return Array.from(expectedTargetIds).filter(targetId => !reportedTargetIds.has(targetId));
|
|
1295
|
+
}
|
|
1225
1296
|
|
|
1297
|
+
private async waitForProtocolV2FirmwareUpdateComplete(
|
|
1298
|
+
targets: Array<{ target_id: number; path: string }>
|
|
1299
|
+
) {
|
|
1300
|
+
const expectedTargetIds = new Set(targets.map(target => target.target_id));
|
|
1226
1301
|
const startTime = Date.now();
|
|
1227
1302
|
let lastError: unknown;
|
|
1303
|
+
let shouldReconnect = true;
|
|
1304
|
+
let deviceInfo: ProtocolV2DeviceInfo | undefined;
|
|
1305
|
+
let missingTargetStatusSince: number | undefined;
|
|
1306
|
+
let missingTargetStatusKey: string | undefined;
|
|
1307
|
+
const resetMissingTargetStatusGrace = () => {
|
|
1308
|
+
missingTargetStatusSince = undefined;
|
|
1309
|
+
missingTargetStatusKey = undefined;
|
|
1310
|
+
};
|
|
1228
1311
|
|
|
1229
1312
|
while (Date.now() - startTime < PROTOCOL_V2_INSTALL_TIMEOUT) {
|
|
1230
1313
|
try {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
return;
|
|
1236
|
-
}
|
|
1237
|
-
} catch (error) {
|
|
1238
|
-
lastError = error;
|
|
1239
|
-
if (error instanceof HardwareError && error.errorCode === HardwareErrorCode.FirmwareError) {
|
|
1240
|
-
throw error;
|
|
1314
|
+
if (shouldReconnect) {
|
|
1315
|
+
await this.reconnectProtocolV2Device();
|
|
1316
|
+
deviceInfo = await this.verifyProtocolV2ReconnectIdentity();
|
|
1317
|
+
shouldReconnect = false;
|
|
1241
1318
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1319
|
+
const currentDeviceInfo = deviceInfo;
|
|
1320
|
+
try {
|
|
1321
|
+
const statusResponse = await this.device.getCommands().typedCall(
|
|
1322
|
+
'DeviceFirmwareUpdateStatusGet',
|
|
1323
|
+
'DeviceFirmwareUpdateStatus',
|
|
1324
|
+
{
|
|
1325
|
+
fields: {
|
|
1326
|
+
status: true,
|
|
1327
|
+
payload_version: true,
|
|
1328
|
+
path: true,
|
|
1329
|
+
},
|
|
1330
|
+
},
|
|
1331
|
+
{ timeoutMs: PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT }
|
|
1332
|
+
);
|
|
1333
|
+
const statusTargets = (statusResponse.message.records ??
|
|
1334
|
+
[]) as ProtocolV2FirmwareUpdateStatusTarget[];
|
|
1335
|
+
if (this.assertProtocolV2TargetStatus(statusTargets, expectedTargetIds)) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
if (
|
|
1340
|
+
statusTargets.length === 0 &&
|
|
1341
|
+
currentDeviceInfo &&
|
|
1342
|
+
(await this.probeProtocolV2NormalMode(currentDeviceInfo))
|
|
1343
|
+
) {
|
|
1344
|
+
Log.log(
|
|
1345
|
+
'[FirmwareUpdateV4] empty firmware status after confirmed App reboot; update complete'
|
|
1346
|
+
);
|
|
1347
|
+
this.postProgressMessage(100, 'installingFirmware');
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
const missingTargetIds = this.getProtocolV2MissingTargetIds(
|
|
1352
|
+
statusTargets,
|
|
1353
|
+
expectedTargetIds
|
|
1354
|
+
);
|
|
1355
|
+
if (missingTargetIds.length > 0) {
|
|
1356
|
+
const now = Date.now();
|
|
1357
|
+
const missingKey = missingTargetIds.join(',');
|
|
1358
|
+
if (missingTargetStatusSince === undefined || missingTargetStatusKey !== missingKey) {
|
|
1359
|
+
missingTargetStatusSince = now;
|
|
1360
|
+
missingTargetStatusKey = missingKey;
|
|
1361
|
+
} else if (
|
|
1362
|
+
now - missingTargetStatusSince >=
|
|
1363
|
+
PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT
|
|
1364
|
+
) {
|
|
1365
|
+
const reportedTargetIds = statusTargets
|
|
1366
|
+
.map(target => normalizeProtocolV2TargetId(target.target_id))
|
|
1367
|
+
.filter((targetId): targetId is number => targetId !== undefined);
|
|
1368
|
+
throw ERRORS.TypedError(
|
|
1369
|
+
HardwareErrorCode.FirmwareError,
|
|
1370
|
+
`Protocol V2 firmware status is missing requested records: targetIds=${missingKey} reportedTargetIds=${reportedTargetIds.join(
|
|
1371
|
+
','
|
|
1372
|
+
)}`
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
lastError = new Error(
|
|
1376
|
+
`Protocol V2 firmware status is temporarily missing targetIds=${missingKey}`
|
|
1377
|
+
);
|
|
1378
|
+
} else {
|
|
1379
|
+
resetMissingTargetStatusGrace();
|
|
1380
|
+
lastError = new Error('Protocol V2 firmware targets are still installing');
|
|
1381
|
+
}
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
if (
|
|
1384
|
+
error instanceof HardwareError &&
|
|
1385
|
+
error.errorCode === HardwareErrorCode.FirmwareError
|
|
1386
|
+
) {
|
|
1387
|
+
throw error;
|
|
1388
|
+
}
|
|
1389
|
+
// Only consecutive full status dumps can prove that a record is absent.
|
|
1390
|
+
// A reboot or transport interruption starts a fresh grace window.
|
|
1391
|
+
resetMissingTargetStatusGrace();
|
|
1392
|
+
// App firmware does not register DeviceFirmwareUpdateStatusGet. Treat the
|
|
1393
|
+
// missing endpoint as completion only after the runtime probe confirms App mode.
|
|
1394
|
+
if (isProtocolV2FirmwareStatusEndpointUnavailable(error)) {
|
|
1395
|
+
if (!currentDeviceInfo) {
|
|
1396
|
+
throw ERRORS.TypedError(
|
|
1397
|
+
HardwareErrorCode.RuntimeError,
|
|
1398
|
+
'Protocol V2 device identity is unavailable during install polling'
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
if (await this.probeProtocolV2NormalMode(currentDeviceInfo)) {
|
|
1402
|
+
Log.log(
|
|
1403
|
+
'[FirmwareUpdateV4] firmware status endpoint unavailable after confirmed App reboot'
|
|
1404
|
+
);
|
|
1405
|
+
this.postProgressMessage(100, 'installingFirmware');
|
|
1247
1406
|
return;
|
|
1248
1407
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1408
|
+
lastError = new Error(
|
|
1409
|
+
'Protocol V2 firmware status endpoint is unavailable while the device remains in loader mode'
|
|
1410
|
+
);
|
|
1411
|
+
} else {
|
|
1412
|
+
shouldReconnect = true;
|
|
1413
|
+
deviceInfo = undefined;
|
|
1414
|
+
lastError = error;
|
|
1251
1415
|
Log.log(
|
|
1252
|
-
'
|
|
1253
|
-
|
|
1416
|
+
'[FirmwareUpdateV4] DeviceFirmwareUpdateStatusGet unavailable during install: ',
|
|
1417
|
+
error
|
|
1254
1418
|
);
|
|
1255
1419
|
}
|
|
1256
|
-
try {
|
|
1257
|
-
await this.pingProtocolV2Device();
|
|
1258
|
-
Log.log('Protocol V2 firmware status unavailable, Ping is ready');
|
|
1259
|
-
} catch (pingError) {
|
|
1260
|
-
lastError = pingError;
|
|
1261
|
-
Log.log('Protocol V2 firmware install Ping polling failed: ', pingError);
|
|
1262
|
-
}
|
|
1263
1420
|
}
|
|
1421
|
+
} catch (error) {
|
|
1422
|
+
lastError = error;
|
|
1423
|
+
if (this.isProtocolV2ReconnectIdentityError(error)) {
|
|
1424
|
+
throw error;
|
|
1425
|
+
}
|
|
1426
|
+
if (error instanceof HardwareError && error.errorCode === HardwareErrorCode.FirmwareError) {
|
|
1427
|
+
throw error;
|
|
1428
|
+
}
|
|
1429
|
+
shouldReconnect = true;
|
|
1430
|
+
deviceInfo = undefined;
|
|
1431
|
+
resetMissingTargetStatusGrace();
|
|
1432
|
+
Log.log('Protocol V2 firmware install device readiness probe failed: ', error);
|
|
1264
1433
|
}
|
|
1265
1434
|
await wait(1000);
|
|
1266
1435
|
}
|
|
1267
1436
|
|
|
1268
1437
|
throw ERRORS.TypedError(
|
|
1269
1438
|
HardwareErrorCode.RuntimeError,
|
|
1270
|
-
`Protocol V2 firmware update status
|
|
1439
|
+
`Protocol V2 firmware update status not complete within ${
|
|
1440
|
+
PROTOCOL_V2_INSTALL_TIMEOUT / 1000
|
|
1441
|
+
}s: ${this.normalizeErrorMessage(lastError)}`
|
|
1271
1442
|
);
|
|
1272
1443
|
}
|
|
1273
1444
|
|
|
1274
1445
|
private async exitProtocolV2BootloaderToNormal() {
|
|
1275
|
-
this.
|
|
1446
|
+
await this.reconnectProtocolV2Device();
|
|
1447
|
+
const deviceInfo = await this.verifyProtocolV2ReconnectIdentity();
|
|
1276
1448
|
try {
|
|
1277
|
-
await this.
|
|
1278
|
-
|
|
1279
|
-
Log.log('Protocol V2 device is already in normal mode, skip normal reboot');
|
|
1449
|
+
if (await this.probeProtocolV2NormalMode(deviceInfo)) {
|
|
1450
|
+
Log.log('[FirmwareUpdateV4] device already returned to App mode; skip Normal reboot');
|
|
1280
1451
|
return;
|
|
1281
1452
|
}
|
|
1282
1453
|
} catch (error) {
|
|
1283
|
-
Log.log('
|
|
1454
|
+
Log.log('[FirmwareUpdateV4] unable to confirm App mode before Normal reboot: ', error);
|
|
1284
1455
|
}
|
|
1285
1456
|
await this.protocolV2Reboot(DeviceRebootType.Normal);
|
|
1286
1457
|
}
|
|
1287
1458
|
|
|
1459
|
+
private async probeProtocolV2NormalMode(deviceInfo: ProtocolV2DeviceInfo) {
|
|
1460
|
+
const features = await this.device.probeProtocolV2RuntimeState(
|
|
1461
|
+
deviceInfo,
|
|
1462
|
+
PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
|
|
1463
|
+
);
|
|
1464
|
+
return features.mode === 'normal' && !features.bootloaderMode;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1288
1467
|
private async waitForProtocolV2FinalFeatures() {
|
|
1289
1468
|
const features = await this.waitForProtocolV2ReconnectAndFeatures(
|
|
1290
|
-
|
|
1469
|
+
PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT
|
|
1291
1470
|
);
|
|
1292
1471
|
|
|
1472
|
+
return this.getProtocolV2VersionResult(features);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
private getProtocolV2VersionResult(features: Features) {
|
|
1293
1476
|
const bootloaderVersion = getDeviceBootloaderVersion(features).join('.');
|
|
1294
1477
|
const bleVersion = getDeviceBLEFirmwareVersion(features).join('.');
|
|
1295
1478
|
const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
|
|
@@ -1309,29 +1492,41 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1309
1492
|
private async waitForProtocolV2ReconnectAndFeatures(timeout: number) {
|
|
1310
1493
|
const startTime = Date.now();
|
|
1311
1494
|
let lastError: unknown;
|
|
1495
|
+
let shouldReconnect = true;
|
|
1312
1496
|
|
|
1313
1497
|
while (Date.now() - startTime < timeout) {
|
|
1314
1498
|
try {
|
|
1315
|
-
|
|
1499
|
+
if (shouldReconnect) {
|
|
1500
|
+
await this.reconnectProtocolV2Device();
|
|
1501
|
+
shouldReconnect = false;
|
|
1502
|
+
}
|
|
1316
1503
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
1317
1504
|
commands: this.device.getCommands(),
|
|
1318
|
-
timeoutMs:
|
|
1319
|
-
//
|
|
1505
|
+
timeoutMs: this.getProtocolV2DeviceInfoTimeout(),
|
|
1506
|
+
// Completion needs target versions only; keep scope aligned with the request.
|
|
1320
1507
|
request: PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
|
|
1321
1508
|
});
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1509
|
+
this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
|
|
1510
|
+
const features = await this.device.probeProtocolV2RuntimeState(
|
|
1511
|
+
deviceInfo,
|
|
1512
|
+
PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
|
|
1513
|
+
);
|
|
1514
|
+
if (features.mode === 'normal' && !features.bootloaderMode) {
|
|
1515
|
+
return features;
|
|
1328
1516
|
}
|
|
1329
|
-
|
|
1517
|
+
lastError = ERRORS.TypedError(
|
|
1518
|
+
HardwareErrorCode.DeviceNotFound,
|
|
1519
|
+
'Protocol V2 device is still in bootloader mode'
|
|
1520
|
+
);
|
|
1330
1521
|
} catch (error) {
|
|
1522
|
+
if (this.isProtocolV2ReconnectIdentityError(error)) {
|
|
1523
|
+
throw error;
|
|
1524
|
+
}
|
|
1525
|
+
shouldReconnect = true;
|
|
1331
1526
|
lastError = error;
|
|
1332
1527
|
Log.log('Protocol V2 normal mode not ready, polling Ping: ', error);
|
|
1333
|
-
await wait(1000);
|
|
1334
1528
|
}
|
|
1529
|
+
await wait(1000);
|
|
1335
1530
|
}
|
|
1336
1531
|
|
|
1337
1532
|
throw ERRORS.TypedError(
|
|
@@ -1355,54 +1550,101 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1355
1550
|
DataManager.isBrowserWebUsb(DataManager.getSettings('env')) &&
|
|
1356
1551
|
devicesDescriptor.length === 1
|
|
1357
1552
|
) {
|
|
1553
|
+
const descriptor = devicesDescriptor[0];
|
|
1554
|
+
if (!this.protocolV2ExpectedSerialNumber && descriptor.path !== this.protocolV2ExpectedPath) {
|
|
1555
|
+
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
|
|
1556
|
+
}
|
|
1358
1557
|
this.device.updateDescriptor(
|
|
1359
1558
|
{
|
|
1360
|
-
...
|
|
1559
|
+
...descriptor,
|
|
1361
1560
|
protocolType: PROTOCOL_V2_CONNECT_PROTOCOL,
|
|
1362
1561
|
},
|
|
1363
1562
|
true
|
|
1364
1563
|
);
|
|
1365
|
-
await this.
|
|
1564
|
+
await this.ensureProtocolV2DeviceAcquired();
|
|
1366
1565
|
this.device.commands.disposed = false;
|
|
1367
1566
|
this.device.getCommands().mainId = this.device.mainId ?? '';
|
|
1368
|
-
await this.device.initialize();
|
|
1369
1567
|
return;
|
|
1370
1568
|
}
|
|
1371
1569
|
|
|
1372
|
-
//
|
|
1373
|
-
//
|
|
1570
|
+
// Reinitialize every USB descriptor so DeviceInfo can provide the physical serial.
|
|
1571
|
+
// Enumeration order is not stable and must never decide the reconnect target.
|
|
1374
1572
|
const { deviceList } = await DevicePool.getDevices(devicesDescriptor, undefined, {
|
|
1375
1573
|
connectProtocol: PROTOCOL_V2_CONNECT_PROTOCOL,
|
|
1376
1574
|
});
|
|
1377
|
-
|
|
1575
|
+
const expectedSerialNumber = this.protocolV2ExpectedSerialNumber?.trim();
|
|
1576
|
+
const expectedPath = this.protocolV2ExpectedPath?.trim();
|
|
1577
|
+
const reconnectDevice = deviceList.find(candidate => {
|
|
1578
|
+
const candidateSerialNumber = candidate.getCurrentSerialNo?.().trim();
|
|
1579
|
+
if (expectedSerialNumber && candidateSerialNumber) {
|
|
1580
|
+
return candidateSerialNumber === expectedSerialNumber;
|
|
1581
|
+
}
|
|
1582
|
+
return !!expectedPath && candidate.getConnectId() === expectedPath;
|
|
1583
|
+
});
|
|
1584
|
+
if (!reconnectDevice) {
|
|
1378
1585
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound);
|
|
1379
1586
|
}
|
|
1380
1587
|
|
|
1381
1588
|
Log.debug(
|
|
1382
|
-
'Protocol V2 firmware reconnect using
|
|
1383
|
-
|
|
1589
|
+
'Protocol V2 firmware reconnect using matched device:',
|
|
1590
|
+
reconnectDevice.getConnectId()
|
|
1384
1591
|
);
|
|
1385
|
-
this.device.updateFromCache(
|
|
1386
|
-
await this.
|
|
1592
|
+
this.device.updateFromCache(reconnectDevice);
|
|
1593
|
+
await this.ensureProtocolV2DeviceAcquired();
|
|
1387
1594
|
this.device.commands.disposed = false;
|
|
1388
1595
|
this.device.getCommands().mainId = this.device.mainId ?? '';
|
|
1389
|
-
await this.device.initialize();
|
|
1390
1596
|
}
|
|
1391
1597
|
|
|
1392
|
-
|
|
1598
|
+
/**
|
|
1599
|
+
* After acquiring a USB session, polling reuses its command channel. Reacquire only
|
|
1600
|
+
* after reboot or enumeration changes cause hasDeviceAcquire() to become false.
|
|
1601
|
+
*/
|
|
1602
|
+
private async ensureProtocolV2DeviceAcquired() {
|
|
1603
|
+
const commands = this.device.getCommands();
|
|
1604
|
+
if (this.device.hasDeviceAcquire() && !commands.disposed) {
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
await this.device.acquire(PROTOCOL_V2_CONNECT_PROTOCOL, {
|
|
1608
|
+
throwOnRunPromiseError: true,
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
private isProtocolV2ReconnectIdentityError(error: unknown) {
|
|
1613
|
+
return this.normalizeErrorMessage(error).includes('Protocol V2 reconnect physical identity');
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
private async protocolV2CommonUpdateProcess(params: ProtocolV2FileTransferParams) {
|
|
1617
|
+
let lastError: unknown;
|
|
1618
|
+
for (let attempt = 1; attempt <= PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT; attempt += 1) {
|
|
1619
|
+
try {
|
|
1620
|
+
return await this.protocolV2WriteWholeFile(params);
|
|
1621
|
+
} catch (error) {
|
|
1622
|
+
lastError = error;
|
|
1623
|
+
Log.error(
|
|
1624
|
+
`Protocol V2 file transfer failed path=${params.filePath} attempt=${attempt}/${PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT}; restarting from offset 0`,
|
|
1625
|
+
error
|
|
1626
|
+
);
|
|
1627
|
+
if (attempt === PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT) {
|
|
1628
|
+
break;
|
|
1629
|
+
}
|
|
1630
|
+
await this.recoverProtocolV2FileTransfer();
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
throw ERRORS.TypedError(
|
|
1635
|
+
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1636
|
+
`transfer data error: ${getProtocolV2UnknownErrorText(lastError)}`
|
|
1637
|
+
);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
private async protocolV2WriteWholeFile({
|
|
1393
1641
|
payload,
|
|
1394
1642
|
filePath,
|
|
1395
1643
|
processedSize,
|
|
1396
1644
|
totalSize,
|
|
1397
1645
|
onTransferredBytes,
|
|
1398
|
-
}:
|
|
1399
|
-
filePath: string;
|
|
1400
|
-
processedSize?: number;
|
|
1401
|
-
totalSize?: number;
|
|
1402
|
-
onTransferredBytes?: (transferredBytes: number) => void;
|
|
1403
|
-
}) {
|
|
1646
|
+
}: ProtocolV2FileTransferParams) {
|
|
1404
1647
|
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
1405
|
-
let offset = 0;
|
|
1406
1648
|
const getUploadProgress = (fileOffset: number) => {
|
|
1407
1649
|
if (totalSize !== undefined && processedSize !== undefined) {
|
|
1408
1650
|
return Math.min(Math.ceil(((processedSize + fileOffset) / totalSize) * 100), 99);
|
|
@@ -1410,39 +1652,43 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1410
1652
|
return Math.min(Math.ceil((fileOffset / payload.byteLength) * 100), 99);
|
|
1411
1653
|
};
|
|
1412
1654
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
progress
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1655
|
+
try {
|
|
1656
|
+
await writeProtocolV2File({
|
|
1657
|
+
commands: this.device.getCommands(),
|
|
1658
|
+
path: filePath,
|
|
1659
|
+
data: payload,
|
|
1660
|
+
totalSize: payload.byteLength,
|
|
1661
|
+
chunkSize,
|
|
1662
|
+
overwrite: true,
|
|
1663
|
+
append: false,
|
|
1664
|
+
writeWithResponse: true,
|
|
1665
|
+
maxChunkRetries: 0,
|
|
1666
|
+
getUiPercentage: ({ offset, chunkLength }) =>
|
|
1667
|
+
getProtocolV2DeviceTransferProgress(
|
|
1668
|
+
(processedSize ?? 0) + offset,
|
|
1669
|
+
(processedSize ?? 0) + offset + chunkLength,
|
|
1670
|
+
totalSize ?? payload.byteLength
|
|
1671
|
+
),
|
|
1672
|
+
onProgress: progress => {
|
|
1673
|
+
const transferredBytes = (processedSize ?? 0) + progress.transferredBytes;
|
|
1674
|
+
onTransferredBytes?.(transferredBytes);
|
|
1675
|
+
this.postProgressMessage(getUploadProgress(progress.transferredBytes), 'transferData', {
|
|
1676
|
+
transferredBytes,
|
|
1677
|
+
totalBytes: totalSize ?? payload.byteLength,
|
|
1678
|
+
rateBytesPerSecond: progress.rateBytesPerSecond,
|
|
1679
|
+
elapsedMs: progress.elapsedMs,
|
|
1680
|
+
});
|
|
1681
|
+
},
|
|
1682
|
+
});
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
if (
|
|
1685
|
+
error instanceof HardwareError &&
|
|
1686
|
+
error.errorCode === HardwareErrorCode.RuntimeError &&
|
|
1687
|
+
error.message.includes('FilesystemFileWrite')
|
|
1688
|
+
) {
|
|
1689
|
+
throw ERRORS.TypedError(HardwareErrorCode.EmmcFileWriteFirmwareError, error.message);
|
|
1442
1690
|
}
|
|
1443
|
-
|
|
1444
|
-
onTransferredBytes?.((processedSize ?? 0) + offset);
|
|
1445
|
-
this.postProgressMessage(getUploadProgress(offset), 'transferData');
|
|
1691
|
+
throw error;
|
|
1446
1692
|
}
|
|
1447
1693
|
|
|
1448
1694
|
return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
|
|
@@ -1462,65 +1708,15 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1462
1708
|
return env ?? 'unknown';
|
|
1463
1709
|
}
|
|
1464
1710
|
|
|
1465
|
-
private async
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
chunk: ArrayBuffer | Buffer,
|
|
1470
|
-
overwrite: boolean,
|
|
1471
|
-
progress: number | null
|
|
1472
|
-
): Promise<TypedResponseMessage<'FilesystemFile'>> {
|
|
1473
|
-
const writeFunc = async () => {
|
|
1474
|
-
const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
|
|
1475
|
-
const writeRes = await typedCall('FilesystemFileWrite', 'FilesystemFile', {
|
|
1476
|
-
file: {
|
|
1477
|
-
path: filePath,
|
|
1478
|
-
offset,
|
|
1479
|
-
total_size: totalFileSize,
|
|
1480
|
-
data: chunk,
|
|
1481
|
-
},
|
|
1482
|
-
overwrite,
|
|
1483
|
-
append: false,
|
|
1484
|
-
ui_percentage: progress ?? undefined,
|
|
1485
|
-
});
|
|
1486
|
-
if (writeRes.type !== 'FilesystemFile') {
|
|
1487
|
-
if ((writeRes as any).type === 'CallMethodError') {
|
|
1488
|
-
if (((writeRes as any).message.error ?? '').indexOf(SESSION_ERROR) > -1) {
|
|
1489
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, SESSION_ERROR);
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
throw ERRORS.TypedError(
|
|
1493
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1494
|
-
'transfer data error'
|
|
1495
|
-
);
|
|
1496
|
-
}
|
|
1497
|
-
return writeRes;
|
|
1498
|
-
};
|
|
1499
|
-
|
|
1500
|
-
let retryCount = 10;
|
|
1501
|
-
while (retryCount > 0) {
|
|
1502
|
-
try {
|
|
1503
|
-
const result = await writeFunc();
|
|
1504
|
-
return result;
|
|
1505
|
-
} catch (error) {
|
|
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
|
-
}
|
|
1711
|
+
private async recoverProtocolV2FileTransfer() {
|
|
1712
|
+
const env = DataManager.getSettings('env');
|
|
1713
|
+
if (DataManager.isBleConnect(env)) {
|
|
1714
|
+
await wait(3000);
|
|
1522
1715
|
}
|
|
1523
|
-
|
|
1716
|
+
await this.reconnectProtocolV2Device();
|
|
1717
|
+
await this.verifyProtocolV2ReconnectIdentity();
|
|
1718
|
+
await this.device.initialize();
|
|
1719
|
+
await wait(2000);
|
|
1524
1720
|
}
|
|
1525
1721
|
|
|
1526
1722
|
private async acquireProtocolV2BleDevice() {
|
|
@@ -1538,35 +1734,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1538
1734
|
targets: Array<{ target_id: number; path: string }>;
|
|
1539
1735
|
}) {
|
|
1540
1736
|
const commands = this.device.getCommands();
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
{
|
|
1550
|
-
intermediateTypes: ['DeviceFirmwareUpdateStatus'],
|
|
1551
|
-
timeoutMs: PROTOCOL_V2_START_UPDATE_TIMEOUT,
|
|
1552
|
-
onIntermediateResponse: (response: { type?: string }) => {
|
|
1553
|
-
if (response.type === 'DeviceFirmwareUpdateStatus') {
|
|
1554
|
-
this.postProgressMessage(99, 'installingFirmware');
|
|
1555
|
-
}
|
|
1556
|
-
},
|
|
1557
|
-
}
|
|
1558
|
-
);
|
|
1559
|
-
} catch (error) {
|
|
1560
|
-
if (isProtocolV2StartUpdateTransientError(error)) {
|
|
1561
|
-
Log.log(
|
|
1562
|
-
'Protocol V2 firmware update request did not return; continue status polling',
|
|
1563
|
-
error
|
|
1564
|
-
);
|
|
1565
|
-
} else {
|
|
1566
|
-
throw error;
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1737
|
+
const response: ProtocolV2FirmwareUpdateStartResponse = await commands.typedCall(
|
|
1738
|
+
'DeviceFirmwareUpdateRequest',
|
|
1739
|
+
'Success',
|
|
1740
|
+
{ targets },
|
|
1741
|
+
{ timeoutMs: PROTOCOL_V2_START_UPDATE_TIMEOUT }
|
|
1742
|
+
);
|
|
1743
|
+
// Success acknowledges that the device accepted installation. End confirmation
|
|
1744
|
+
// and begin status polling only after receiving this ACK.
|
|
1569
1745
|
this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdating);
|
|
1746
|
+
this.postProgressMessage(0, 'installingFirmware');
|
|
1570
1747
|
return response;
|
|
1571
1748
|
}
|
|
1572
1749
|
|
|
@@ -1576,9 +1753,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1576
1753
|
const res = await typedCall('DeviceReboot', 'Success', {
|
|
1577
1754
|
reboot_type: rebootType,
|
|
1578
1755
|
});
|
|
1756
|
+
this.device.markProtocolV2Reboot(rebootType);
|
|
1579
1757
|
return res.message;
|
|
1580
1758
|
} catch (error) {
|
|
1581
1759
|
if (isProtocolV2DeviceDisconnectedError(error) || isProtocolV2ReconnectProbeError(error)) {
|
|
1760
|
+
this.device.markProtocolV2Reboot(rebootType);
|
|
1582
1761
|
return { message: 'Device rebooted successfully' };
|
|
1583
1762
|
}
|
|
1584
1763
|
throw error;
|