diff --git a/packages/uhk-agent/src/services/device.service.ts b/packages/uhk-agent/src/services/device.service.ts index 6ef5893300a..3cecddc5748 100644 --- a/packages/uhk-agent/src/services/device.service.ts +++ b/packages/uhk-agent/src/services/device.service.ts @@ -10,6 +10,7 @@ import { ConfigurationReply, convertBleAddressArrayToString, convertBleStringToNumberArray, + CurrentlyUpdatingModuleInfo, DeviceConnectionState, disableAgentUpgradeProtection, findUhkModuleById, @@ -31,6 +32,8 @@ import { LeftSlotModules, LogService, mapObjectToUserConfigBinaryBuffer, + ModuleFirmwareUpgradeSkipInfo, + ModuleFirmwareUpgradeSkipReason, ModuleInfo, ModuleSlotToId, RIGHT_HALF_FIRMWARE_UPGRADE_MODULE_NAME, @@ -431,7 +434,11 @@ export class DeviceService { deviceConfig.md5); if (data.forceUpgrade || versionInfo.builtFirmwareChecksum !== deviceConfig.md5) { - event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, UHK_DONGLE.name); + event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, { + forceUpgraded: versionInfo.builtFirmwareChecksum === deviceConfig.md5, + moduleName: UHK_DONGLE.name, + newFirmwareChecksum: deviceConfig.md5, + } as CurrentlyUpdatingModuleInfo); await dongleOperations.updateDeviceFirmware(dongleFirmwarePath, UHK_DONGLE); this.logService.misc('[DeviceService] Waiting for keyboard'); await waitForDevices(UHK_DONGLE.keyboard); @@ -446,6 +453,11 @@ export class DeviceService { } } else { + event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, { + moduleName: UHK_DONGLE.name, + newFirmwareChecksum: deviceConfig?.md5, + reason: ModuleFirmwareUpgradeSkipReason.DeviceChecksumMatches, + } as ModuleFirmwareUpgradeSkipInfo); this.logService.misc('Skip dongle firmware upgrade.'); } } @@ -471,7 +483,11 @@ export class DeviceService { deviceConfig.md5); if (data.forceUpgrade || hardwareModules.rightModuleInfo.builtFirmwareChecksum !== deviceConfig.md5) { - event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, RIGHT_HALF_FIRMWARE_UPGRADE_MODULE_NAME); + event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, { + forceUpgraded: hardwareModules.rightModuleInfo.builtFirmwareChecksum === deviceConfig.md5, + newFirmwareChecksum: deviceConfig.md5, + moduleName: RIGHT_HALF_FIRMWARE_UPGRADE_MODULE_NAME, + } as CurrentlyUpdatingModuleInfo); await this.operations.updateDeviceFirmware(deviceFirmwarePath, uhkDeviceProduct); this.logService.misc('[DeviceService] Waiting for keyboard'); await waitForDevices(uhkDeviceProduct.keyboard); @@ -490,6 +506,11 @@ export class DeviceService { response.userConfigSaved = true; } } else { + event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, { + moduleName: RIGHT_HALF_FIRMWARE_UPGRADE_MODULE_NAME, + newFirmwareChecksum: deviceConfig?.md5, + reason: ModuleFirmwareUpgradeSkipReason.DeviceChecksumMatches, + } as ModuleFirmwareUpgradeSkipInfo); this.logService.misc('Skip right firmware upgrade.'); } @@ -515,7 +536,13 @@ export class DeviceService { ); if (data.forceUpgrade || !isLeftModuleFirmwareSame) { - event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, leftModuleInfo.module.name); + const moduleConfig = packageJson.modules.find(firmwareDevice => firmwareDevice.moduleId === leftModuleInfo.module.id); + + event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, { + forceUpgraded: isLeftModuleFirmwareSame, + moduleName: leftModuleInfo.module.name, + newFirmwareChecksum: moduleConfig.md5, + } as CurrentlyUpdatingModuleInfo); if(uhkDeviceProduct.firmwareUpgradeMethod === FIRMWARE_UPGRADE_METHODS.MCUBOOT) { if (!(await isUhkDeviceConnected(UHK_80_DEVICE_LEFT))) { @@ -542,51 +569,84 @@ export class DeviceService { ); } } else { - event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, leftModuleInfo.module.name); + const moduleConfig = packageJson.modules.find(firmwareDevice => firmwareDevice.moduleId === leftModuleInfo.module.id); + + event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, { + moduleName: leftModuleInfo.module.name, + newFirmwareChecksum: moduleConfig?.md5, + reason: ModuleFirmwareUpgradeSkipReason.ModuleChecksumMatches, + } as ModuleFirmwareUpgradeSkipInfo); this.logService.misc('[DeviceService] Skip left firmware upgrade.'); } - // TODO: implement MCUBOOT version - if (uhkDeviceProduct.firmwareUpgradeMethod === FIRMWARE_UPGRADE_METHODS.KBOOT) { - for (const moduleInfo of hardwareModules.moduleInfos) { - if (moduleInfo.module.slotId === ModuleSlotToId.leftHalf) { - // Left half upgrade mandatory, it is running before the other modules upgrade. - } else if (moduleInfo.module.firmwareUpgradeSupported) { - this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" firmware version:`, moduleInfo.info.firmwareVersion); - this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" current remote firmware checksum:`, moduleInfo.info.remoteFirmwareChecksum); - - const moduleFirmwareInfo = hardwareModules.rightModuleInfo.modules[moduleInfo.module.id]; - if (moduleFirmwareInfo) { - this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" new built firmware checksum:`, moduleFirmwareInfo.builtFirmwareChecksum); - } + for (const moduleInfo of hardwareModules.moduleInfos) { + if (moduleInfo.module.slotId === ModuleSlotToId.leftHalf) { + // Left half upgrade mandatory, it is running before the other modules upgrade. + continue; + } + // TODO: implement MCUBOOT version + if (uhkDeviceProduct.firmwareUpgradeMethod === FIRMWARE_UPGRADE_METHODS.MCUBOOT) { + event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, { + moduleName: moduleInfo.module.name, + newFirmwareChecksum: '', + reason: ModuleFirmwareUpgradeSkipReason.Uhk80Limitation, + } as ModuleFirmwareUpgradeSkipInfo); + + continue; + } - const isModuleFirmwareSame = isSameFirmware( - { - firmwareChecksum: moduleInfo.info.remoteFirmwareChecksum, - firmwareVersion: moduleInfo.info.firmwareVersion - }, - { - firmwareChecksum: moduleFirmwareInfo?.builtFirmwareChecksum, - firmwareVersion: packageJson.firmwareVersion - } - ); + if (moduleInfo.module.firmwareUpgradeSupported) { + this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" firmware version:`, moduleInfo.info.firmwareVersion); + this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" current remote firmware checksum:`, moduleInfo.info.remoteFirmwareChecksum); - if (data.forceUpgrade || !isModuleFirmwareSame) { - event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, moduleInfo.module.name); - await this.operations - .updateModuleWithKboot( - getModuleFirmwarePath(moduleInfo.module, packageJson), - uhkDeviceProduct, - moduleInfo.module - ); - this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" firmware update done.`); - } else { - event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, moduleInfo.module.name); - this.logService.misc(`[DeviceService] Skip "${moduleInfo.module.name}" firmware upgrade.`); + const moduleFirmwareInfo = hardwareModules.rightModuleInfo.modules[moduleInfo.module.id]; + if (moduleFirmwareInfo) { + this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" new built firmware checksum:`, moduleFirmwareInfo.builtFirmwareChecksum); + } + + const isModuleFirmwareSame = isSameFirmware( + { + firmwareChecksum: moduleInfo.info.remoteFirmwareChecksum, + firmwareVersion: moduleInfo.info.firmwareVersion + }, + { + firmwareChecksum: moduleFirmwareInfo?.builtFirmwareChecksum, + firmwareVersion: packageJson.firmwareVersion } + ); + + if (data.forceUpgrade || !isModuleFirmwareSame) { + const moduleConfig = packageJson.modules.find(firmwareDevice => firmwareDevice.moduleId === moduleInfo.module.id); + + event.sender.send(IpcEvents.device.moduleFirmwareUpgrading, { + forceUpgraded: isModuleFirmwareSame, + moduleName: moduleInfo.module.name, + newFirmwareChecksum: moduleConfig.md5, + } as CurrentlyUpdatingModuleInfo); + await this.operations + .updateModuleWithKboot( + getModuleFirmwarePath(moduleInfo.module, packageJson), + uhkDeviceProduct, + moduleInfo.module + ); + this.logService.misc(`[DeviceService] "${moduleInfo.module.name}" firmware update done.`); } else { - this.logService.misc(`[DeviceService] Skip "${moduleInfo.module.name}" firmware upgrade. Currently not supported`); + const moduleConfig = packageJson.modules.find(firmwareDevice => firmwareDevice.moduleId === moduleInfo.module.id); + + event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, { + moduleName: moduleInfo.module.name, + newFirmwareChecksum: moduleConfig?.md5, + reason: ModuleFirmwareUpgradeSkipReason.ModuleChecksumMatches, + } as ModuleFirmwareUpgradeSkipInfo); + this.logService.misc(`[DeviceService] Skip "${moduleInfo.module.name}" firmware upgrade.`); } + } else { + event.sender.send(IpcEvents.device.moduleFirmwareUpgradeSkip, { + moduleName: moduleInfo.module.name, + newFirmwareChecksum: '', + reason: ModuleFirmwareUpgradeSkipReason.NotSupported, + } as ModuleFirmwareUpgradeSkipInfo); + this.logService.misc(`[DeviceService] Skip "${moduleInfo.module.name}" firmware upgrade. Currently not supported`); } } diff --git a/packages/uhk-common/src/models/currently-updating-module-info.ts b/packages/uhk-common/src/models/currently-updating-module-info.ts new file mode 100644 index 00000000000..6de43234352 --- /dev/null +++ b/packages/uhk-common/src/models/currently-updating-module-info.ts @@ -0,0 +1,5 @@ +export interface CurrentlyUpdatingModuleInfo { + forceUpgraded: boolean; + moduleName: string; + newFirmwareChecksum: string; +} diff --git a/packages/uhk-common/src/models/index.ts b/packages/uhk-common/src/models/index.ts index dfd878522b6..fa8e5a45258 100644 --- a/packages/uhk-common/src/models/index.ts +++ b/packages/uhk-common/src/models/index.ts @@ -4,6 +4,7 @@ export * from './backup-user-configuration-info.js'; export * from './ble-address-pair.js'; export * from './command-line-args.js'; export * from './config-sizes-info.js'; +export * from './currently-updating-module-info.js'; export * from './device-module-record.js'; export * from './device-version-information.js'; export * from './dongle.js'; @@ -22,6 +23,7 @@ export * from './app-start-info.js'; export * from './configuration-reply.js'; export * from './version-information.js'; export * from './device-connection-state.js'; +export * from './module-firmware-upgrade-skip-info.js'; export * from './module-slot-to-i2c-adress.js'; export * from './module-slot-id.js'; export * from './module-version-info.js'; diff --git a/packages/uhk-common/src/models/module-firmware-upgrade-skip-info.ts b/packages/uhk-common/src/models/module-firmware-upgrade-skip-info.ts new file mode 100644 index 00000000000..1d9586c8bae --- /dev/null +++ b/packages/uhk-common/src/models/module-firmware-upgrade-skip-info.ts @@ -0,0 +1,24 @@ +export enum ModuleFirmwareUpgradeSkipReason { + /** + * The actually running firmware checksum of the right half or the dongle is matching with the firmware tarball checksum. + */ + DeviceChecksumMatches = 'DeviceChecksumMatches', + /** + * The actually running firmware checksum of the module is matching with the expected firmware checksum by right half device. + */ + ModuleChecksumMatches = 'ModuleChecksumMatches', + /** + * The module does not support the firmware upgrade like touchpad. + */ + NotSupported = 'NotSupported', + /** + * UHK 80 currently does not support the firmware upgrades of the modules. + */ + Uhk80Limitation = 'Uhk80Limitation', +} + +export interface ModuleFirmwareUpgradeSkipInfo { + moduleName: string; + newFirmwareChecksum: string; + reason: ModuleFirmwareUpgradeSkipReason; +} diff --git a/packages/uhk-web/src/app/components/device/firmware/device-firmware.component.html b/packages/uhk-web/src/app/components/device/firmware/device-firmware.component.html index 318f1b487f1..6af4df4c1ab 100644 --- a/packages/uhk-web/src/app/components/device/firmware/device-firmware.component.html +++ b/packages/uhk-web/src/app/components/device/firmware/device-firmware.component.html @@ -9,10 +9,17 @@