@onekeyfe/hd-core 1.2.0-alpha.160 → 1.2.0-alpha.161

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 (45) hide show
  1. package/__tests__/device-lifecycle-events.test.ts +0 -2
  2. package/__tests__/device-state-events.test.ts +2 -2
  3. package/__tests__/device-state-mapper.test.ts +2 -11
  4. package/__tests__/device-utils.test.ts +0 -6
  5. package/__tests__/firmware-memory-host.test.ts +126 -0
  6. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +3 -13
  7. package/__tests__/protocol-v2-resources.test.ts +2 -35
  8. package/__tests__/protocol-v2.test.ts +42 -89
  9. package/__tests__/search-devices.test.ts +3 -4
  10. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  11. package/dist/api/FirmwareUpdateV4.d.ts +1 -3
  12. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  13. package/dist/api/firmware/FirmwareMemoryHost.d.ts +22 -0
  14. package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +1 -0
  15. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +15 -0
  16. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
  17. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
  18. package/dist/core/index.d.ts.map +1 -1
  19. package/dist/device/Device.d.ts.map +1 -1
  20. package/dist/device/DeviceCommands.d.ts.map +1 -1
  21. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  22. package/dist/index.d.ts +22 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +299 -109
  25. package/dist/protocols/protocol-v2/resources.d.ts +0 -1
  26. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  27. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  28. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  29. package/package.json +4 -4
  30. package/src/api/FirmwareUpdateV3.ts +0 -1
  31. package/src/api/FirmwareUpdateV4.ts +179 -75
  32. package/src/api/SearchDevices.ts +2 -2
  33. package/src/api/firmware/FirmwareMemoryHost.ts +143 -0
  34. package/src/api/firmware/FirmwareUpdatePlan.ts +41 -0
  35. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +6 -10
  36. package/src/core/index.ts +97 -7
  37. package/src/device/Device.ts +1 -3
  38. package/src/device/DeviceCommands.ts +1 -7
  39. package/src/device/DeviceStateMapper.ts +2 -2
  40. package/src/deviceProfile/buildDeviceFeatures.ts +2 -7
  41. package/src/index.ts +6 -0
  42. package/src/protocols/protocol-v2/resources.ts +12 -16
  43. package/src/types/api/firmwareUpdate.ts +1 -1
  44. package/src/utils/deviceFeaturesCompat.ts +4 -9
  45. package/src/utils/deviceInfoUtils.ts +1 -3
package/dist/index.js CHANGED
@@ -419,8 +419,7 @@ const resolveDeviceBleName = (features) => {
419
419
  if (!features)
420
420
  return null;
421
421
  const compatible = asCompatibleFeatures(features);
422
- const bleName = (_a = firstNonEmptyString(compatible.bleName, compatible.onekey_ble_name, compatible.ble_name)) !== null && _a !== void 0 ? _a : null;
423
- return bleName ? hdShared.canonicalizePro2BleAdvertisementName(bleName) : null;
422
+ return ((_a = firstNonEmptyString(compatible.bleName, compatible.onekey_ble_name, compatible.ble_name)) !== null && _a !== void 0 ? _a : null);
424
423
  };
