@onekeyfe/hd-core 1.2.0-alpha.50 → 1.2.0-alpha.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
  2. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  3. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +3 -111
  4. package/__tests__/connectSettings.test.ts +47 -5
  5. package/__tests__/device-initialize-timeout.test.ts +56 -0
  6. package/__tests__/device-lifecycle-events.test.ts +3 -105
  7. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  8. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  9. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  10. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  11. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +200 -0
  12. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  13. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +294 -0
  14. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  15. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  16. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  17. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  18. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  19. package/__tests__/get-device-state.test.ts +12 -132
  20. package/__tests__/homescreen.test.ts +1 -41
  21. package/__tests__/logBlockEvent.test.ts +1 -1
  22. package/__tests__/method-protocol-support.test.ts +0 -19
  23. package/__tests__/open-wallet-session.test.ts +33 -446
  24. package/__tests__/protocol-v2-unlock-policy.test.ts +35 -196
  25. package/__tests__/protocol-v2.test.ts +1032 -1056
  26. package/__tests__/protocolV2UiInteraction.test.ts +0 -63
  27. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  28. package/__tests__/search-devices.test.ts +3 -12
  29. package/dist/api/BaseMethod.d.ts +1 -3
  30. package/dist/api/BaseMethod.d.ts.map +1 -1
  31. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  32. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  33. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  34. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  35. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  36. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  37. package/dist/api/FirmwareUpdateV4.d.ts +25 -9
  38. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  39. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  40. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  41. package/dist/api/SearchDevices.d.ts.map +1 -1
  42. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  43. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  44. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  45. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  46. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  47. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  48. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  49. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  50. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  51. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +9 -0
  52. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  53. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  54. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  55. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  56. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  57. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +32 -0
  58. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  59. package/dist/api/firmware/getBinary.d.ts +7 -0
  60. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  61. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  62. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  63. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  64. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  65. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  66. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  67. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
  68. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  69. package/dist/api/index.d.ts +0 -2
  70. package/dist/api/index.d.ts.map +1 -1
  71. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  72. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  73. package/dist/core/deviceEventRegistration.d.ts +0 -2
  74. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  75. package/dist/core/index.d.ts.map +1 -1
  76. package/dist/data-manager/DataManager.d.ts +2 -4
  77. package/dist/data-manager/DataManager.d.ts.map +1 -1
  78. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  79. package/dist/device/Device.d.ts +6 -29
  80. package/dist/device/Device.d.ts.map +1 -1
  81. package/dist/device/DeviceCommands.d.ts +4 -4
  82. package/dist/device/DevicePool.d.ts.map +1 -1
  83. package/dist/events/device.d.ts +0 -4
  84. package/dist/events/device.d.ts.map +1 -1
  85. package/dist/events/logBlockEvent.d.ts.map +1 -1
  86. package/dist/events/ui-promise.d.ts +2 -4
  87. package/dist/events/ui-promise.d.ts.map +1 -1
  88. package/dist/events/ui-request.d.ts +2 -31
  89. package/dist/events/ui-request.d.ts.map +1 -1
  90. package/dist/events/ui-response.d.ts +2 -10
  91. package/dist/events/ui-response.d.ts.map +1 -1
  92. package/dist/index.d.ts +230 -203
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +3469 -2419
  95. package/dist/inject.d.ts +1 -6
  96. package/dist/inject.d.ts.map +1 -1
  97. package/dist/lowLevelInject.d.ts.map +1 -1
  98. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  99. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  100. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  101. package/dist/protocols/protocol-v2/uiInteraction.d.ts +4 -7
  102. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  103. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  104. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  105. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  106. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  107. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -4
  108. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  109. package/dist/topLevelInject.d.ts.map +1 -1
  110. package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -1
  111. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  112. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  113. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  114. package/dist/types/api/export.d.ts +4 -1
  115. package/dist/types/api/export.d.ts.map +1 -1
  116. package/dist/types/api/firmwareUpdate.d.ts +70 -2
  117. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  118. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  119. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  120. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  121. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  122. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  123. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  124. package/dist/types/api/index.d.ts +10 -7
  125. package/dist/types/api/index.d.ts.map +1 -1
  126. package/dist/types/api/protocolV2.d.ts +0 -3
  127. package/dist/types/api/protocolV2.d.ts.map +1 -1
  128. package/dist/types/params.d.ts +0 -1
  129. package/dist/types/params.d.ts.map +1 -1
  130. package/dist/types/settings.d.ts +13 -22
  131. package/dist/types/settings.d.ts.map +1 -1
  132. package/dist/utils/deviceFeaturesCompat.d.ts +1 -0
  133. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  134. package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
  135. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  136. package/dist/utils/homescreen.d.ts +0 -4
  137. package/dist/utils/homescreen.d.ts.map +1 -1
  138. package/dist/utils/index.d.ts +1 -1
  139. package/dist/utils/index.d.ts.map +1 -1
  140. package/dist/utils/patch.d.ts +1 -1
  141. package/dist/utils/patch.d.ts.map +1 -1
  142. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  143. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  144. package/package.json +4 -4
  145. package/src/api/BaseMethod.ts +10 -8
  146. package/src/api/CheckAllFirmwareRelease.ts +53 -41
  147. package/src/api/FirmwareUpdate.ts +15 -7
  148. package/src/api/FirmwareUpdateV2.ts +316 -126
  149. package/src/api/FirmwareUpdateV3.ts +265 -63
  150. package/src/api/FirmwareUpdateV4.ts +937 -430
  151. package/src/api/GetPassphraseState.ts +1 -7
  152. package/src/api/OpenWalletSession.ts +17 -54
  153. package/src/api/SearchDevices.ts +1 -3
  154. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
  155. package/src/api/device/DeviceUnlock.ts +1 -1
  156. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  157. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  158. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  159. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  160. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +83 -16
  161. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  162. package/src/api/firmware/FirmwareUpdatePlan.ts +772 -0
  163. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +415 -0
  164. package/src/api/firmware/progressThrottle.ts +44 -0
  165. package/src/api/firmware/updateBootloader.ts +19 -4
  166. package/src/api/firmware/uploadFirmware.ts +144 -39
  167. package/src/api/helpers/protocolV2FileWrite.ts +4 -11
  168. package/src/api/index.ts +0 -2
  169. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  170. package/src/core/deviceEventRegistration.ts +0 -4
  171. package/src/core/index.ts +83 -167
  172. package/src/data/messages/messages-protocol-v2.json +0 -25
  173. package/src/data-manager/DataManager.ts +38 -67
  174. package/src/data-manager/connectSettings.ts +11 -0
  175. package/src/device/Device.ts +42 -257
  176. package/src/device/DevicePool.ts +2 -7
  177. package/src/events/device.ts +0 -4
  178. package/src/events/logBlockEvent.ts +0 -1
  179. package/src/events/ui-promise.ts +2 -4
  180. package/src/events/ui-request.ts +2 -36
  181. package/src/events/ui-response.ts +2 -12
  182. package/src/index.ts +5 -0
  183. package/src/inject.ts +24 -60
  184. package/src/lowLevelInject.ts +8 -7
  185. package/src/protocols/protocol-v2/features.ts +2 -9
  186. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  187. package/src/protocols/protocol-v2/uiInteraction.ts +6 -46
  188. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  189. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  190. package/src/protocols/protocol-v2/walletSession.ts +30 -169
  191. package/src/topLevelInject.ts +8 -7
  192. package/src/types/api/checkAllFirmwareRelease.ts +4 -1
  193. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  194. package/src/types/api/export.ts +18 -0
  195. package/src/types/api/firmwareUpdate.ts +76 -3
  196. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  197. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  198. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  199. package/src/types/api/index.ts +14 -13
  200. package/src/types/api/protocolV2.ts +0 -13
  201. package/src/types/params.ts +1 -7
  202. package/src/types/settings.ts +13 -42
  203. package/src/utils/deviceFeaturesCompat.ts +6 -0
  204. package/src/utils/deviceFeaturesUtils.ts +0 -4
  205. package/src/utils/homescreen.ts +6 -32
  206. package/src/utils/index.ts +1 -6
  207. package/src/utils/pro2Wallpaper.ts +8 -35
  208. package/__tests__/deviceUploadNft.test.ts +0 -293
  209. package/__tests__/pro2Nft.test.ts +0 -108
  210. package/__tests__/protocol-binding.test.ts +0 -89
  211. package/__tests__/protocol-v2-resources.test.ts +0 -284
  212. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -91
  213. package/__tests__/uiProgressThrottle.test.ts +0 -74
  214. package/__tests__/uiPromiseRegistry.test.ts +0 -86
  215. package/dist/api/DetectDeviceConnectProtocol.d.ts +0 -7
  216. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +0 -1
  217. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -31
  218. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  219. package/dist/core/uiPromiseRegistry.d.ts +0 -4
  220. package/dist/core/uiPromiseRegistry.d.ts.map +0 -1
  221. package/dist/protocols/protocol-v2/resources.d.ts +0 -30
  222. package/dist/protocols/protocol-v2/resources.d.ts.map +0 -1
  223. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  224. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  225. package/dist/types/api/detectDeviceConnectProtocol.d.ts +0 -4
  226. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +0 -1
  227. package/dist/utils/pro2Nft.d.ts +0 -31
  228. package/dist/utils/pro2Nft.d.ts.map +0 -1
  229. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  230. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  231. package/src/api/DetectDeviceConnectProtocol.ts +0 -18
  232. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -189
  233. package/src/core/uiPromiseRegistry.ts +0 -41
  234. package/src/protocols/protocol-v2/resources.ts +0 -359
  235. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -124
  236. package/src/types/api/detectDeviceConnectProtocol.ts +0 -7
  237. package/src/utils/pro2Nft.ts +0 -142
  238. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -0,0 +1,100 @@
