Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e1f0ded9e | ||
|
|
d58386ef4b | ||
|
|
179c982bfb | ||
|
|
a7d07dbf4c | ||
|
|
0ca922d24a | ||
|
|
a6f1aa15a5 | ||
|
|
fc2d025cc4 | ||
|
|
8b5ae106bd | ||
|
|
44639bbf53 | ||
|
|
9fcce9234a | ||
|
|
b26fecfc7a | ||
|
|
1b15911783 | ||
|
|
148dd8d361 | ||
|
|
0d9ac50999 | ||
|
|
e19e4bc5a4 | ||
|
|
bdd79a5a9a | ||
|
|
fb4e05fdc4 | ||
|
|
01fcf9053a | ||
|
|
533c2f13d2 | ||
|
|
b9c32b46a9 | ||
|
|
f9b7260be6 | ||
|
|
847694d590 | ||
|
|
58178a5c7b | ||
|
|
9b93b4dac5 | ||
|
|
478dac0621 | ||
|
|
f196fcdaa2 | ||
|
|
0b420ff516 | ||
|
|
7656af76e4 | ||
|
|
beed546ae4 | ||
|
|
bf94370f2f | ||
|
|
2476049681 | ||
|
|
f8d8b6d213 | ||
|
|
05bbce1d50 | ||
|
|
32494fa228 | ||
|
|
e0ce38988e | ||
|
|
5c660c549d | ||
|
|
510b914e26 | ||
|
|
cf64fc0c08 | ||
|
|
b25bc9d81d | ||
|
|
2f00a5eaf4 | ||
|
|
e8fe0f8d3e |
@@ -6,6 +6,15 @@ The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1
|
||||
|
||||
Every Agent version includes the most recent firmware version. See the [firmware changelog](https://github.com/UltimateHackingKeyboard/firmware/blob/master/CHANGELOG.md).
|
||||
|
||||
## [1.1.3] - 2018-04-06
|
||||
|
||||
Firmware: 8.1.**5** [[release](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/v8.1.5)] | Device Protocol: 4.2.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||
|
||||
- Show the firmware versions of the left and right keyboard halves on the firmware page.
|
||||
- Fix menu scancode.
|
||||
- Make the tooltip text regarding non-US characters easier to understand.
|
||||
- On the Device Configuration page change terminology from download/upload to export/import for greater clarity.
|
||||
|
||||
## [1.1.2] - 2018-03-09
|
||||
|
||||
Firmware: 8.1.**4** [[release](https://github.com/UltimateHackingKeyboard/firmware/releases/tag/v8.1.4)] | Device Protocol: 4.2.0 | User Config: 4.0.0 | Hardware Config: 1.0.0
|
||||
|
||||
679
package-lock.json
generated
679
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -3,8 +3,8 @@
|
||||
"private": true,
|
||||
"author": "Ultimate Gadget Laboratories",
|
||||
"main": "electron/dist/electron-main.js",
|
||||
"version": "1.1.2",
|
||||
"firmwareVersion": "8.1.4",
|
||||
"version": "1.1.3",
|
||||
"firmwareVersion": "8.1.5",
|
||||
"deviceProtocolVersion": "4.2.0",
|
||||
"userConfigVersion": "4.0.0",
|
||||
"hardwareConfigVersion": "1.0.0",
|
||||
@@ -30,19 +30,21 @@
|
||||
"@types/usb": "1.1.3",
|
||||
"autoprefixer": "6.5.3",
|
||||
"buffer": "5.0.6",
|
||||
"copyfiles": "^2.0.0",
|
||||
"copy-webpack-plugin": "4.0.1",
|
||||
"core-js": "2.4.1",
|
||||
"cross-env": "5.0.5",
|
||||
"decompress": "4.2.0",
|
||||
"decompress-tarbz2": "^4.1.1",
|
||||
"devtron": "1.4.0",
|
||||
"electron": "1.7.11",
|
||||
"electron-builder": "20.4.0",
|
||||
"electron-debug": "1.4.0",
|
||||
"electron-devtools-installer": "2.2.0",
|
||||
"electron-log": "2.2.9",
|
||||
"electron": "1.8.4",
|
||||
"electron-builder": "20.8.1",
|
||||
"electron-debug": "1.5.0",
|
||||
"electron-devtools-installer": "2.2.3",
|
||||
"electron-log": "2.2.14",
|
||||
"electron-rebuild": "1.7.3",
|
||||
"electron-settings": "3.1.2",
|
||||
"electron-settings": "3.1.4",
|
||||
"electron-updater": "2.21.4",
|
||||
"exports-loader": "0.6.3",
|
||||
"file-loader": "0.10.0",
|
||||
"fs-extra": "4.0.2",
|
||||
|
||||
2950
packages/uhk-agent/package-lock.json
generated
2950
packages/uhk-agent/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,12 +17,6 @@
|
||||
"command-line-args": "4.0.7",
|
||||
"decompress": "4.2.0",
|
||||
"decompress-bzip2": "4.0.0",
|
||||
"electron": "1.7.9",
|
||||
"electron-is-dev": "0.1.2",
|
||||
"electron-log": "2.2.9",
|
||||
"electron-rebuild": "1.6.0",
|
||||
"electron-settings": "3.1.2",
|
||||
"electron-updater": "2.15.0",
|
||||
"node-hid": "0.5.4",
|
||||
"sudo-prompt": "7.0.0",
|
||||
"tmp": "0.0.33",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ipcMain } from 'electron';
|
||||
import { ConfigurationReply, DeviceConnectionState, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
||||
import { ConfigurationReply, DeviceConnectionState, HardwareModules, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
||||
import { snooze, UhkHidDevice, UhkOperations } from 'uhk-usb';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
@@ -73,10 +73,15 @@ export class DeviceService {
|
||||
try {
|
||||
await this.device.waitUntilKeyboardBusy();
|
||||
const result = await this.operations.loadConfigurations();
|
||||
const modules: HardwareModules = {
|
||||
leftModuleInfo: await this.operations.getLeftModuleVersionInfo(),
|
||||
rightModuleInfo: await this.operations.getRightModuleVersionInfo()
|
||||
};
|
||||
|
||||
response = {
|
||||
success: true,
|
||||
...result
|
||||
...result,
|
||||
modules
|
||||
};
|
||||
} catch (error) {
|
||||
response = {
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
"url": "git@github.com:UltimateHackingKeyboard/agent.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build": "run-s tsc copy:*",
|
||||
"tsc": "tsc",
|
||||
"copy:scancodes": "copyfiles ./src/config-serializer/config-items/scancodes.json dist",
|
||||
"copy:secondary-roles": "copyfiles ./src/config-serializer/config-items/secondaryRole.json dist",
|
||||
"test": "jasmine-ts --config=jasmine.json",
|
||||
"coverage": "nyc jasmine-ts --config=jasmine.json"
|
||||
},
|
||||
|
||||
@@ -9,3 +9,6 @@ export * from './macro';
|
||||
export * from './module';
|
||||
export * from './module-configuration';
|
||||
export * from './user-configuration';
|
||||
|
||||
export const SCANCODES = require('./scancodes.json');
|
||||
export const SECONDARY_ROLES = require('./secondaryRole.json');
|
||||
|
||||
@@ -8,6 +8,7 @@ import { SwitchKeymapAction, UnresolvedSwitchKeymapAction } from './switch-keyma
|
||||
import { MouseAction } from './mouse-action';
|
||||
import { PlayMacroAction } from './play-macro-action';
|
||||
import { NoneAction } from './none-action';
|
||||
import { isScancodeExists } from '../scancode-checker';
|
||||
|
||||
export class Helper {
|
||||
|
||||
@@ -26,7 +27,12 @@ export class Helper {
|
||||
buffer.backtrack();
|
||||
|
||||
if (keyActionFirstByte >= KeyActionId.KeystrokeAction && keyActionFirstByte < KeyActionId.LastKeystrokeAction) {
|
||||
return new KeystrokeAction().fromBinary(buffer);
|
||||
const keystrokeAction = new KeystrokeAction().fromBinary(buffer);
|
||||
if (isValidKeystrokeAction(keystrokeAction)) {
|
||||
return keystrokeAction;
|
||||
}
|
||||
|
||||
return new NoneAction();
|
||||
}
|
||||
|
||||
switch (keyActionFirstByte) {
|
||||
@@ -68,8 +74,14 @@ export class Helper {
|
||||
}
|
||||
|
||||
switch (keyAction.keyActionType) {
|
||||
case keyActionType.KeystrokeAction:
|
||||
return new KeystrokeAction().fromJsonObject(keyAction);
|
||||
case keyActionType.KeystrokeAction: {
|
||||
const keystrokeAction = new KeystrokeAction().fromJsonObject(keyAction);
|
||||
if (isValidKeystrokeAction(keystrokeAction)) {
|
||||
return keystrokeAction;
|
||||
}
|
||||
|
||||
return new NoneAction();
|
||||
}
|
||||
case keyActionType.SwitchLayerAction:
|
||||
return new SwitchLayerAction().fromJsonObject(keyAction);
|
||||
case keyActionType.SwitchKeymapAction:
|
||||
@@ -85,3 +97,9 @@ export class Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isValidKeystrokeAction(keystrokeAction: KeystrokeAction): boolean {
|
||||
return keystrokeAction.hasSecondaryRoleAction() ||
|
||||
keystrokeAction.hasActiveModifier() ||
|
||||
keystrokeAction.hasScancode() && isScancodeExists(keystrokeAction.scancode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { SCANCODES } from './';
|
||||
|
||||
let scancodeMap: Map<number, any>;
|
||||
|
||||
export function isScancodeExists(scancode: number): boolean {
|
||||
if (!scancodeMap) {
|
||||
fillScancodeMap();
|
||||
}
|
||||
|
||||
return scancodeMap.has(scancode);
|
||||
}
|
||||
|
||||
function fillScancodeMap(): void {
|
||||
scancodeMap = new Map<number, any>();
|
||||
|
||||
for (const scanGroup of SCANCODES) {
|
||||
for (const child of scanGroup.children) {
|
||||
if (child.additional && child.additional.scancode) {
|
||||
scancodeMap.set(child.additional.scancode, child);
|
||||
}
|
||||
else {
|
||||
scancodeMap.set(Number.parseInt(child.id), child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,7 +242,7 @@
|
||||
"text": "Delete"
|
||||
},
|
||||
{
|
||||
"id": "118",
|
||||
"id": "101",
|
||||
"text": "Menu"
|
||||
},
|
||||
{
|
||||
@@ -1,6 +1,9 @@
|
||||
import { HardwareModules } from './hardware-modules';
|
||||
|
||||
export interface ConfigurationReply {
|
||||
success: boolean;
|
||||
userConfiguration?: string;
|
||||
hardwareConfiguration?: string;
|
||||
modules?: HardwareModules;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
4
packages/uhk-common/src/models/hardware-module-info.ts
Normal file
4
packages/uhk-common/src/models/hardware-module-info.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface HardwareModuleInfo {
|
||||
firmwareVersion?: string;
|
||||
moduleProtocolVersion?: string;
|
||||
}
|
||||
6
packages/uhk-common/src/models/hardware-modules.ts
Normal file
6
packages/uhk-common/src/models/hardware-modules.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { HardwareModuleInfo } from './hardware-module-info';
|
||||
|
||||
export interface HardwareModules {
|
||||
leftModuleInfo?: HardwareModuleInfo;
|
||||
rightModuleInfo?: HardwareModuleInfo;
|
||||
}
|
||||
@@ -5,3 +5,5 @@ export * from './app-start-info';
|
||||
export * from './configuration-reply';
|
||||
export * from './version-information';
|
||||
export * from './device-connection-state';
|
||||
export * from './hardware-modules';
|
||||
export * from './hardware-module-info';
|
||||
|
||||
@@ -22,7 +22,7 @@ export enum UsbCommand {
|
||||
GetDebugBuffer = 0x0b,
|
||||
GetAdcValue = 0x0c,
|
||||
SetLedPwmBrightness = 0x0d,
|
||||
GetModuleProperties = 0x0e
|
||||
GetModuleProperty = 0x0e
|
||||
}
|
||||
|
||||
export enum EepromOperation {
|
||||
@@ -81,3 +81,7 @@ export enum KbootCommands {
|
||||
ping = 1,
|
||||
reset = 2
|
||||
}
|
||||
|
||||
export enum ModulePropertyId {
|
||||
protocolVersions = 0
|
||||
}
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { LogService } from 'uhk-common';
|
||||
import { EnumerationModes, EnumerationNameToProductId, KbootCommands, ModuleSlotToI2cAddress, ModuleSlotToId } from './constants';
|
||||
import { HardwareModuleInfo, LogService, UhkBuffer } from 'uhk-common';
|
||||
import {
|
||||
EnumerationModes,
|
||||
EnumerationNameToProductId,
|
||||
KbootCommands,
|
||||
ModulePropertyId,
|
||||
ModuleSlotToI2cAddress,
|
||||
ModuleSlotToId
|
||||
} from './constants';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { UhkBlhost } from './uhk-blhost';
|
||||
@@ -193,6 +200,50 @@ export class UhkOperations {
|
||||
return false;
|
||||
}
|
||||
|
||||
public async getLeftModuleVersionInfo(): Promise<HardwareModuleInfo> {
|
||||
try {
|
||||
this.logService.debug('[DeviceOperation] USB[T]: Read left module version information');
|
||||
|
||||
const command = new Buffer([
|
||||
UsbCommand.GetModuleProperty,
|
||||
ModuleSlotToId.leftHalf,
|
||||
ModulePropertyId.protocolVersions
|
||||
]);
|
||||
|
||||
const buffer = await this.device.write(command);
|
||||
const uhkBuffer = UhkBuffer.fromArray(convertBufferToIntArray(buffer));
|
||||
// skip the first 2 byte
|
||||
uhkBuffer.readUInt16();
|
||||
|
||||
return {
|
||||
moduleProtocolVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`,
|
||||
firmwareVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
this.logService.error('[DeviceOperation] Could not read left module version information', error);
|
||||
}
|
||||
|
||||
return {
|
||||
moduleProtocolVersion: '',
|
||||
firmwareVersion: ''
|
||||
};
|
||||
}
|
||||
|
||||
public async getRightModuleVersionInfo(): Promise<HardwareModuleInfo> {
|
||||
this.logService.debug('[DeviceOperation] USB[T]: Read right module version information');
|
||||
|
||||
const command = new Buffer([UsbCommand.GetProperty, DevicePropertyIds.ProtocolVersions]);
|
||||
const buffer = await this.device.write(command);
|
||||
const uhkBuffer = UhkBuffer.fromArray(convertBufferToIntArray(buffer));
|
||||
// skip the first byte
|
||||
uhkBuffer.readUInt8();
|
||||
|
||||
return {
|
||||
firmwareVersion: `${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}.${uhkBuffer.readUInt16()}`
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* IpcMain handler. Send the UserConfiguration to the UHK Device and send a response with the result.
|
||||
* @param {string} json - UserConfiguration in JSON format
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
<ul class="list-unstyled btn-list">
|
||||
<li>
|
||||
Download device configuration in
|
||||
<span role="button" class="btn-link" (click)="saveConfigurationInJSONFormat()">JSON</span> or
|
||||
<span role="button" class="btn-link" (click)="saveConfigurationInBINFormat()">binary</span> format.
|
||||
<button class="btn btn-default"
|
||||
(click)="exportUserConfiguration($event)">Export device configuration
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<label class="btn btn-default btn-file">
|
||||
Upload device configuration
|
||||
Import device configuration
|
||||
<input type="file"
|
||||
(change)="changeFile($event)">
|
||||
</label>
|
||||
|
||||
@@ -34,6 +34,14 @@ export class DeviceConfigurationComponent {
|
||||
this.store.dispatch(new SaveUserConfigInBinaryFileAction());
|
||||
}
|
||||
|
||||
exportUserConfiguration(event: MouseEvent) {
|
||||
if (event.shiftKey) {
|
||||
this.saveConfigurationInBINFormat();
|
||||
} else {
|
||||
this.saveConfigurationInJSONFormat();
|
||||
}
|
||||
}
|
||||
|
||||
changeFile(event): void {
|
||||
const files = event.srcElement.files;
|
||||
const fileReader = new FileReader();
|
||||
|
||||
@@ -7,30 +7,35 @@
|
||||
<span>Firmware</span>
|
||||
</h1>
|
||||
|
||||
<p><i>
|
||||
<p>
|
||||
Firmware {{ hardwareModules.leftModuleInfo.firmwareVersion }} is running on the left keyboard half.<br>
|
||||
Firmware {{ hardwareModules.rightModuleInfo.firmwareVersion }} is running on the right keyboard half.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<i>
|
||||
Please note that the firmware update process may sometimes fail. If if fails then
|
||||
simply retry until it succeeds. If the left half becomes unresponsive after a failed
|
||||
update then retry and follow the instructions displayed during the update to fix it.
|
||||
We'll make the firmware update process more robust.
|
||||
</i></p>
|
||||
|
||||
<p>
|
||||
Flash firmware {{ (getAgentVersionInfo$ | async).firmwareVersion }} (bundled with Agent)
|
||||
<button class="btn btn-primary"
|
||||
[disabled]="flashFirmwareButtonDisbabled$ | async"
|
||||
(click)="onUpdateFirmware()">Flash firmware
|
||||
</button>
|
||||
</i>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Flash firmware file <input id="firmware-file-select"
|
||||
type="file"
|
||||
[disabled]="flashFirmwareButtonDisbabled$ | async"
|
||||
(change)="changeFile($event)">
|
||||
<button class="btn btn-primary"
|
||||
[disabled]="flashFirmwareButtonDisbabled$ | async"
|
||||
(click)="onUpdateFirmwareWithFile()">Flash firmware
|
||||
(click)="onUpdateFirmware()">
|
||||
Flash firmware {{ (getAgentVersionInfo$ | async).firmwareVersion }} (bundled with Agent)
|
||||
</button>
|
||||
<label class="btn btn-primary btn-file"
|
||||
[class.disabled]="flashFirmwareButtonDisbabled$ | async">
|
||||
Choose firmware file and flash it
|
||||
<input id="firmware-file-select"
|
||||
type="file"
|
||||
accept=".tar.bz2"
|
||||
[disabled]="flashFirmwareButtonDisbabled$ | async"
|
||||
(change)="changeFile($event)">
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,9 +2,16 @@ import { Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { VersionInformation } from 'uhk-common';
|
||||
import { HardwareModules, VersionInformation } from 'uhk-common';
|
||||
|
||||
import { AppState, firmwareOkButtonDisabled, flashFirmwareButtonDisbabled, getAgentVersionInfo, xtermLog } from '../../../store';
|
||||
import {
|
||||
AppState,
|
||||
firmwareOkButtonDisabled,
|
||||
flashFirmwareButtonDisbabled,
|
||||
getAgentVersionInfo,
|
||||
getHardwareModules,
|
||||
xtermLog
|
||||
} from '../../../store';
|
||||
import { UpdateFirmwareAction, UpdateFirmwareOkButtonAction, UpdateFirmwareWithAction } from '../../../store/actions/device';
|
||||
import { XtermLog } from '../../../models/xterm-log';
|
||||
|
||||
@@ -22,8 +29,9 @@ export class DeviceFirmwareComponent implements OnDestroy {
|
||||
xtermLogSubscription: Subscription;
|
||||
getAgentVersionInfo$: Observable<VersionInformation>;
|
||||
firmwareOkButtonDisabled$: Observable<boolean>;
|
||||
hardwareModulesSubscription: Subscription;
|
||||
hardwareModules: HardwareModules;
|
||||
|
||||
arrayBuffer: Uint8Array;
|
||||
@ViewChild('scrollMe') divElement: ElementRef;
|
||||
|
||||
constructor(private store: Store<AppState>) {
|
||||
@@ -38,24 +46,20 @@ export class DeviceFirmwareComponent implements OnDestroy {
|
||||
});
|
||||
this.getAgentVersionInfo$ = store.select(getAgentVersionInfo);
|
||||
this.firmwareOkButtonDisabled$ = store.select(firmwareOkButtonDisabled);
|
||||
this.hardwareModulesSubscription = store.select(getHardwareModules).subscribe(data => {
|
||||
this.hardwareModules = data;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.xtermLogSubscription.unsubscribe();
|
||||
this.hardwareModulesSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
onUpdateFirmware(): void {
|
||||
this.store.dispatch(new UpdateFirmwareAction());
|
||||
}
|
||||
|
||||
onUpdateFirmwareWithFile(): void {
|
||||
if (!this.arrayBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.store.dispatch(new UpdateFirmwareWithAction(Array.prototype.slice.call(this.arrayBuffer)));
|
||||
}
|
||||
|
||||
onOkButtonClick(): void {
|
||||
this.store.dispatch(new UpdateFirmwareOkButtonAction());
|
||||
}
|
||||
@@ -64,14 +68,13 @@ export class DeviceFirmwareComponent implements OnDestroy {
|
||||
const files = event.srcElement.files;
|
||||
|
||||
if (files.length === 0) {
|
||||
this.arrayBuffer = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onloadend = function () {
|
||||
this.arrayBuffer = new Uint8Array(fileReader.result);
|
||||
const arrayBuffer = new Uint8Array(fileReader.result);
|
||||
this.store.dispatch(new UpdateFirmwareWithAction(Array.prototype.slice.call(arrayBuffer)));
|
||||
}.bind(this);
|
||||
fileReader.readAsArrayBuffer(files[0]);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
></select2>
|
||||
<icon name="question-circle"
|
||||
data-toggle="tooltip"
|
||||
title="Looking for a non-US character, but can't find it? Please note that USB keyboards send scancodes, not characters to your computer. Then your operating system translates the scancodes to characters according to your current OS keyboard layout. This means that you have to select the US-equivalent character of the desired key in Agent."
|
||||
title="Looking for a non-US character? Just pick the character of the desired key according to the US layout."
|
||||
data-placement="bottom"></icon>
|
||||
<capture-keystroke-button (capture)="onKeysCapture($event)" tabindex="0"></capture-keystroke-button>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { Select2OptionData, Select2TemplateFunction } from 'ng2-select2';
|
||||
import { KeyAction, KeystrokeAction, KeystrokeType } from 'uhk-common';
|
||||
import { KeyAction, KeystrokeAction, KeystrokeType, SCANCODES, SECONDARY_ROLES } from 'uhk-common';
|
||||
|
||||
import { Tab } from '../tab';
|
||||
import { MapperService } from '../../../../services/mapper.service';
|
||||
@@ -35,8 +35,8 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
id: '0',
|
||||
text: 'None'
|
||||
}];
|
||||
this.scanCodeGroups = this.scanCodeGroups.concat(require('./scancodes.json'));
|
||||
this.secondaryRoleGroups = require('./secondaryRole.json');
|
||||
this.scanCodeGroups = this.scanCodeGroups.concat(SCANCODES);
|
||||
this.secondaryRoleGroups = SECONDARY_ROLES;
|
||||
this.leftModifierSelects = Array(this.leftModifiers.length).fill(false);
|
||||
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
|
||||
this.selectedScancodeOption = this.scanCodeGroups[0];
|
||||
|
||||
@@ -128,12 +128,14 @@
|
||||
<ul [@toggler]="animation['agent']">
|
||||
<li class="sidebar__level-2--item">
|
||||
<div class="sidebar__level-2" [routerLinkActive]="['active']">
|
||||
<a [routerLink]="['/settings']">Settings</a>
|
||||
<a [routerLink]="['/settings']"
|
||||
[class.disabled]="updatingFirmware$ | async">Settings</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="sidebar__level-2--item">
|
||||
<div class="sidebar__level-2" [routerLinkActive]="['active']">
|
||||
<a [routerLink]="['/about']">About</a>
|
||||
<a [routerLink]="['/about']"
|
||||
[class.disabled]="updatingFirmware$ | async">About</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
a {
|
||||
color: #333;
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
|
||||
// General list styles for the sidebar-menu.
|
||||
@@ -112,6 +116,10 @@ ul {
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ export class CaptureService {
|
||||
this.mapping.set(88, 27); // X
|
||||
this.mapping.set(89, 28); // Y
|
||||
this.mapping.set(90, 29); // Z
|
||||
this.mapping.set(93, 118); // Menu
|
||||
this.mapping.set(93, 101); // Menu
|
||||
this.mapping.set(96, 98); // Num pad 0
|
||||
this.mapping.set(97, 89); // Num pad 1
|
||||
this.mapping.set(98, 90); // Num pad 2
|
||||
|
||||
@@ -190,6 +190,7 @@ export class MapperService {
|
||||
this.basicScanCodeTextMap.set(98, ['Insert', '0']);
|
||||
this.basicScanCodeTextMap.set(99, ['Del', '.']);
|
||||
this.basicScanCodeTextMap.set(100, ['ISO key', '|']);
|
||||
this.basicScanCodeTextMap.set(101, ['Menu']);
|
||||
this.basicScanCodeTextMap.set(104, ['F13']);
|
||||
this.basicScanCodeTextMap.set(105, ['F14']);
|
||||
this.basicScanCodeTextMap.set(106, ['F15']);
|
||||
@@ -202,7 +203,6 @@ export class MapperService {
|
||||
this.basicScanCodeTextMap.set(113, ['F22']);
|
||||
this.basicScanCodeTextMap.set(114, ['F23']);
|
||||
this.basicScanCodeTextMap.set(115, ['F24']);
|
||||
this.basicScanCodeTextMap.set(118, ['Menu']);
|
||||
this.basicScanCodeTextMap.set(176, ['00']);
|
||||
this.basicScanCodeTextMap.set(177, ['000']);
|
||||
|
||||
@@ -236,7 +236,7 @@ export class MapperService {
|
||||
this.basicScancodeIcons.set(80, 'icon-kbd__mod--arrow-left');
|
||||
this.basicScancodeIcons.set(81, 'icon-kbd__mod--arrow-down');
|
||||
this.basicScancodeIcons.set(82, 'icon-kbd__mod--arrow-up');
|
||||
this.basicScancodeIcons.set(118, 'icon-kbd__mod--menu');
|
||||
this.basicScancodeIcons.set(101, 'icon-kbd__mod--menu');
|
||||
|
||||
this.mediaScancodeIcons = new Map<number, string>();
|
||||
this.mediaScancodeIcons.set(138, 'icon-kbd__fn--browser');
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { DeviceConnectionState, IpcResponse, type } from 'uhk-common';
|
||||
import { HardwareModules } from '../../../../../uhk-common/src/models';
|
||||
|
||||
const PREFIX = '[device] ';
|
||||
|
||||
@@ -22,7 +23,8 @@ export const ActionTypes = {
|
||||
UPDATE_FIRMWARE_REPLY: type(PREFIX + 'update firmware reply'),
|
||||
UPDATE_FIRMWARE_SUCCESS: type(PREFIX + 'update firmware success'),
|
||||
UPDATE_FIRMWARE_FAILED: type(PREFIX + 'update firmware failed'),
|
||||
UPDATE_FIRMWARE_OK_BUTTON: type(PREFIX + 'update firmware ok button click')
|
||||
UPDATE_FIRMWARE_OK_BUTTON: type(PREFIX + 'update firmware ok button click'),
|
||||
MODULES_INFO_LOADED: type(PREFIX + 'module info loaded')
|
||||
};
|
||||
|
||||
export class SetPrivilegeOnLinuxAction implements Action {
|
||||
@@ -114,6 +116,13 @@ export class ResetMouseSpeedSettingsAction implements Action {
|
||||
type = ActionTypes.RESET_MOUSE_SPEED_SETTINGS;
|
||||
}
|
||||
|
||||
export class HardwareModulesLoadedAction implements Action {
|
||||
type = ActionTypes.MODULES_INFO_LOADED;
|
||||
|
||||
constructor(public payload: HardwareModules) {
|
||||
}
|
||||
}
|
||||
|
||||
export type Actions
|
||||
= SetPrivilegeOnLinuxAction
|
||||
| SetPrivilegeOnLinuxReplyAction
|
||||
@@ -132,4 +141,5 @@ export type Actions
|
||||
| UpdateFirmwareSuccessAction
|
||||
| UpdateFirmwareFailedAction
|
||||
| UpdateFirmwareOkButtonAction
|
||||
| HardwareModulesLoadedAction
|
||||
;
|
||||
|
||||
@@ -43,7 +43,7 @@ import {
|
||||
ShowNotificationAction,
|
||||
UndoLastAction
|
||||
} from '../actions/app';
|
||||
import { ShowSaveToKeyboardButtonAction } from '../actions/device';
|
||||
import { HardwareModulesLoadedAction, ShowSaveToKeyboardButtonAction } from '../actions/device';
|
||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
||||
import { UploadFileData } from '../../models/upload-file-data';
|
||||
@@ -173,6 +173,8 @@ export class UserConfigEffects {
|
||||
}));
|
||||
}
|
||||
|
||||
result.push(new HardwareModulesLoadedAction(data.modules));
|
||||
|
||||
this.router.navigate(['/']);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -77,3 +77,4 @@ export const xtermLog = createSelector(deviceState, fromDevice.xtermLog);
|
||||
export const firmwareOkButtonDisabled = createSelector(deviceState, fromDevice.firmwareOkButtonDisabled);
|
||||
// tslint:disable-next-line: max-line-length
|
||||
export const flashFirmwareButtonDisbabled = createSelector(runningInElectron, deviceState, (electron, state: fromDevice.State) => !electron || state.updatingFirmware);
|
||||
export const getHardwareModules = createSelector(deviceState, fromDevice.getHardwareModules);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { HardwareModules } from 'uhk-common';
|
||||
|
||||
import {
|
||||
ActionTypes,
|
||||
ConnectionStateChangedAction,
|
||||
HardwareModulesLoadedAction,
|
||||
SaveConfigurationAction,
|
||||
UpdateFirmwareFailedAction
|
||||
} from '../actions/device';
|
||||
@@ -16,6 +18,7 @@ export interface State {
|
||||
saveToKeyboard: ProgressButtonState;
|
||||
updatingFirmware: boolean;
|
||||
firmwareUpdateFinished: boolean;
|
||||
modules: HardwareModules;
|
||||
log: Array<XtermLog>;
|
||||
}
|
||||
|
||||
@@ -25,6 +28,15 @@ export const initialState: State = {
|
||||
saveToKeyboard: initProgressButtonState,
|
||||
updatingFirmware: false,
|
||||
firmwareUpdateFinished: false,
|
||||
modules: {
|
||||
leftModuleInfo: {
|
||||
firmwareVersion: '',
|
||||
moduleProtocolVersion: ''
|
||||
},
|
||||
rightModuleInfo: {
|
||||
firmwareVersion: ''
|
||||
}
|
||||
},
|
||||
log: [{message: '', cssClass: XtermCssClass.standard}]
|
||||
};
|
||||
|
||||
@@ -148,6 +160,13 @@ export function reducer(state = initialState, action: Action) {
|
||||
log: [...state.log, logEntry]
|
||||
};
|
||||
}
|
||||
|
||||
case ActionTypes.MODULES_INFO_LOADED:
|
||||
return {
|
||||
...state,
|
||||
modules: (action as HardwareModulesLoadedAction).payload
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -159,3 +178,4 @@ export const hasDevicePermission = (state: State) => state.hasPermission;
|
||||
export const getSaveToKeyboardState = (state: State) => state.saveToKeyboard;
|
||||
export const xtermLog = (state: State) => state.log;
|
||||
export const firmwareOkButtonDisabled = (state: State) => !state.firmwareUpdateFinished;
|
||||
export const getHardwareModules = (state: State) => state.modules;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
const uhk = require('./uhk');
|
||||
|
||||
(async function() {
|
||||
const device = uhk.getUhkDevice();
|
||||
const sendData = new Buffer([uhk.usbCommands.applyConfig]);
|
||||
device.write(uhk.getTransferData(sendData));
|
||||
const response = Buffer.from(device.readSync());
|
||||
console.log(response);
|
||||
uhk.applyConfig(device);
|
||||
})();
|
||||
|
||||
@@ -9,23 +9,5 @@ if (eepromTransfer === undefined) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const device = uhk.getUhkDevice();
|
||||
device.write(uhk.getTransferData(new Buffer([uhk.usbCommands.launchEepromTransfer, eepromTransfer.operation, eepromTransfer.configBuffer])));
|
||||
const buffer = Buffer.from(device.readSync());
|
||||
const responseCode = buffer[0];
|
||||
if (responseCode !== 0) {
|
||||
console.error(`Write user config to eeprom failed. Response code: ${responseCode}`);
|
||||
process.exit(1);
|
||||
}
|
||||
// const buffer = await uhk.writeDevice(device, [uhk.usbCommands.launchEepromTransfer, eepromTransfer.operation, eepromTransfer.configBuffer]);
|
||||
|
||||
function waitUntilKeyboardBusy() {
|
||||
|
||||
device.write(uhk.getTransferData(new Buffer([uhk.usbCommands.getDeviceState])));
|
||||
const keyboardStateBuffer = Buffer.from(device.readSync());
|
||||
|
||||
if (keyboardStateBuffer[1] === 1) {
|
||||
setTimeout(waitUntilKeyboardBusy, 200);
|
||||
}
|
||||
}
|
||||
|
||||
waitUntilKeyboardBusy();
|
||||
|
||||
40
packages/usb/factory-update.js
Executable file
40
packages/usb/factory-update.js
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env node
|
||||
const fs = require('fs');
|
||||
const program = require('commander');
|
||||
const uhk = require('./uhk')
|
||||
require('shelljs/global');
|
||||
|
||||
(async function() {
|
||||
config.fatal = true;
|
||||
|
||||
program
|
||||
.usage(`firmwarePath`)
|
||||
.parse(process.argv);
|
||||
|
||||
if (program.args.length < 1) {
|
||||
console.error('No firmware path specified.');
|
||||
exit(1);
|
||||
}
|
||||
const firmwarePath = program.args[0];
|
||||
|
||||
if (program.args.length < 2) {
|
||||
console.error('No layout specified.');
|
||||
exit(1);
|
||||
}
|
||||
const layout = program.args[1];
|
||||
if (!['ansi', 'iso'].includes(layout)) {
|
||||
console.error('The specified layout is neither ansi nor iso.');
|
||||
exit(1);
|
||||
}
|
||||
const isIso = layout === 'iso';
|
||||
|
||||
config.verbose = true;
|
||||
await uhk.updateFirmwares(firmwarePath);
|
||||
const device = uhk.getUhkDevice();
|
||||
const configBuffer = fs.readFileSync(`${firmwarePath}/devices/uhk60-right/config.bin`);
|
||||
await uhk.writeUca(device, configBuffer);
|
||||
await uhk.writeHca(device, isIso);
|
||||
await uhk.switchKeymap(device, 'TES');
|
||||
console.log('All done!')
|
||||
config.verbose = false;
|
||||
})();
|
||||
@@ -1,14 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
const uhk = require('./uhk');
|
||||
|
||||
(async function() {
|
||||
const device = uhk.getUhkDevice();
|
||||
|
||||
function getModuleState() {
|
||||
const payload = new Buffer([uhk.usbCommands.getModuleProperty, 1]);
|
||||
console.log('Sending ', uhk.bufferToString(payload));
|
||||
device.write(uhk.getTransferData(payload));
|
||||
const receivedBuffer = device.readSync();
|
||||
console.log('Received', uhk.bufferToString(receivedBuffer));
|
||||
setTimeout(getModuleState, 500)
|
||||
}
|
||||
|
||||
getModuleState();
|
||||
await uhk.getModuleProperty(device, 1, uhk.modulePropertyIds.protocolVersions);
|
||||
})();
|
||||
|
||||
15
packages/usb/switch-keymap.js
Executable file
15
packages/usb/switch-keymap.js
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env node
|
||||
const uhk = require('./uhk');
|
||||
|
||||
(async function() {
|
||||
const keymapAbbreviation = process.argv[2];
|
||||
|
||||
if (keymapAbbreviation === undefined) {
|
||||
console.log('Usage: switch-keymap.js keymapName');
|
||||
return;
|
||||
}
|
||||
|
||||
const device = uhk.getUhkDevice();
|
||||
const sendData = await uhk.switchKeymap(device, keymapAbbreviation);
|
||||
console.log(sendData)
|
||||
})();
|
||||
@@ -1,7 +1,24 @@
|
||||
const util = require('util');
|
||||
const HID = require('node-hid');
|
||||
// const debug = process.env.DEBUG;
|
||||
const debug = true;
|
||||
const {HardwareConfiguration, UhkBuffer} = require('uhk-common');
|
||||
const {getTransferBuffers, ConfigBufferId, UhkHidDevice, UsbCommand} = require('uhk-usb');
|
||||
const Logger = require('./logger');
|
||||
const debug = process.env.DEBUG;
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const kbootCommandIdToName = {
|
||||
0: 'idle',
|
||||
1: 'ping',
|
||||
2: 'reset',
|
||||
};
|
||||
|
||||
const eepromOperationIdToName = {
|
||||
0: 'read',
|
||||
1: 'write',
|
||||
}
|
||||
|
||||
function bufferToString(buffer) {
|
||||
let str = '';
|
||||
@@ -28,11 +45,27 @@ function uint32ToArray(value) {
|
||||
}
|
||||
|
||||
function writeDevice(device, data, options={}) {
|
||||
device.write(getTransferData(new Buffer(data)));
|
||||
const dataBuffer = new Buffer(data);
|
||||
if (!options.noDebug) {
|
||||
writeLog('W: ', dataBuffer);
|
||||
}
|
||||
device.write(getTransferData(dataBuffer));
|
||||
if (options.noRead) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return util.promisify(device.read.bind(device))();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
device.read((err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
if (!options.noDebug) {
|
||||
writeLog('R: ', data);
|
||||
}
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getUhkDevice() {
|
||||
@@ -119,12 +152,18 @@ function execRetry(command) {
|
||||
} while(code && --remainingRetries);
|
||||
}
|
||||
|
||||
let configBufferIds = {
|
||||
const configBufferIds = {
|
||||
hardwareConfig: 0,
|
||||
stagingUserConfig: 1,
|
||||
validatedUserConfig: 2,
|
||||
};
|
||||
|
||||
const configBufferIdToName = {
|
||||
0: 'hardwareConfig',
|
||||
1: 'stagingUserConfig',
|
||||
2: 'validatedUserConfig',
|
||||
}
|
||||
|
||||
let eepromOperations = {
|
||||
read: 0,
|
||||
write: 1,
|
||||
@@ -199,14 +238,24 @@ function reenumerate(enumerationMode) {
|
||||
};
|
||||
|
||||
async function sendKbootCommandToModule(device, kbootCommandId, i2cAddress) {
|
||||
writeLog(`T: sendKbootCommandToModule kbootCommandId:${kbootCommandIdToName[kbootCommandId]} i2cAddress:${i2cAddress}`);
|
||||
return await uhk.writeDevice(device, [uhk.usbCommands.sendKbootCommandToModule, kbootCommandId, parseInt(i2cAddress)])
|
||||
};
|
||||
|
||||
async function jumpToModuleBootloader(device, moduleSlotId) {
|
||||
writeLog(`T: jumpToModuleBootloader moduleSlotId:${moduleSlotId}`);
|
||||
await uhk.writeDevice(device, [uhk.usbCommands.jumpToModuleBootloader, moduleSlotId]);
|
||||
};
|
||||
|
||||
async function switchKeymap(device, keymapAbbreviation) {
|
||||
writeLog(`T: switchKeymap keymapAbbreviation:${keymapAbbreviation}`);
|
||||
const keymapAbbreviationAscii = keymapAbbreviation.split('').map(char => char.charCodeAt(0));
|
||||
const payload = [uhk.usbCommands.switchKeymap, keymapAbbreviation.length, ...keymapAbbreviationAscii];
|
||||
return await uhk.writeDevice(device, payload);
|
||||
}
|
||||
|
||||
async function waitForKbootIdle(device) {
|
||||
writeLog(`T: waitForKbootIdle`);
|
||||
const intervalMs = 100;
|
||||
const pingMessageInterval = 500;
|
||||
let timeoutMs = 10000;
|
||||
@@ -256,12 +305,98 @@ async function updateModuleFirmware(i2cAddress, moduleSlotId, firmwareImage) {
|
||||
await uhk.reenumerate('normalKeyboard');
|
||||
device = uhk.getUhkDevice();
|
||||
await uhk.sendKbootCommandToModule(device, uhk.kbootCommands.reset, i2cAddress);
|
||||
await sleep(1000);
|
||||
await uhk.sendKbootCommandToModule(device, uhk.kbootCommands.idle, i2cAddress);
|
||||
device.close();
|
||||
config.verbose = false;
|
||||
echo('Firmware updated successfully.');
|
||||
};
|
||||
|
||||
async function updateFirmwares(firmwarePath) {
|
||||
console.log('Updating right firmware');
|
||||
await uhk.updateDeviceFirmware(`${firmwarePath}/devices/uhk60-right/firmware.hex`, 'hex');
|
||||
await uhk.reenumerate('normalKeyboard');
|
||||
console.log('Updating left firmware');
|
||||
await uhk.updateModuleFirmware(uhk.moduleSlotToI2cAddress.leftHalf, uhk.moduleSlotToId.leftHalf, `${firmwarePath}/modules/uhk60-left.bin`);
|
||||
}
|
||||
|
||||
async function writeConfig(device, configBuffer, isHardwareConfig) {
|
||||
writeLog(`T: writeConfig isHardwareConfig:${isHardwareConfig}`);
|
||||
const chunkSize = 60;
|
||||
let offset = 0;
|
||||
let chunkSizeToRead;
|
||||
let buffer = await uhk.writeDevice(device, [uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.configSizes]);
|
||||
const hardwareConfigMaxSize = getUint16(buffer, 1);
|
||||
const userConfigMaxSize = getUint16(buffer, 3);
|
||||
const configMaxSize = isHardwareConfig ? hardwareConfigMaxSize : userConfigMaxSize;
|
||||
const configSize = Math.min(configMaxSize, configBuffer.length);
|
||||
|
||||
writeLog('WR: ...');
|
||||
while (offset < configSize) {
|
||||
const usbCommand = isHardwareConfig ? uhk.usbCommands.writeHardwareConfig : uhk.usbCommands.writeStagingUserConfig;
|
||||
chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
||||
|
||||
if (chunkSizeToRead === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = [
|
||||
usbCommand, chunkSizeToRead, offset & 0xff, offset >> 8,
|
||||
...configBuffer.slice(offset, offset+chunkSizeToRead)
|
||||
];
|
||||
await uhk.writeDevice(device, buffer, {noDebug:true})
|
||||
offset += chunkSizeToRead;
|
||||
}
|
||||
}
|
||||
|
||||
async function applyConfig(device) {
|
||||
writeLog(`T: applyConfig`);
|
||||
await uhk.writeDevice(device, [uhk.usbCommands.applyConfig]);
|
||||
}
|
||||
|
||||
async function launchEepromTransfer(device, operation, configBufferId) {
|
||||
writeLog(`T: launchEepromTransfer operation:${eepromOperationIdToName[operation]}`);
|
||||
const buffer = await uhk.writeDevice(device, [uhk.usbCommands.launchEepromTransfer, operation, configBufferId]);
|
||||
isBusy = true;
|
||||
writeLog(`T: getDeviceState`);
|
||||
do {
|
||||
const buffer = await uhk.writeDevice(device, [uhk.usbCommands.getDeviceState]);
|
||||
isBusy = buffer[1] === 1;
|
||||
} while (isBusy);
|
||||
};
|
||||
|
||||
async function writeUca(device, configBuffer) {
|
||||
await uhk.writeConfig(device, configBuffer, false);
|
||||
await uhk.applyConfig(device);
|
||||
await uhk.launchEepromTransfer(device, uhk.eepromOperations.write, configBufferIds.validatedUserConfig);
|
||||
}
|
||||
|
||||
async function writeHca(device, isIso) {
|
||||
const hardwareConfig = new HardwareConfiguration();
|
||||
|
||||
hardwareConfig.signature = 'UHK';
|
||||
hardwareConfig.majorVersion = 1;
|
||||
hardwareConfig.minorVersion = 0;
|
||||
hardwareConfig.patchVersion = 0;
|
||||
hardwareConfig.brandId = 0;
|
||||
hardwareConfig.deviceId = 1;
|
||||
hardwareConfig.uniqueId = Math.floor(2**32 * Math.random());
|
||||
hardwareConfig.isVendorModeOn = false;
|
||||
hardwareConfig.isIso = isIso;
|
||||
|
||||
const logger = new Logger();
|
||||
const hardwareBuffer = new UhkBuffer();
|
||||
hardwareConfig.toBinary(hardwareBuffer);
|
||||
const buffer = hardwareBuffer.getBufferContent();
|
||||
|
||||
await uhk.writeConfig(device, buffer, true);
|
||||
await uhk.launchEepromTransfer(device, uhk.eepromOperations.write, configBufferIds.hardwareConfig);
|
||||
}
|
||||
|
||||
async function getModuleProperty(device, slotId, moduleProperty) {
|
||||
await writeDevice(device, [uhk.usbCommands.getModuleProperty, slotId, moduleProperty]);
|
||||
}
|
||||
|
||||
uhk = exports = module.exports = moduleExports = {
|
||||
bufferToString,
|
||||
getUint16,
|
||||
@@ -279,8 +414,16 @@ uhk = exports = module.exports = moduleExports = {
|
||||
reenumerate,
|
||||
sendKbootCommandToModule,
|
||||
jumpToModuleBootloader,
|
||||
switchKeymap,
|
||||
waitForKbootIdle,
|
||||
updateModuleFirmware,
|
||||
updateFirmwares,
|
||||
writeConfig,
|
||||
applyConfig,
|
||||
launchEepromTransfer,
|
||||
writeUca,
|
||||
writeHca,
|
||||
getModuleProperty,
|
||||
usbCommands: {
|
||||
getDeviceProperty : 0x00,
|
||||
reenumerate : 0x01,
|
||||
@@ -299,6 +442,7 @@ uhk = exports = module.exports = moduleExports = {
|
||||
getModuleProperty : 0x0e,
|
||||
getSlaveI2cErrors : 0x0f,
|
||||
setI2cBaudRate : 0x10,
|
||||
switchKeymap : 0x11,
|
||||
},
|
||||
enumerationModes: {
|
||||
bootloader: 0,
|
||||
@@ -332,24 +476,6 @@ uhk = exports = module.exports = moduleExports = {
|
||||
},
|
||||
configBufferIds,
|
||||
eepromOperations,
|
||||
eepromTransfer: {
|
||||
readHardwareConfig: {
|
||||
operation: eepromOperations.read,
|
||||
configBuffer: configBufferIds.hardwareConfig,
|
||||
},
|
||||
writeHardwareConfig: {
|
||||
operation: eepromOperations.write,
|
||||
configBuffer:configBufferIds.hardwareConfig,
|
||||
},
|
||||
readUserConfig: {
|
||||
operation: eepromOperations.read,
|
||||
configBuffer: configBufferIds.validatedUserConfig,
|
||||
},
|
||||
writeUserConfig: {
|
||||
operation: eepromOperations.write,
|
||||
configBuffer: configBufferIds.validatedUserConfig,
|
||||
},
|
||||
},
|
||||
kbootCommands: {
|
||||
idle: 0,
|
||||
ping: 1,
|
||||
@@ -395,7 +521,11 @@ function writeLog(prefix, buffer) {
|
||||
if (!debug) {
|
||||
return;
|
||||
}
|
||||
if (buffer) {
|
||||
console.log(prefix + bufferToString(buffer))
|
||||
} else {
|
||||
console.log(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
function checkModuleSlot(moduleSlot, mapping) {
|
||||
|
||||
@@ -18,7 +18,7 @@ const firmwarePath = program.args[0];
|
||||
const layout = program.args[1];
|
||||
|
||||
config.verbose = true;
|
||||
exec(`${__dirname}/update-all-firmwares.js --overwrite-user-config ${firmwarePath}`);
|
||||
exec(`${__dirname}/update-firmwares.js --overwrite-user-config ${firmwarePath}`);
|
||||
exec(`${__dirname}/write-hca.js ${layout}`);
|
||||
config.verbose = false;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
const fs = require('fs');
|
||||
const program = require('commander');
|
||||
const tmp = require('tmp');
|
||||
const decompress = require('decompress');
|
||||
@@ -29,16 +30,14 @@ require('shelljs/global');
|
||||
firmwarePath = tmpObj.name;
|
||||
}
|
||||
config.verbose = true;
|
||||
console.log('Updating right firmware');
|
||||
await uhk.updateDeviceFirmware(`${firmwarePath}/devices/uhk60-right/firmware.hex`, 'hex');
|
||||
await uhk.reenumerate('normalKeyboard');
|
||||
console.log('Updating left firmware');
|
||||
await uhk.updateModuleFirmware(uhk.moduleSlotToI2cAddress.leftHalf, uhk.moduleSlotToId.leftHalf, `${firmwarePath}/modules/uhk60-left.bin`);
|
||||
await uhk.updateFirmwares(firmwarePath);
|
||||
|
||||
if (program.overwriteUserConfig) {
|
||||
exec(`${__dirname}/write-config.js ${firmwarePath}/devices/uhk60-right/config.bin`);
|
||||
exec(`${__dirname}/apply-config.js`);
|
||||
exec(`${__dirname}/eeprom.js writeUserConfig`);
|
||||
const device = uhk.getUhkDevice();
|
||||
const configBuffer = fs.readFileSync(`${firmwarePath}/devices/uhk60-right/config.bin`);
|
||||
await uhk.writeConfig(device, configBuffer, false);
|
||||
await uhk.applyConfig(device);
|
||||
await uhk.launchEepromTransfer(device, uhk.eepromOperations.write, uhk.eepromTransfer.writeUserConfig);
|
||||
}
|
||||
|
||||
config.verbose = false;
|
||||
@@ -2,6 +2,8 @@
|
||||
const program = require('commander');
|
||||
const fs = require('fs');
|
||||
const uhk = require('./uhk');
|
||||
|
||||
(async function() {
|
||||
const device = uhk.getUhkDevice();
|
||||
require('shelljs/global');
|
||||
|
||||
@@ -16,36 +18,9 @@ if (program.args.length == 0) {
|
||||
}
|
||||
|
||||
const configBin = program.args[0];
|
||||
const chunkSize = 60;
|
||||
const isHardwareConfig = program.hardwareConfig;
|
||||
const configTypeString = isHardwareConfig ? 'hardware' : 'user';
|
||||
let offset = 0;
|
||||
let configBuffer = fs.readFileSync(configBin);
|
||||
let chunkSizeToRead;
|
||||
const configBuffer = fs.readFileSync(configBin);
|
||||
|
||||
const payload = new Buffer([uhk.usbCommands.getDeviceProperty, uhk.devicePropertyIds.configSizes]);
|
||||
|
||||
device.write(uhk.getTransferData(payload));
|
||||
let buffer = Buffer.from(device.readSync());
|
||||
const hardwareConfigMaxSize = buffer[1] + (buffer[2]<<8);
|
||||
const userConfigMaxSize = buffer[3] + (buffer[4]<<8);
|
||||
const configMaxSize = isHardwareConfig ? hardwareConfigMaxSize : userConfigMaxSize;
|
||||
const configSize = Math.min(configMaxSize, configBuffer.length);
|
||||
|
||||
while (offset < configSize) {
|
||||
const usbCommand = isHardwareConfig ? uhk.usbCommands.writeHardwareConfig : uhk.usbCommands.writeStagingUserConfig;
|
||||
chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
||||
|
||||
if (chunkSizeToRead === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = Buffer.concat([
|
||||
new Buffer([usbCommand, chunkSizeToRead, offset & 0xff, offset >> 8]),
|
||||
configBuffer.slice(offset, offset+chunkSizeToRead)
|
||||
]);
|
||||
|
||||
device.write(uhk.getTransferData(buffer));
|
||||
device.readSync();
|
||||
offset += chunkSizeToRead;
|
||||
}
|
||||
await uhk.writeUserConfig(device, configBuffer, isHardwareConfig);
|
||||
})();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
const {HardwareConfiguration, UhkBuffer} = require('uhk-common');
|
||||
const {EepromTransfer, getTransferBuffers, ConfigBufferId, UhkHidDevice, UsbCommand} = require('uhk-usb');
|
||||
const Logger = require('./logger');
|
||||
const uhk = require('./uhk');
|
||||
|
||||
if (process.argv.length < 2) {
|
||||
console.log(`use: write-hca {iso|ansi}`);
|
||||
@@ -14,36 +12,7 @@ if (layout !== 'iso' && layout !== 'ansi') {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const hardwareConfig = new HardwareConfiguration();
|
||||
|
||||
hardwareConfig.signature = 'UHK';
|
||||
hardwareConfig.majorVersion = 1;
|
||||
hardwareConfig.minorVersion = 0;
|
||||
hardwareConfig.patchVersion = 0;
|
||||
hardwareConfig.brandId = 0;
|
||||
hardwareConfig.deviceId = 1;
|
||||
hardwareConfig.uniqueId = Math.floor(2**32 * Math.random());
|
||||
hardwareConfig.isVendorModeOn = false;
|
||||
hardwareConfig.isIso = layout === 'iso';
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
async function writeHca() {
|
||||
const device = new UhkHidDevice(logger);
|
||||
const hardwareBuffer = new UhkBuffer();
|
||||
hardwareConfig.toBinary(hardwareBuffer);
|
||||
const buffer = hardwareBuffer.getBufferContent();
|
||||
const fragments = getTransferBuffers(UsbCommand.WriteHardwareConfig, buffer);
|
||||
logger.debug('USB[T]: Write hardware configuration to keyboard');
|
||||
for (const fragment of fragments) {
|
||||
await device.write(fragment);
|
||||
}
|
||||
|
||||
logger.debug('USB[T]: Write hardware configuration to EEPROM');
|
||||
await device.writeConfigToEeprom(ConfigBufferId.hardwareConfig);
|
||||
}
|
||||
|
||||
writeHca()
|
||||
uhk.writeHca(layout === 'iso')
|
||||
.catch((err)=>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user