425
424
  const resolveDeviceFirmwareVersion = (features) => {
426
425
  var _a;
@@ -468,7 +467,7 @@ const getDeviceTypeByBleName = (name) => {
468
467
  if (/^Touch/i.test(name))
469
468
  return hdShared.EDeviceType.Touch;
470
469
  const compactName = name.replace(/[\s-]/g, '');
471
- if (/\bPro\s*2\b/i.test(name) || /^(?:OneKey)?Pro2[a-f0-9]{4}$/i.test(compactName)) {
470
+ if (/\bPro\s*2\b/i.test(name) || /^Pro2/i.test(name) || /^(?:OneKey)?Pro2/i.test(compactName)) {
472
471
  return hdShared.EDeviceType.Pro2;
473
472
  }
474
473
  if (/\bNeo\b/i.test(name) || /^Neo/i.test(name) || /^(?:OneKey)?Neo/i.test(compactName)) {
@@ -930,6 +929,22 @@ const finalizeFirmwareUpdatePlan = ({ features, firmwareType, platform, artifact
930
929
  };
931
930
  return assertFirmwareUpdatePlan(Object.assign(Object.assign({}, planWithoutDigest), { planDigest: digestFirmwareUpdatePlan(planWithoutDigest) }));
932
931
  };
932
+ const buildProtocolV2LocalFirmwareUpdatePlan = ({ features, firmwareType, platform, artifacts, }) => {
933
+ if (artifacts.length === 0) {
934
+ return planError('Protocol V2 local firmware plan has no artifacts');
935
+ }
936
+ const plan = finalizeFirmwareUpdatePlan({
937
+ features,
938
+ firmwareType,
939
+ platform,
940
+ artifacts: artifacts.map(artifact => (Object.assign(Object.assign({}, artifact), { role: artifact.target === 'resource' ? 'resourceBundle' : 'component', url: `https://local-firmware.invalid/${encodeURIComponent(artifact.artifactId)}` }))),
941
+ targetsToUpdate: artifacts.map(artifact => artifact.target),
942
+ });
943
+ if (plan.executor !== 'v4') {
944
+ return planError('Protocol V2 local firmware plan requires executor v4');
945
+ }
946
+ return plan;
947
+ };
933
948
  const buildProtocolV2FirmwareUpdatePlan = ({ features, firmwareType, platform, release, targetsToUpdate, forceUpdateTargets, resourceArchive, }) => {
934
949
  const validatedForceTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
935
950
  if (validatedForceTargets.some(target => target === 'ble' || target === 'bootloader')) {
@@ -1120,10 +1135,6 @@ const getFirmwareUpdateResourceName = (value) => {
1120
1135
  }
1121
1136
  return resourceName;
1122
1137
  };
1123
- const getPreparedEntryIdentity = (entryName) => {
1124
- getFirmwareUpdateResourceName(entryName);
1125
- return entryName.toLowerCase();
1126
- };
1127
1138
  const assertPreparedEntry = (value) => {
1128
1139
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
1129
1140
  return preparedPlanError('Firmware prepared plan entry must be an object');
@@ -1176,8 +1187,7 @@ const assertPreparedArtifacts = ({ plan, artifacts, }) => {
1176
1187
  return preparedPlanError('Firmware prepared plan materialization is incomplete');
1177
1188
  }
1178
1189
  if (materializedEntries &&
1179
- new Set(materializedEntries.map(entry => getPreparedEntryIdentity(entry.entryName))).size !==
1180
- materializedEntries.length) {
1190
+ new Set(materializedEntries.map(entry => getFirmwareUpdateResourceName(entry.entryName).toLowerCase())).size !== materializedEntries.length) {
1181
1191
  return preparedPlanError('Firmware prepared plan contains duplicate entry names');
1182
1192
  }
1183
1193
  return Object.assign(Object.assign(Object.assign(Object.assign({ artifactId: planArtifact.artifactId, role: planArtifact.role, target: planArtifact.target, container: planArtifact.container }, (planArtifact.logicalName ? { logicalName: planArtifact.logicalName } : {})), (planArtifact.targetVersion ? { targetVersion: planArtifact.targetVersion } : {})), { artifact: Object.assign(Object.assign({}, artifact), { sha256: artifact.sha256.toLowerCase() }) }), ((materializedEntries === null || materializedEntries === void 0 ? void 0 : materializedEntries.length) ? { materializedEntries } : {}));
@@ -1283,7 +1293,7 @@ const validateFirmwareUpdatePreparedPlan = (value) => {
1283
1293
  assertFirmwareArtifactReference(artifact.artifact);
1284
1294
  const materializedEntryNames = (_d = (_c = artifact.materializedEntries) === null || _c === void 0 ? void 0 : _c.map(entry => {
1285
1295
  assertPreparedEntry(entry);
1286
- return getPreparedEntryIdentity(entry.entryName);
1296
+ return getFirmwareUpdateResourceName(entry.entryName).toLowerCase();
1287
1297
  })) !== null && _d !== void 0 ? _d : [];
1288
1298
  if (new Set(materializedEntryNames).size !== materializedEntryNames.length) {
1289
1299
  return preparedPlanError('Firmware prepared plan contains duplicate entry names');
@@ -40706,26 +40716,21 @@ function parseProtocolV2Resources(value) {
40706
40716
  },
40707
40717
  };
40708
40718
  }
40709
- function isProtocolV2ResourceArchiveEntryName(entryName) {
40710
- var _a;
40711
- const normalized = entryName.replace(/\\/g, '/');
40712
- if (!normalized.toLowerCase().endsWith('.okpkg')) {
40713
- return false;
40714
- }
40715
- const parts = normalized.split('/');
40716
- const fileName = (_a = parts[parts.length - 1]) !== null && _a !== void 0 ? _a : '';
40717
- return (fileName.length > 0 &&
40718
- !fileName.startsWith('.') &&
40719
- !parts.some(part => part === '__MACOSX' || part === '.' || part === '..' || part === ''));
40720
- }
40721
- function isSafeResourceDevicePath(path) {
40722
- return !(path.includes('\\') ||
40719
+ const PROTOCOL_V2_RESOURCE_DEVICE_ROOTS = ['vol0:/bundles/', 'vol0:/loaders/rom/'];
40720
+ function isAllowedResourceDevicePath(path) {
40721
+ if (path.includes('\\') ||
40723
40722
  path.includes('//') ||
40724
40723
  [...path].some(char => {
40725
40724
  const code = char.charCodeAt(0);
40726
40725
  return code <= 0x1f || code === 0x7f;
40727
40726
  }) ||
40728
- path.split('/').some(part => part === '.' || part === '..'));
40727
+ path.split('/').some(part => part === '.' || part === '..')) {
40728
+ return false;
40729
+ }
40730
+ if (path === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH) {
40731
+ return true;
40732
+ }
40733
+ return (path.endsWith('.okpkg') && PROTOCOL_V2_RESOURCE_DEVICE_ROOTS.some(root => path.startsWith(root)));
40729
40734
  }
40730
40735
  function readAscii(bytes, offset, length) {
40731
40736
  return Array.from(bytes.slice(offset, offset + length))
@@ -40743,7 +40748,7 @@ function readResourceDevicePath(bytes) {
40743
40748
  throw new Error('Invalid Pro2 RESOURCE package device path metadata');
40744
40749
  }
40745
40750
  const path = readAscii(pathBytes, 0, pathBytes.byteLength);
40746
- if (!isSafeResourceDevicePath(path)) {
40751
+ if (!isAllowedResourceDevicePath(path)) {
40747
40752
  throw new Error(`Invalid Pro2 RESOURCE package device path: ${path}`);
40748
40753
  }
40749
40754
  return path;
@@ -43718,8 +43723,7 @@ class DeviceCommands {
43718
43723
  errorCode: error === null || error === void 0 ? void 0 : error.errorCode,
43719
43724
  response: hdTransport.getSafeTransportLogPayload((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data, type),
43720
43725
  });
43721
- if (error.errorCode === hdShared.HardwareErrorCode.BleDeviceBondError ||
43722
- error.errorCode === hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation) {
43726
+ if (error.errorCode === hdShared.HardwareErrorCode.BleDeviceBondError) {
43723
43727
  return {
43724
43728
  type: 'BleDeviceBondError',
43725
43729
  message: {
@@ -43778,9 +43782,6 @@ class DeviceCommands {
43778
43782
  if (error.message.indexOf('BleDeviceBondError') > -1) {
43779
43783
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceBondError);
43780
43784
  }
43781
- if (error.message.indexOf('BlePeerRemovedPairingInformation') > -1) {
43782
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation);
43783
- }
43784
43785
  if (error.message.indexOf('BridgeDeviceDisconnected') > -1) {
43785
43786
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BridgeDeviceDisconnected);
43786
43787
  }
@@ -44530,7 +44531,7 @@ const mapProtocolV2DeviceInfoToState = (info, mode = 'unknown') => {
44530
44531
  vendor: 'onekey.so',
44531
44532
  serialNo: (_b = info.hw) === null || _b === void 0 ? void 0 : _b.serial_no,
44532
44533
  bleName: ((_c = info.coprocessor) === null || _c === void 0 ? void 0 : _c.bt_adv_name)
44533
- ? hdShared.canonicalizePro2BleAdvertisementName(info.coprocessor.bt_adv_name)
44534
+ ? hdShared.normalizePro2FindMyAdvertisementName(info.coprocessor.bt_adv_name)
44534
44535
  : undefined,
44535
44536
  deviceId: loader ? null : undefined,
44536
44537
  }),
@@ -45411,8 +45412,7 @@ class Device extends events.exports {
45411
45412
  }
45412
45413
  getCurrentBleName() {
45413
45414
  var _a, _b;
45414
- const bleName = (_b = (_a = this.state) === null || _a === void 0 ? void 0 : _a.identity.bleName) !== null && _b !== void 0 ? _b : null;
45415
- return bleName ? hdShared.canonicalizePro2BleAdvertisementName(bleName) : null;
45415
+ return (_b = (_a = this.state) === null || _a === void 0 ? void 0 : _a.identity.bleName) !== null && _b !== void 0 ? _b : null;
45416
45416
  }
45417
45417
  getCurrentLabel() {
45418
45418
  var _a, _b;
@@ -46923,7 +46923,7 @@ class SearchDevices extends BaseMethod {
46923
46923
  if (!seenIds.has(lowerId)) {
46924
46924
  seenIds.add(lowerId);
46925
46925
  const rawBleName = (_e = (_d = device.name) !== null && _d !== void 0 ? _d : device.localName) !== null && _e !== void 0 ? _e : '';
46926
- const bleName = hdShared.canonicalizePro2BleAdvertisementName(rawBleName);
46926
+ const bleName = hdShared.normalizePro2FindMyAdvertisementName(rawBleName);
46927
46927
  devices.push(Object.assign(Object.assign({}, device), { connectId: device.id, serialNo: null, uuid: '', deviceId: null, name: bleName || device.name, deviceType: getDeviceTypeByBleName(bleName) }));
46928
46928
  }
46929
46929
  }
@@ -51407,7 +51407,6 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
51407
51407
  hdShared.HardwareErrorCode.BlePermissionError,
51408
51408
  hdShared.HardwareErrorCode.BleLocationError,
51409
51409
  hdShared.HardwareErrorCode.BleDeviceBondError,
51410
- hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation,
51411
51410
  hdShared.HardwareErrorCode.BleCharacteristicNotifyError,
51412
51411
  hdShared.HardwareErrorCode.BleTimeoutError,
51413
51412
  hdShared.HardwareErrorCode.BleWriteCharacteristicError,
@@ -51708,6 +51707,86 @@ const INSTALLABLE_FIRMWARE_TARGET_IDS = new Set([
51708
51707
  ]);
51709
51708
  new Map(Object.entries(ProtocolV2FirmwareTargetType).flatMap(([key, value]) => INSTALLABLE_FIRMWARE_TARGET_IDS.has(value) ? [[key, value]] : []));
51710
51709
 
51710
+ let memoryHostSequence = 0;
51711
+ const createReference = (binary, prefix) => {
51712
+ const digest = utils.bytesToHex(sha256.sha256(new Uint8Array(binary)));
51713
+ return {
51714
+ artifactRef: `fwmem:${prefix}:${digest.slice(0, 32)}`,
51715
+ size: binary.byteLength,
51716
+ sha256: digest,
51717
+ };
51718
+ };
51719
+ function prepareFirmwareUpdateV4MemoryHost({ sdk, plan, artifacts, }) {
51720
+ if (plan.executor !== 'v4') {
51721
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory host only supports V4 plans');
51722
+ }
51723
+ memoryHostSequence += 1;
51724
+ const hostId = `${Date.now()}:${memoryHostSequence}`;
51725
+ const binaries = new Map();
51726
+ const inputs = artifacts.map((input, artifactIndex) => {
51727
+ var _a;
51728
+ const artifactBinary = new Uint8Array(input.binary).slice();
51729
+ const artifact = createReference(artifactBinary.buffer, `${hostId}:artifact:${artifactIndex}`);
51730
+ binaries.set(artifact.artifactRef, artifactBinary);
51731
+ const materializedEntries = (_a = input.materializedEntries) === null || _a === void 0 ? void 0 : _a.map((entry, entryIndex) => {
51732
+ const entryArtifact = createReference(entry.binary, `${hostId}:entry:${artifactIndex}:${entryIndex}`);
51733
+ return {
51734
+ entryName: entry.entryName,
51735
+ artifact: entryArtifact,
51736
+ };
51737
+ });
51738
+ return Object.assign({ artifactId: input.artifactId, artifact }, ((materializedEntries === null || materializedEntries === void 0 ? void 0 : materializedEntries.length) ? { materializedEntries } : {}));
51739
+ });
51740
+ const preparedPlan = sdk.prepareFirmwareUpdatePlan({
51741
+ plan,
51742
+ leaseRef: `fwmemlease:${hostId}`,
51743
+ artifacts: inputs,
51744
+ });
51745
+ const readers = new Map();
51746
+ let readerSequence = 0;
51747
+ const artifactReader = {
51748
+ open({ artifactRef }) {
51749
+ const binary = binaries.get(artifactRef);
51750
+ if (!binary) {
51751
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory artifact is unavailable');
51752
+ }
51753
+ readerSequence += 1;
51754
+ const readerId = `fwmemreader:${hostId}:${readerSequence}`;
51755
+ readers.set(readerId, binary);
51756
+ return Promise.resolve({ readerId, size: binary.byteLength });
51757
+ },
51758
+ read({ readerId, offset, length }) {
51759
+ const binary = readers.get(readerId);
51760
+ if (!binary || offset < 0 || length <= 0 || offset + length > binary.byteLength) {
51761
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory artifact read is invalid');
51762
+ }
51763
+ const data = binary.slice(offset, offset + length).buffer;
51764
+ return Promise.resolve({
51765
+ data,
51766
+ bytesRead: data.byteLength,
51767
+ eof: offset + length === binary.byteLength,
51768
+ });
51769
+ },
51770
+ close({ readerId }) {
51771
+ readers.delete(readerId);
51772
+ return Promise.resolve();
51773
+ },
51774
+ };
51775
+ const hostBindingGeneration = sdk.registerFirmwareUpdateHostBinding({
51776
+ artifactReader,
51777
+ preparedPlanDigest: preparedPlan.preparedPlanDigest,
51778
+ });
51779
+ return {
51780
+ preparedPlan,
51781
+ hostBindingGeneration,
51782
+ release: () => {
51783
+ sdk.unregisterFirmwareUpdateHostBinding(hostBindingGeneration);
51784
+ readers.clear();
51785
+ binaries.clear();
51786
+ },
51787
+ };
51788
+ }
51789
+
51711
51790
  const Log$7 = getLogger(exports.LoggerNames.Method);
51712
51791
  const SESSION_ERROR$1 = 'session not found';
51713
51792
  const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
@@ -52176,7 +52255,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52176
52255
  if (!this.params.preparedPlan &&
52177
52256
  this.params.resourceArchiveBinary &&
52178
52257
  ((_c = this.params.targetsToUpdate) === null || _c === void 0 ? void 0 : _c.includes('resource'))) {
52179
- return this.runProtocolV2DirectArtifacts({});
52258
+ const localMemoryHost = yield this.prepareProtocolV2LocalMemoryHost({
52259
+ features: deviceFeatures,
52260
+ firmwareType,
52261
+ });
52262
+ try {
52263
+ return yield this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
52264
+ }
52265
+ finally {
52266
+ localMemoryHost.release();
52267
+ }
52180
52268
  }
52181
52269
  const hasPreparedComponentArtifacts = Object.values((_d = this.params.componentArtifacts) !== null && _d !== void 0 ? _d : {}).some(Boolean);
52182
52270
  if (this.params.preparedPlan || hasPreparedComponentArtifacts) {
@@ -52185,12 +52273,12 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52185
52273
  let fwBinaryMap = [];
52186
52274
  let bootloaderBinary = null;
52187
52275
  let installItems;
52188
- let explicitInstallItems;
52276
+ let resourceMemoryHost;
52189
52277
  try {
52190
52278
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartDownloadFirmware);
52191
52279
  fwBinaryMap = this.collectExplicitTargetBinaries();
52192
52280
  bootloaderBinary = this.prepareBootloaderBinary();
52193
- explicitInstallItems = this.buildProtocolV2InstallItems({
52281
+ const explicitInstallItems = this.buildProtocolV2InstallItems({
52194
52282
  bootloaderBinary,
52195
52283
  fwBinaryMap,
52196
52284
  });
@@ -52232,10 +52320,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52232
52320
  }
52233
52321
  if (wantsResources) {
52234
52322
  this.params.resourceArchiveBinary = yield this.downloadRemoteProtocolV2ResourceArchive(deviceFeatures, firmwareType);
52323
+ resourceMemoryHost = yield this.prepareProtocolV2LocalMemoryHost({
52324
+ features: deviceFeatures,
52325
+ firmwareType,
52326
+ availableInstallItems: installItems !== null && installItems !== void 0 ? installItems : explicitInstallItems,
52327
+ });
52235
52328
  }
52236
52329
  this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
52237
52330
  }
52238
52331
  catch (err) {
52332
+ resourceMemoryHost === null || resourceMemoryHost === void 0 ? void 0 : resourceMemoryHost.release();
52239
52333
  if (typeof err === 'object' &&
52240
52334
  err !== null &&
52241
52335
  'params' in err &&
@@ -52247,11 +52341,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52247
52341
  }
52248
52342
  throw normalizeFirmwarePreparationError(err);
52249
52343
  }
52250
- if (wantsResources && this.params.resourceArchiveBinary) {
52251
- return this.runProtocolV2DirectArtifacts({
52252
- availableInstallItems: installItems !== null && installItems !== void 0 ? installItems : explicitInstallItems,
52253
- announceDownload: false,
52254
- });
52344
+ if (resourceMemoryHost) {
52345
+ try {
52346
+ return yield this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType, false);
52347
+ }
52348
+ finally {
52349
+ resourceMemoryHost.release();
52350
+ }
52255
52351
  }
52256
52352
  if (!bootloaderBinary && fwBinaryMap.length === 0 && !(installItems === null || installItems === void 0 ? void 0 : installItems.length)) {
52257
52353
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
@@ -52352,59 +52448,95 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52352
52448
  return installSources;
52353
52449
  });
52354
52450
  }
52355
- runProtocolV2DirectArtifacts({ availableInstallItems, announceDownload = true, }) {
52451
+ prepareProtocolV2LocalMemoryHost({ features, firmwareType, availableInstallItems = this.buildProtocolV2InstallItems({
52452
+ bootloaderBinary: this.prepareBootloaderBinary(),
52453
+ fwBinaryMap: this.collectExplicitTargetBinaries(),
52454
+ }), }) {
52455
+ var _a, _b;
52356
52456
  return __awaiter(this, void 0, void 0, function* () {
52357
- try {
52358
- if (announceDownload) {
52359
- this.postTipMessage(exports.FirmwareUpdateTipMessage.StartDownloadFirmware);
52360
- }
52361
- const installItems = this.filterProtocolV2LocalInstallItems(availableInstallItems !== null && availableInstallItems !== void 0 ? availableInstallItems : this.buildProtocolV2InstallItems({
52362
- bootloaderBinary: this.prepareBootloaderBinary(),
52363
- fwBinaryMap: this.collectExplicitTargetBinaries(),
52364
- }));
52365
- const installSources = yield Promise.all(installItems.map((item) => __awaiter(this, void 0, void 0, function* () {
52366
- return ({
52367
- fileName: item.fileName,
52368
- source: yield this.openProtocolV2MemorySource(item.binary),
52369
- targetId: item.targetId,
52370
- kind: item.kind,
52371
- });
52372
- })));
52373
- const resourceSources = this.params.resourceArchiveBinary
52374
- ? yield this.createProtocolV2ResourceSourcesFromArchive(this.params.resourceArchiveBinary)
52375
- : [];
52376
- if (installSources.length === 0 && resourceSources.length === 0) {
52377
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
52378
- }
52379
- if (announceDownload) {
52380
- this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
52381
- }
52382
- return yield this.executeProtocolV2SourceUpdate({
52383
- installSources,
52384
- resourceSources,
52457
+ const requestedComponentTargets = new Set(((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : []).filter((target) => target !== 'resource' && target !== 'boot_resources'));
52458
+ const localComponentTargets = new Set(availableInstallItems.flatMap(item => {
52459
+ const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52460
+ return target ? [target] : [];
52461
+ }));
52462
+ const missingTarget = Array.from(requestedComponentTargets).find(target => !localComponentTargets.has(target));
52463
+ if (missingTarget) {
52464
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local update has no binary for requested target ${missingTarget}`, {
52465
+ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
52466
+ artifactName: missingTarget,
52385
52467
  });
52386
52468
  }
52387
- finally {
52388
- yield this.closeProtocolV2PreparedSources();
52469
+ const installItems = this.filterProtocolV2LocalInstallItems(availableInstallItems);
52470
+ const planArtifacts = [];
52471
+ const memoryArtifacts = [];
52472
+ for (const item of installItems) {
52473
+ const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52474
+ if (!target || item.binary.byteLength <= 0) {
52475
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local firmware artifact is invalid: ${item.fileName}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52476
+ }
52477
+ const artifactId = `component:${target}`;
52478
+ planArtifacts.push(Object.assign({ artifactId,
52479
+ target, container: 'raw', logicalName: item.fileName, expectedSize: item.binary.byteLength, expectedSha256: bytesToHex(sha256.sha256(new Uint8Array(item.binary))) }, (((_b = this.params.expectedTargetVersions) === null || _b === void 0 ? void 0 : _b[target])
52480
+ ? { targetVersion: this.params.expectedTargetVersions[target] }
52481
+ : {})));
52482
+ memoryArtifacts.push({ artifactId, binary: item.binary });
52389
52483
  }
52390
- });
52391
- }
52392
- createProtocolV2ResourceSourcesFromArchive(binary) {
52393
- var _a;
52394
- return __awaiter(this, void 0, void 0, function* () {
52395
- const archive = yield this.prepareProtocolV2LocalResourceArchive(binary);
52396
- const sources = [];
52397
- for (const resource of archive.resources) {
52398
- sources.push({
52399
- name: (_a = resource.entryName.split('/').pop()) !== null && _a !== void 0 ? _a : resource.entryName,
52400
- source: yield this.openProtocolV2MemorySource(resource.binary),
52401
- devicePath: resource.header.devicePath,
52402
- version: resource.header.version,
52403
- payloadHash: resource.header.payloadHash,
52404
- headerHash: resource.header.headerHash,
52484
+ const resourceArchive = yield this.prepareProtocolV2LocalResourceArchive(this.params.resourceArchiveBinary);
52485
+ const resourceArtifactId = 'resource:archive';
52486
+ planArtifacts.push({
52487
+ artifactId: resourceArtifactId,
52488
+ target: 'resource',
52489
+ container: 'zip',
52490
+ logicalName: 'protocol-v2-local-resource-archive',
52491
+ expectedSize: resourceArchive.binary.byteLength,
52492
+ expectedSha256: bytesToHex(sha256.sha256(new Uint8Array(resourceArchive.binary))),
52493
+ });
52494
+ memoryArtifacts.push({
52495
+ artifactId: resourceArtifactId,
52496
+ binary: resourceArchive.binary,
52497
+ materializedEntries: resourceArchive.materializedEntries,
52498
+ });
52499
+ const plan = buildProtocolV2LocalFirmwareUpdatePlan({
52500
+ features,
52501
+ firmwareType,
52502
+ platform: this.params.platform,
52503
+ artifacts: planArtifacts,
52504
+ });
52505
+ let memoryHost;
52506
+ try {
52507
+ memoryHost = prepareFirmwareUpdateV4MemoryHost({
52508
+ sdk: {
52509
+ prepareFirmwareUpdatePlan,
52510
+ registerFirmwareUpdateHostBinding,
52511
+ unregisterFirmwareUpdateHostBinding,
52512
+ },
52513
+ plan,
52514
+ artifacts: memoryArtifacts,
52515
+ });
52516
+ const preparedPlan = validateFirmwareUpdatePreparedPlan(memoryHost.preparedPlan);
52517
+ assertFirmwareUpdatePreparedPlanBinding({
52518
+ preparedPlan,
52519
+ executor: 'v4',
52520
+ platform: this.params.platform,
52521
+ scopeTargets: [],
52522
+ bindings: [],
52523
+ });
52524
+ assertFirmwareUpdatePreparedPlanDeviceIdentity({
52525
+ preparedPlan,
52526
+ deviceIdentity: this.protocolV2ExpectedSerialNumber,
52527
+ deviceModel: this.getProtocolV2PreparedPlanDeviceModel(features),
52405
52528
  });
52529
+ const hostBinding = resolveFirmwareUpdateHostBinding(memoryHost.hostBindingGeneration, preparedPlan.preparedPlanDigest);
52530
+ this.params.preparedPlan = preparedPlan;
52531
+ this.params.targetsToUpdate = [...preparedPlan.targetsToUpdate];
52532
+ this.params.artifactReader = hostBinding.artifactReader;
52533
+ this.params.componentArtifacts = undefined;
52534
+ return memoryHost;
52535
+ }
52536
+ catch (error) {
52537
+ memoryHost === null || memoryHost === void 0 ? void 0 : memoryHost.release();
52538
+ throw error;
52406
52539
  }
52407
- return sources;
52408
52540
  });
52409
52541
  }
52410
52542
  prepareProtocolV2LocalResourceArchive(binary) {
@@ -52420,12 +52552,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52420
52552
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource ZIP cannot be parsed', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52421
52553
  }
52422
52554
  const zipEntries = Object.values(zip.files);
52423
- const resourceEntries = zipEntries.filter(entry => !entry.dir && isProtocolV2ResourceArchiveEntryName(entry.name));
52555
+ const resourceEntries = zipEntries.filter(entry => !entry.dir && entry.name.toLowerCase().endsWith('.okpkg'));
52424
52556
  if (resourceEntries.length === 0 ||
52425
52557
  resourceEntries.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
52426
52558
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource ZIP has no valid resource package set', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52427
52559
  }
52428
52560
  let totalSize = 0;
52561
+ const materializedEntries = [];
52429
52562
  const resources = [];
52430
52563
  const devicePaths = new Set();
52431
52564
  for (const entry of resourceEntries) {
@@ -52452,9 +52585,10 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52452
52585
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource ZIP contains duplicate device path: ${header.devicePath}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52453
52586
  }
52454
52587
  devicePaths.add(canonicalDevicePath);
52588
+ materializedEntries.push({ entryName: entry.name, binary: fileBinary });
52455
52589
  resources.push({ entryName: entry.name, binary: fileBinary, header });
52456
52590
  }
52457
- return { binary, resources };
52591
+ return { binary, materializedEntries, resources };
52458
52592
  });
52459
52593
  }
52460
52594
  prepareProtocolV2ResourceSources() {
@@ -52472,7 +52606,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52472
52606
  });
52473
52607
  }
52474
52608
  prepareProtocolV2ResourceArchiveSources() {
52475
- var _a, _b;
52609
+ var _a, _b, _c;
52476
52610
  return __awaiter(this, void 0, void 0, function* () {
52477
52611
  const archiveArtifacts = (_b = (_a = this.params.preparedPlan) === null || _a === void 0 ? void 0 : _a.artifacts.filter(artifact => artifact.role === 'resourceBundle' &&
52478
52612
  artifact.target === 'resource' &&
@@ -52499,7 +52633,20 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52499
52633
  if (archiveDigest !== archiveArtifact.artifact.sha256.toLowerCase()) {
52500
52634
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive does not match its approved receipt', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52501
52635
  }
52502
- return this.createProtocolV2ResourceSourcesFromArchive(archiveBinary);
52636
+ const verifiedArchive = yield this.prepareProtocolV2LocalResourceArchive(archiveBinary);
52637
+ const sources = [];
52638
+ for (const resource of verifiedArchive.resources) {
52639
+ const source = yield this.openProtocolV2MemorySource(resource.binary);
52640
+ sources.push({
52641
+ name: (_c = resource.entryName.split('/').pop()) !== null && _c !== void 0 ? _c : resource.entryName,
52642
+ source,
52643
+ devicePath: resource.header.devicePath,
52644
+ version: resource.header.version,
52645
+ payloadHash: resource.header.payloadHash,
52646
+ headerHash: resource.header.headerHash,
52647
+ });
52648
+ }
52649
+ return sources;
52503
52650
  });
52504
52651
  }
52505
52652
  runProtocolV2PreparedArtifacts(features, firmwareType, announceDownload = true) {
@@ -52867,11 +53014,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52867
53014
  return `vol0:${path}`;
52868
53015
  return `vol0:/${path}`;
52869
53016
  }
52870
- getProtocolV2ResourceComparePath(devicePath) {
52871
- return isProtocolV2BootResourcePackagePath(devicePath)
52872
- ? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH
52873
- : devicePath;
52874
- }
52875
53017
  readProtocolV2DeviceFileHeader(path, expectedSize) {
52876
53018
  var _a, _b, _c, _d;
52877
53019
  return __awaiter(this, void 0, void 0, function* () {
@@ -52930,7 +53072,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52930
53072
  if (!bundle.payloadHash || !bundle.headerHash)
52931
53073
  return false;
52932
53074
  try {
52933
- const header = yield this.readProtocolV2DeviceFileHeader(this.getProtocolV2ResourceComparePath(bundle.devicePath), bundle.source.size);
53075
+ const header = yield this.readProtocolV2DeviceFileHeader(bundle.devicePath, bundle.source.size);
52934
53076
  if (!header)
52935
53077
  return false;
52936
53078
  if (bundle.version) {
@@ -53131,7 +53273,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53131
53273
  let totalSize = installSources.reduce((total, item) => total + item.source.size, 0);
53132
53274
  const resourcesToSync = [];
53133
53275
  for (const resource of resourceSources) {
53134
- if (yield this.isProtocolV2ResourceBundleUpToDate(resource)) {
53276
+ const requiresFreshStaging = isProtocolV2BootResourcePackagePath(resource.devicePath);
53277
+ if (!requiresFreshStaging && (yield this.isProtocolV2ResourceBundleUpToDate(resource))) {
53135
53278
  Log$7.log(`[FirmwareUpdateV4] skip RESC bundle ${resource.name}; already up to date`);
53136
53279
  }
53137
53280
  else {
@@ -65073,6 +65216,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65073
65216
  if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
65074
65217
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
65075
65218
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
65219
+ requestQueue.releaseTask(method.responseID);
65076
65220
  return createResponseMessage(method.responseID, true, null);
65077
65221
  }
65078
65222
  Log.debug('Call API - setDevice: ', device.mainId);
@@ -65448,7 +65592,31 @@ function isMissingDetectedProtocolV2Error(method, error) {
65448
65592
  typeof typedError.message === 'string' &&
65449
65593
  typedError.message.includes('Device protocol has not been detected'));
65450
65594
  }
65451
- function connectDeviceForBle(method, device, retryCount = 0) {
65595
+ const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
65596
+ function raceBleAcquire(acquirePromise, abortSignal) {
65597
+ return new Promise((resolve, reject) => {
65598
+ let settled = false;
65599
+ const settle = (fn) => {
65600
+ if (settled)
65601
+ return;
65602
+ settled = true;
65603
+ clearTimeout(deadline);
65604
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', onAbort);
65605
+ fn();
65606
+ };
65607
+ const onAbort = () => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled)));
65608
+ const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`))), BLE_ACQUIRE_DEADLINE_MS);
65609
+ acquirePromise.then(value => settle(() => resolve(value)), error => settle(() => reject(error)));
65610
+ if (abortSignal) {
65611
+ if (abortSignal.aborted) {
65612
+ onAbort();
65613
+ return;
65614
+ }
65615
+ abortSignal.addEventListener('abort', onAbort);
65616
+ }
65617
+ });
65618
+ }
65619
+ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
65452
65620
  var _a;
65453
65621
  return __awaiter(this, void 0, void 0, function* () {
65454
65622
  try {
@@ -65463,9 +65631,31 @@ function connectDeviceForBle(method, device, retryCount = 0) {
65463
65631
  !device.commands ||
65464
65632
  device.commands.disposed;
65465
65633
  if (shouldAcquire) {
65466
- yield device.acquire(method.payload.connectProtocol, {
65467
- forceProtocolDetection: method.payload.forceProtocolDetection,
65468
- });
65634
+ const useAcquireGuards = DataManager.getSettings('env') === 'desktop-web-ble';
65635
+ if (useAcquireGuards && (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) {
65636
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65637
+ }
65638
+ if (!useAcquireGuards) {
65639
+ yield device.acquire(method.payload.connectProtocol, {
65640
+ forceProtocolDetection: method.payload.forceProtocolDetection,
65641
+ });
65642
+ }
65643
+ else {
65644
+ try {
65645
+ yield raceBleAcquire(device.acquire(method.payload.connectProtocol, {
65646
+ forceProtocolDetection: method.payload.forceProtocolDetection,
65647
+ }), abortSignal);
65648
+ }
65649
+ catch (err) {
65650
+ if (err.errorCode === hdShared.HardwareErrorCode.BleTimeoutError &&
65651
+ device.mainId &&
65652
+ device.deviceConnector) {
65653
+ yield device.deviceConnector.disconnect(device.mainId).catch(() => undefined);
65654
+ device.markTransportDisconnected();
65655
+ }
65656
+ throw err;
65657
+ }
65658
+ }
65469
65659
  }
65470
65660
  if ((_a = method.payload) === null || _a === void 0 ? void 0 : _a.onlyConnectBleDevice) {
65471
65661
  if (shouldAcquire) {
@@ -65496,7 +65686,7 @@ function connectDeviceForBle(method, device, retryCount = 0) {
65496
65686
  const nextRetry = retryCount + 1;
65497
65687
  Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
65498
65688
  yield wait(3000);
65499
- yield connectDeviceForBle(method, device, nextRetry);
65689
+ yield connectDeviceForBle(method, device, abortSignal, nextRetry);
65500
65690
  }
65501
65691
  else {
65502
65692
  throw err;
@@ -65581,7 +65771,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65581
65771
  if (tryCount === 1) {
65582
65772
  device.beginConnectionAttempt();
65583
65773
  }
65584
- yield connectDeviceForBle(method, device);
65774
+ yield connectDeviceForBle(method, device, abortSignal);
65585
65775
  }
65586
65776
  resolve(device);
65587
65777
  return;
@@ -65611,7 +65801,6 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65611
65801
  hdShared.HardwareErrorCode.BleLocationServicesDisabled,
65612
65802
  hdShared.HardwareErrorCode.BleDeviceNotBonded,
65613
65803
  hdShared.HardwareErrorCode.BleDeviceBondError,
65614
- hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation,
65615
65804
  hdShared.HardwareErrorCode.BleDeviceBondedCanceled,
65616
65805
  hdShared.HardwareErrorCode.BleCharacteristicNotifyError,
65617
65806
  hdShared.HardwareErrorCode.BleTimeoutError,
@@ -66198,6 +66387,7 @@ exports.parseConnectSettings = parseConnectSettings;
66198
66387
  exports.parseMessage = parseMessage;
66199
66388
  exports.patchFeatures = patchFeatures;
66200
66389
  exports.preloadSessionCache = preloadSessionCache;
66390
+ exports.prepareFirmwareUpdateV4MemoryHost = prepareFirmwareUpdateV4MemoryHost;
66201
66391
  exports.projectDeviceStateFeatures = projectFeatures;
66202
66392
  exports.registerFirmwareUpdateHostBinding = registerFirmwareUpdateHostBinding;
66203
66393
  exports.safeThrowError = safeThrowError;