1
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ import type { FirmwareUpdateHostBinding } from '../../types/api/firmwareUpdate';
4
+
5
+ const bindingError = (message: string): never => {
6
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, message, {
7
+ firmwareUpdateCode: 'FirmwareArtifactReaderInvalid',
8
+ });
9
+ };
10
+
11
+ class FirmwareHostBindingRegistry {
12
+ private generation = 0;
13
+
14
+ private binding?: FirmwareUpdateHostBinding;
15
+
16
+ register(binding: FirmwareUpdateHostBinding): number {
17
+ if (
18
+ !binding ||
19
+ typeof binding.artifactReader?.open !== 'function' ||
20
+ typeof binding.artifactReader.read !== 'function' ||
21
+ typeof binding.artifactReader.close !== 'function'
22
+ ) {
23
+ return bindingError('Firmware host binding is invalid');
24
+ }
25
+ this.generation += 1;
26
+ this.binding = binding;
27
+ return this.generation;
28
+ }
29
+
30
+ unregister(generation?: number): boolean {
31
+ if (generation !== undefined && generation !== this.generation) {
32
+ return false;
33
+ }
34
+ this.generation += 1;
35
+ this.binding = undefined;
36
+ return true;
37
+ }
38
+
39
+ getGeneration(): number {
40
+ return this.generation;
41
+ }
42
+
43
+ resolve(generation: number): FirmwareUpdateHostBinding {
44
+ if (
45
+ !Number.isSafeInteger(generation) ||
46
+ generation <= 0 ||
47
+ generation !== this.generation ||
48
+ !this.binding
49
+ ) {
50
+ return bindingError(`Firmware host binding generation ${generation} is stale`);
51
+ }
52
+ const { binding } = this;
53
+ const assertCurrent = () => {
54
+ if (generation !== this.generation || binding !== this.binding) {
55
+ bindingError(`Firmware host binding generation ${generation} is stale`);
56
+ }
57
+ };
58
+ return {
59
+ artifactReader: {
60
+ open: async input => {
61
+ assertCurrent();
62
+ const opened = await binding.artifactReader.open(input);
63
+ try {
64
+ assertCurrent();
65
+ } catch (error) {
66
+ if (opened?.readerId) {
67
+ await binding.artifactReader
68
+ .close({ readerId: opened.readerId })
69
+ .catch(() => undefined);
70
+ }
71
+ throw error;
72
+ }
73
+ return opened;
74
+ },
75
+ read: async input => {
76
+ assertCurrent();
77
+ const result = await binding.artifactReader.read(input);
78
+ assertCurrent();
79
+ return result;
80
+ },
81
+ close: input => binding.artifactReader.close(input),
82
+ },
83
+ };
84
+ }
85
+ }
86
+
87
+ const firmwareHostBindingRegistry = new FirmwareHostBindingRegistry();
88
+
89
+ export const registerFirmwareUpdateHostBinding = (binding: FirmwareUpdateHostBinding): number =>
90
+ firmwareHostBindingRegistry.register(binding);
91
+
92
+ export const unregisterFirmwareUpdateHostBinding = (generation?: number): boolean =>
93
+ firmwareHostBindingRegistry.unregister(generation);
94
+
95
+ export const getFirmwareUpdateHostBindingGeneration = (): number =>
96
+ firmwareHostBindingRegistry.getGeneration();
97
+
98
+ export const resolveFirmwareUpdateHostBinding = (
99
+ generation: number | undefined
100
+ ): FirmwareUpdateHostBinding => firmwareHostBindingRegistry.resolve(generation ?? Number.NaN);
@@ -0,0 +1,12 @@
1
+ import { ERRORS, HardwareError, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ export const normalizeFirmwarePreparationError = (error: unknown) => {
4
+ if (error instanceof HardwareError && error.params?.firmwareUpdateCode) {
5
+ return error;
6
+ }
7
+
8
+ return ERRORS.TypedError(
9
+ HardwareErrorCode.FirmwareUpdateDownloadFailed,
10
+ error instanceof Error ? error.message : String(error)
11
+ );
12
+ };
@@ -13,6 +13,8 @@ import { DeviceModelToTypes } from '../../types';
13
13
  import { DataManager } from '../../data-manager';
14
14
  import { BaseMethod } from '../BaseMethod';
15
15
  import { DEVICE } from '../../events';
16
+ import { createFirmwareProgressThrottle } from './progressThrottle';
17
+ import { writeFirmwareByteSource } from './FirmwareArtifactSource';
16
18
 
17
19
  import type {
18
20
  IFirmwareUpdateProgressType,
@@ -23,11 +25,22 @@ import type { RebootType } from '@onekeyfe/hd-transport';
23
25
  import type { Deferred } from '@onekeyfe/hd-shared';
24
26
  import type { KnownDevice } from '../../types';
25
27
  import type { TypedResponseMessage } from '../../device/DeviceCommands';
28
+ import type { FirmwareByteSource } from './FirmwareArtifactSource';
26
29
 
27
30
  const Log = getLogger(LoggerNames.Method);
28
31
  const SESSION_ERROR = 'session not found';
29
32
  const FIRMWARE_UPDATE_CONFIRM = 'Firmware install confirmed';
30
33
 
34
+ /**
35
+ * Response timeout for each Initialize probe while polling a rebooting device over BLE.
36
+ * Overlap safety comes from the poll's in-flight guard, not from this value. Keep it
37
+ * well below the 30s reboot budget so several attempts fit: a probe written into the
38
+ * dying pre-reboot connection is never answered, and its timeout tears that stale link
39
+ * down so the next tick reconnects fresh. Raise it only if a device model is proven to
40
+ * answer bootloader Initialize slower than this on a fresh connection.
41
+ */
42
+ export const BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS = 5000;
43
+
31
44
  const isDeviceDisconnectedError = (error: unknown) => {
32
45
  const message = error instanceof Error ? error.message : String(error ?? '');
33
46
  return (
@@ -40,6 +53,8 @@ const isDeviceDisconnectedError = (error: unknown) => {
40
53
  export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
41
54
  checkPromise: Deferred<any> | null = null;
42
55
 
56
+ private shouldPostFirmwareProgress = createFirmwareProgressThrottle();
57
+
43
58
  init(): void {}
44
59
 
45
60
  run(): Promise<any> {
@@ -83,6 +98,10 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
83
98
  * @param progress Post the percentage of the progress
84
99
  */
85
100
  postProgressMessage = (progress: number, progressType: IFirmwareUpdateProgressType) => {
101
+ if (!this.shouldPostFirmwareProgress(progress, progressType)) {
102
+ return;
103
+ }
104
+
86
105
  this.postMessage(
87
106
  createUiMessage(UI_REQUEST.FIRMWARE_PROGRESS, {
88
107
  device: this.device.toMessageObject() as KnownDevice,
@@ -132,6 +151,10 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
132
151
  this.checkPromise = createDeferred();
133
152
  const env = DataManager.getSettings('env');
134
153
  const isBleReconnect = connectId && DataManager.isBleConnect(env);
154
+ // Tracks the in-flight BLE probe so interval ticks never overlap: a superseded
155
+ // Initialize left pending on the V1 transport is exactly what later times out
156
+ // and used to tear down the connection mid-firmware-upload.
157
+ let bleProbeInFlight = false;
135
158
 
136
159
  Log.log('FirmwareUpdateBaseMethod [checkDeviceToBootloader] isBleReconnect: ', isBleReconnect);
137
160
 
@@ -187,14 +210,18 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
187
210
  }
188
211
 
189
212
  if (isBleReconnect) {
213
+ if (bleProbeInFlight) return;
214
+ bleProbeInFlight = true;
190
215
  try {
191
216
  await this.device.deviceConnector?.acquire(
192
217
  this.device.originalDescriptor.id,
193
218
  null,
194
- true,
195
- this.payload.connectProtocol ?? this.device.originalDescriptor.protocolType
219
+ true
196
220
  );
197
- await this.device.initialize();
221
+ // Bound each probe so a request the rebooting device never received
222
+ // frees the slot for the next tick instead of hanging into the
223
+ // 30s reboot budget.
224
+ await this.device.initialize({ timeoutMs: BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS });
198
225
  if (this.device.isBootloader()) {
199
226
  clearInterval(intervalTimer);
200
227
  this.checkPromise?.resolve(true);
@@ -202,6 +229,8 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
202
229
  } catch (e) {
203
230
  // ignore error because of device is not connected
204
231
  Log.log('catch Bluetooth error when device is restarting: ', e);
232
+ } finally {
233
+ bleProbeInFlight = false;
205
234
  }
206
235
  } else {
207
236
  await this._checkDeviceInBootloaderMode(connectId, intervalTimer, timeoutTimer);
@@ -226,9 +255,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
226
255
  ) {
227
256
  const deviceDiff = await this.device.deviceConnector?.enumerate();
228
257
  const devicesDescriptor = deviceDiff?.descriptors ?? [];
229
- const { deviceList } = await DevicePool.getDevices(devicesDescriptor, connectId, {
230
- connectProtocol: this.payload.connectProtocol ?? this.device.originalDescriptor.protocolType,
231
- });
258
+ const { deviceList } = await DevicePool.getDevices(devicesDescriptor, connectId);
232
259
 
233
260
  if (deviceList.length === 1 && deviceList[0]?.isBootloader()) {
234
261
  // should update current device from cache
@@ -383,6 +410,54 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
383
410
  return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
384
411
  }
385
412
 
413
+ async emmcCommonUpdateProcessFromSource({
414
+ source,
415
+ filePath,
416
+ processedSize,
417
+ totalSize,
418
+ }: {
419
+ source: FirmwareByteSource;
420
+ filePath: string;
421
+ processedSize?: number;
422
+ totalSize?: number;
423
+ }) {
424
+ if (!filePath.startsWith('0:')) {
425
+ throw new Error('filePath must start with 0:');
426
+ }
427
+ const env = DataManager.getSettings('env');
428
+ const chunkSize = 1024 * (DataManager.isBleConnect(env) ? 16 : 128);
429
+
430
+ await writeFirmwareByteSource({
431
+ source,
432
+ chunkSize,
433
+ write: async ({ data, sourceOffset, length, first }) => {
434
+ const progress =
435
+ totalSize !== undefined && processedSize !== undefined
436
+ ? Math.min(Math.ceil(((processedSize + sourceOffset + length) / totalSize) * 100), 99)
437
+ : Math.min(Math.ceil(((sourceOffset + length) / source.size) * 100), 99);
438
+ const writeRes = await this.emmcFileWriteWithRetry(
439
+ filePath,
440
+ length,
441
+ sourceOffset,
442
+ data,
443
+ first,
444
+ progress
445
+ );
446
+ if (!writeRes) {
447
+ throw ERRORS.TypedError(
448
+ HardwareErrorCode.EmmcFileWriteFirmwareError,
449
+ 'transfer data error'
450
+ );
451
+ }
452
+ const processedBytes = Number(writeRes.message.processed_byte);
453
+ this.postProgressMessage(progress, 'transferData');
454
+ return Number.isFinite(processedBytes) ? processedBytes : length;
455
+ },
456
+ });
457
+
458
+ return totalSize !== undefined ? (processedSize ?? 0) + source.size : 0;
459
+ }
460
+
386
461
  async emmcFileWriteWithRetry(
387
462
  filePath: string,
388
463
  chunkLength: number,
@@ -437,12 +512,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
437
512
  const env = DataManager.getSettings('env');
438
513
  if (DataManager.isBleConnect(env)) {
439
514
  await wait(3000);
440
- await this.device.deviceConnector?.acquire(
441
- this.device.originalDescriptor.id,
442
- null,
443
- true,
444
- this.payload.connectProtocol ?? this.device.originalDescriptor.protocolType
445
- );
515
+ await this.device.deviceConnector?.acquire(this.device.originalDescriptor.id, null, true);
446
516
  await this.device.initialize();
447
517
  } else if (
448
518
  error?.message?.indexOf(SESSION_ERROR) > -1 ||
@@ -450,10 +520,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
450
520
  ) {
451
521
  const deviceDiff = await this.device.deviceConnector?.enumerate();
452
522
  const devicesDescriptor = deviceDiff?.descriptors ?? [];
453
- const { deviceList } = await DevicePool.getDevices(devicesDescriptor, undefined, {
454
- connectProtocol:
455
- this.payload.connectProtocol ?? this.device.originalDescriptor.protocolType,
456
- });
523
+ const { deviceList } = await DevicePool.getDevices(devicesDescriptor, undefined);
457
524
  if (deviceList.length === 1 && deviceList[0]?.isBootloader()) {
458
525
  this.device.updateFromCache(deviceList[0]);
459
526
  await this.device.acquire();
@@ -0,0 +1,9 @@
1
+ import type { FirmwareUpdateCapabilities } from '../../types/api/firmwareUpdateCapabilities';
2
+
3
+ export const getFirmwareUpdateCapabilities = (): FirmwareUpdateCapabilities => ({
4
+ planSchemaVersion: 2,
5
+ preparedPlanSchemaVersion: 2,
6
+ hostBindingProtocolVersion: 2,
7
+ manifestModes: ['external-only', 'sdk-managed'],
8
+ supportsArtifactReader: true,
9
+ });