Skip to content

Commit

Permalink
Merge pull request #2552 from UltimateHackingKeyboard/fix-differentia…
Browse files Browse the repository at this point in the history
…te-firmware-upgrade-skipped

fix: skipped firmware upgrade icon and explaining tooltip
  • Loading branch information
mondalaci authored Feb 26, 2025
2 parents 7fc3f2c + c2efa83 commit 862c7a4
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 87 deletions.
140 changes: 100 additions & 40 deletions packages/uhk-agent/src/services/device.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ConfigurationReply,
convertBleAddressArrayToString,
convertBleStringToNumberArray,
CurrentlyUpdatingModuleInfo,
DeviceConnectionState,
disableAgentUpgradeProtection,
findUhkModuleById,
Expand All @@ -31,6 +32,8 @@ import {
LeftSlotModules,
LogService,
mapObjectToUserConfigBinaryBuffer,
ModuleFirmwareUpgradeSkipInfo,
ModuleFirmwareUpgradeSkipReason,
ModuleInfo,
ModuleSlotToId,
RIGHT_HALF_FIRMWARE_UPGRADE_MODULE_NAME,
Expand Down Expand Up @@ -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);
Expand All @@ -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.');
}
}
Expand All @@ -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);
Expand All @@ -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.');
}

Expand All @@ -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))) {
Expand All @@ -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`);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface CurrentlyUpdatingModuleInfo {
forceUpgraded: boolean;
moduleName: string;
newFirmwareChecksum: string;
}
2 changes: 2 additions & 0 deletions packages/uhk-common/src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ <h1>

<ul class="list-unstyled">
<li *ngFor="let state of firmwareUpgradeStates.modules; trackBy:firmwareUpgradeStateTrackByFn;">
<span class="upgrading">
<ng-template #htmlTooltipTemplate>
<div [innerHTML]="state.checksumTooltip | safeHtml"></div>
</ng-template>
<span class="upgrading"
[ngbTooltip]="htmlTooltipTemplate"
[disableTooltip]="!state.checksumTooltip"
tooltipClass="tooltip-firmware-checksum"
>
<fa-icon *ngIf="state.state === 'Upgrading'" [icon]="faSpinner" animation="spin" [fixedWidth]="true"></fa-icon>
<fa-icon *ngIf="state.state === 'Failed'" [icon]="faExclamation" class="text-danger" [fixedWidth]="true"></fa-icon>
<fa-icon *ngIf="state.state === 'Success'" [icon]="faCheck" [fixedWidth]="true"></fa-icon>
<fa-icon *ngIf="state.state === 'Success' || state.state === 'Skipped'" [icon]="faCheck" [fixedWidth]="true"></fa-icon>
</span>
{{ state.moduleName }}
<span *ngIf="state.firmwareUpgradeSupported">firmware:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { ChangeDetectorRef, Component, OnDestroy, ViewChild } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable, Subscription } from 'rxjs';
import { faCheck, faExclamation, faLongArrowAltRight, faSlidersH, faSpinner } from '@fortawesome/free-solid-svg-icons';
import {
faCheck,
faExclamation,
faLongArrowAltRight,
faSlidersH,
faSpinner,
} from '@fortawesome/free-solid-svg-icons';
import { FirmwareUpgradeFailReason, UhkModule, VersionInformation } from 'uhk-common';

import {
Expand All @@ -18,7 +24,7 @@ import {
import { RecoveryModuleAction, UpdateFirmwareAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
import { XtermLog } from '../../../models/xterm-log';
import { XtermComponent } from '../../xterm/xterm.component';
import { FirmwareUpgradeState, HistoryFileInfo, ModuleFirmwareUpgradeState, UpdateFirmwareWithPayload } from '../../../models';
import { FirmwareUpgradeState, ModuleFirmwareUpgradeState, UpdateFirmwareWithPayload } from '../../../models';

@Component({
selector: 'device-firmware',
Expand All @@ -36,7 +42,6 @@ export class DeviceFirmwareComponent implements OnDestroy {
runningOnNotSupportedWindows$: Observable<boolean>;
firmwareUpgradeAllowed$: Observable<boolean>;

firmwareGithubIssueUrl: string;
firmwareUpgradeFailed: boolean;
firmwareUpgradeFailReasons = FirmwareUpgradeFailReason;
firmwareUpgradeSuccess: boolean;
Expand Down
9 changes: 8 additions & 1 deletion packages/uhk-web/src/app/models/firmware-upgrade-state.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { FirmwareUpgradeFailReason, UhkModule } from 'uhk-common';
import { FirmwareUpgradeFailReason, ModuleFirmwareUpgradeSkipReason, UhkModule } from 'uhk-common';

export enum ModuleFirmwareUpgradeStates {
Idle = 'Idle',
Upgrading = 'Upgrading',
Skipped = 'Skipped',
Success = 'Success',
Failed = 'Failed'
}

export interface ModuleFirmwareUpgradeState {
beforeFirmwareUpgradeChecksum?: string;
firmwareUpgradeSupported: boolean;
forceUpgraded: boolean;
isOfficialFirmware?: boolean;
gitRepo?: string;
gitTag?: string;
moduleName: string;
currentFirmwareChecksum: string;
currentFirmwareVersion: string;
newFirmwareVersion?: string;
newFirmwareChecksum?: string;
state: ModuleFirmwareUpgradeStates;
skipReason?: ModuleFirmwareUpgradeSkipReason;
tooltip?: string;
checksumTooltip?: string;
}

export interface FirmwareUpgradeState {
Expand Down
6 changes: 4 additions & 2 deletions packages/uhk-web/src/app/services/device-renderer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Action, Store } from '@ngrx/store';

import {
ChangeKeyboardLayoutIpcResponse,
CurrentlyUpdatingModuleInfo,
DeviceConnectionState,
DeviceVersionInformation,
FirmwareJson,
Expand All @@ -13,6 +14,7 @@ import {
IpcResponse,
KeyboardLayout,
LogService,
ModuleFirmwareUpgradeSkipInfo,
SaveUserConfigurationData,
UHK_DEVICE_IDS_TYPE,
UpdateFirmwareData,
Expand Down Expand Up @@ -193,11 +195,11 @@ export class DeviceRendererService {
this.dispachStoreAction(new UpdateFirmwareJsonAction(data));
});

this.ipcRenderer.on(IpcEvents.device.moduleFirmwareUpgradeSkip, (event: string, response: string) => {
this.ipcRenderer.on(IpcEvents.device.moduleFirmwareUpgradeSkip, (event: string, response: ModuleFirmwareUpgradeSkipInfo) => {
this.dispachStoreAction(new CurrentlyUpdateSkipModuleAction(response));
});

this.ipcRenderer.on(IpcEvents.device.moduleFirmwareUpgrading, (event: string, response: string) => {
this.ipcRenderer.on(IpcEvents.device.moduleFirmwareUpgrading, (event: string, response: CurrentlyUpdatingModuleInfo) => {
this.dispachStoreAction(new CurrentlyUpdatingModuleAction(response));
});

Expand Down
6 changes: 4 additions & 2 deletions packages/uhk-web/src/app/store/actions/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
BackupUserConfiguration,
ChangeKeyboardLayoutIpcResponse,
ConfigSizesInfo,
CurrentlyUpdatingModuleInfo,
DeviceConnectionState,
DeviceVersionInformation,
FirmwareJson,
Expand All @@ -11,6 +12,7 @@ import {
HardwareModules,
IpcResponse,
KeyboardLayout,
ModuleFirmwareUpgradeSkipInfo,
UHK_DEVICE_IDS_TYPE,
} from 'uhk-common';
import { FirmwareUpgradeError } from '../../models/firmware-upgrade-error';
Expand Down Expand Up @@ -136,14 +138,14 @@ export class ResetUserConfigurationAction implements Action {
export class CurrentlyUpdatingModuleAction implements Action {
type = ActionTypes.CurrentlyUpdatingModule;

constructor(public payload: string) {
constructor(public payload: CurrentlyUpdatingModuleInfo) {
}
}

export class CurrentlyUpdateSkipModuleAction implements Action {
type = ActionTypes.CurrentlyUpdateSkipModule;

constructor(public payload: string) {
constructor(public payload: ModuleFirmwareUpgradeSkipInfo) {
}
}

Expand Down
Loading

0 comments on commit 862c7a4

Please sign in to comment.