feat(scripts): Add write-userconfig (#511)
This commit is contained in:
committed by
László Monda
parent
2d416e7668
commit
40b72e8903
@@ -1,16 +1,6 @@
|
|||||||
import { ipcMain } from 'electron';
|
import { ipcMain } from 'electron';
|
||||||
import { ConfigurationReply, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
import { ConfigurationReply, IpcEvents, IpcResponse, LogService } from 'uhk-common';
|
||||||
import {
|
import { Constants, snooze, UhkHidDevice, UhkOperations } from 'uhk-usb';
|
||||||
Constants,
|
|
||||||
convertBufferToIntArray,
|
|
||||||
EepromTransfer,
|
|
||||||
getTransferBuffers,
|
|
||||||
snooze,
|
|
||||||
SystemPropertyIds,
|
|
||||||
UhkHidDevice,
|
|
||||||
UhkOperations,
|
|
||||||
UsbCommand
|
|
||||||
} from 'uhk-usb';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
import { Device, devices } from 'node-hid';
|
import { Device, devices } from 'node-hid';
|
||||||
@@ -93,20 +83,11 @@ export class DeviceService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this.device.waitUntilKeyboardBusy();
|
await this.device.waitUntilKeyboardBusy();
|
||||||
const userConfiguration = await this.loadConfiguration(
|
const result = await this.operations.loadConfigurations();
|
||||||
SystemPropertyIds.MaxUserConfigSize,
|
|
||||||
UsbCommand.ReadUserConfig,
|
|
||||||
'user configuration');
|
|
||||||
|
|
||||||
const hardwareConfiguration = await this.loadConfiguration(
|
|
||||||
SystemPropertyIds.HardwareConfigSize,
|
|
||||||
UsbCommand.ReadHardwareConfig,
|
|
||||||
'hardware configuration');
|
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
success: true,
|
success: true,
|
||||||
userConfiguration,
|
...result
|
||||||
hardwareConfiguration
|
|
||||||
};
|
};
|
||||||
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -121,51 +102,6 @@ export class DeviceService {
|
|||||||
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
event.sender.send(IpcEvents.device.loadConfigurationReply, JSON.stringify(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return with the actual user / hardware fonfiguration from UHK Device
|
|
||||||
* @returns {Promise<Buffer>}
|
|
||||||
*/
|
|
||||||
public async loadConfiguration(property: SystemPropertyIds, config: UsbCommand, configName: string): Promise<string> {
|
|
||||||
let response = [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.logService.debug(`[DeviceService] USB[T]: Read ${configName} size from keyboard`);
|
|
||||||
let configSize = await this.getConfigSizeFromKeyboard(property);
|
|
||||||
const originalConfigSize = configSize;
|
|
||||||
this.logService.debug(`[DeviceService] getConfigSize() configSize: ${configSize}`);
|
|
||||||
const chunkSize = 63;
|
|
||||||
let offset = 0;
|
|
||||||
let configBuffer = new Buffer(0);
|
|
||||||
let firstRead = true;
|
|
||||||
|
|
||||||
this.logService.debug(`[DeviceService] USB[T]: Read ${configName} from keyboard`);
|
|
||||||
while (offset < configSize) {
|
|
||||||
const chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
|
||||||
const writeBuffer = Buffer.from([config, chunkSizeToRead, offset & 0xff, offset >> 8]);
|
|
||||||
const readBuffer = await this.device.write(writeBuffer);
|
|
||||||
configBuffer = Buffer.concat([configBuffer, new Buffer(readBuffer.slice(1, chunkSizeToRead + 1))]);
|
|
||||||
offset += chunkSizeToRead;
|
|
||||||
|
|
||||||
if (firstRead && config === UsbCommand.ReadUserConfig) {
|
|
||||||
firstRead = false;
|
|
||||||
configSize = readBuffer[7] + (readBuffer[8] << 8);
|
|
||||||
this.logService.debug(`[DeviceService] userConfigSize: ${configSize}`);
|
|
||||||
if (originalConfigSize < configSize) {
|
|
||||||
this.logService.debug(`[DeviceService] userConfigSize should never be larger than getConfigSize()! ` +
|
|
||||||
`Overriding configSize with getConfigSize()`);
|
|
||||||
configSize = originalConfigSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response = convertBufferToIntArray(configBuffer);
|
|
||||||
return Promise.resolve(JSON.stringify(response));
|
|
||||||
} catch (error) {
|
|
||||||
const errMsg = `[DeviceService] ${configName} from eeprom error`;
|
|
||||||
this.logService.error(errMsg, error);
|
|
||||||
throw new Error(errMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
this.stopPollTimer();
|
this.stopPollTimer();
|
||||||
@@ -231,27 +167,12 @@ export class DeviceService {
|
|||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the user / hardware configuration size from the UHK Device
|
|
||||||
* @returns {Promise<number>}
|
|
||||||
*/
|
|
||||||
private async getConfigSizeFromKeyboard(property: SystemPropertyIds): Promise<number> {
|
|
||||||
const buffer = await this.device.write(new Buffer([UsbCommand.GetProperty, property]));
|
|
||||||
this.device.close();
|
|
||||||
const configSize = buffer[1] + (buffer[2] << 8);
|
|
||||||
this.logService.debug('[DeviceService] User config size:', configSize);
|
|
||||||
return configSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async saveUserConfiguration(event: Electron.Event, args: Array<string>): Promise<void> {
|
private async saveUserConfiguration(event: Electron.Event, args: Array<string>): Promise<void> {
|
||||||
const response = new IpcResponse();
|
const response = new IpcResponse();
|
||||||
const json = args[0];
|
const json = args[0];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.logService.debug('[DeviceService] USB[T]: Write user configuration to keyboard');
|
await this.operations.saveUserConfiguration(json);
|
||||||
await this.sendUserConfigToKeyboard(json);
|
|
||||||
this.logService.debug('[DeviceService] USB[T]: Write user configuration to EEPROM');
|
|
||||||
await this.device.writeConfigToEeprom(EepromTransfer.WriteUserConfig);
|
|
||||||
|
|
||||||
response.success = true;
|
response.success = true;
|
||||||
}
|
}
|
||||||
@@ -267,23 +188,6 @@ export class DeviceService {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* IpcMain handler. Send the UserConfiguration to the UHK Device and send a response with the result.
|
|
||||||
* @param {string} json - UserConfiguration in JSON format
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private async sendUserConfigToKeyboard(json: string): Promise<void> {
|
|
||||||
const buffer: Buffer = new Buffer(JSON.parse(json).data);
|
|
||||||
const fragments = getTransferBuffers(UsbCommand.UploadUserConfig, buffer);
|
|
||||||
for (const fragment of fragments) {
|
|
||||||
await this.device.write(fragment);
|
|
||||||
}
|
|
||||||
this.logService.debug('[DeviceService] USB[T]: Apply user configuration to keyboard');
|
|
||||||
const applyBuffer = new Buffer([UsbCommand.ApplyConfig]);
|
|
||||||
await this.device.write(applyBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private stopPollTimer(): void {
|
private stopPollTimer(): void {
|
||||||
if (!this.pollTimer$) {
|
if (!this.pollTimer$) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export interface LoadConfigurationsResult {
|
||||||
|
userConfiguration: string;
|
||||||
|
hardwareConfiguration: string;
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import * as fs from 'fs';
|
|||||||
import { UhkBlhost } from './uhk-blhost';
|
import { UhkBlhost } from './uhk-blhost';
|
||||||
import { UhkHidDevice } from './uhk-hid-device';
|
import { UhkHidDevice } from './uhk-hid-device';
|
||||||
import { snooze } from './util';
|
import { snooze } from './util';
|
||||||
|
import { convertBufferToIntArray, EepromTransfer, getTransferBuffers, SystemPropertyIds, UsbCommand } from '../index';
|
||||||
|
import { LoadConfigurationsResult } from './models/load-configurations-result';
|
||||||
|
|
||||||
export class UhkOperations {
|
export class UhkOperations {
|
||||||
constructor(private logService: LogService,
|
constructor(private logService: LogService,
|
||||||
@@ -58,6 +60,121 @@ export class UhkOperations {
|
|||||||
this.logService.debug('[UhkOperations] End flashing left module firmware');
|
this.logService.debug('[UhkOperations] End flashing left module firmware');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return with the actual UserConfiguration from UHK Device
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async loadConfigurations(): Promise<LoadConfigurationsResult> {
|
||||||
|
try {
|
||||||
|
await this.device.waitUntilKeyboardBusy();
|
||||||
|
const userConfiguration = await this.loadConfiguration(
|
||||||
|
SystemPropertyIds.MaxUserConfigSize,
|
||||||
|
UsbCommand.ReadUserConfig,
|
||||||
|
'user configuration');
|
||||||
|
|
||||||
|
const hardwareConfiguration = await this.loadConfiguration(
|
||||||
|
SystemPropertyIds.HardwareConfigSize,
|
||||||
|
UsbCommand.ReadHardwareConfig,
|
||||||
|
'hardware configuration');
|
||||||
|
|
||||||
|
return {
|
||||||
|
userConfiguration,
|
||||||
|
hardwareConfiguration
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
this.device.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return with the actual user / hardware fonfiguration from UHK Device
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async loadConfiguration(property: SystemPropertyIds, config: UsbCommand, configName: string): Promise<string> {
|
||||||
|
let response = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.logService.debug(`[DeviceOperation] USB[T]: Read ${configName} size from keyboard`);
|
||||||
|
let configSize = await this.getConfigSizeFromKeyboard(property);
|
||||||
|
const originalConfigSize = configSize;
|
||||||
|
this.logService.debug(`[DeviceOperation] getConfigSize() configSize: ${configSize}`);
|
||||||
|
const chunkSize = 63;
|
||||||
|
let offset = 0;
|
||||||
|
let configBuffer = new Buffer(0);
|
||||||
|
let firstRead = true;
|
||||||
|
|
||||||
|
this.logService.debug(`[DeviceOperation] USB[T]: Read ${configName} from keyboard`);
|
||||||
|
while (offset < configSize) {
|
||||||
|
const chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
||||||
|
const writeBuffer = Buffer.from([config, chunkSizeToRead, offset & 0xff, offset >> 8]);
|
||||||
|
const readBuffer = await this.device.write(writeBuffer);
|
||||||
|
configBuffer = Buffer.concat([configBuffer, new Buffer(readBuffer.slice(1, chunkSizeToRead + 1))]);
|
||||||
|
offset += chunkSizeToRead;
|
||||||
|
|
||||||
|
if (firstRead && config === UsbCommand.ReadUserConfig) {
|
||||||
|
firstRead = false;
|
||||||
|
configSize = readBuffer[7] + (readBuffer[8] << 8);
|
||||||
|
this.logService.debug(`[DeviceOperation] userConfigSize: ${configSize}`);
|
||||||
|
if (originalConfigSize < configSize) {
|
||||||
|
this.logService.debug(`[DeviceOperation] userConfigSize should never be larger than getConfigSize()! ` +
|
||||||
|
`Overriding configSize with getConfigSize()`);
|
||||||
|
configSize = originalConfigSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response = convertBufferToIntArray(configBuffer);
|
||||||
|
return Promise.resolve(JSON.stringify(response));
|
||||||
|
} catch (error) {
|
||||||
|
const errMsg = `[DeviceOperation] ${configName} from eeprom error`;
|
||||||
|
this.logService.error(errMsg, error);
|
||||||
|
throw new Error(errMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the user / hardware configuration size from the UHK Device
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
public async getConfigSizeFromKeyboard(property: SystemPropertyIds): Promise<number> {
|
||||||
|
const buffer = await this.device.write(new Buffer([UsbCommand.GetProperty, property]));
|
||||||
|
this.device.close();
|
||||||
|
const configSize = buffer[1] + (buffer[2] << 8);
|
||||||
|
this.logService.debug('[DeviceOperation] User config size:', configSize);
|
||||||
|
return configSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async saveUserConfiguration(json: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
this.logService.debug('[DeviceOperation] USB[T]: Write user configuration to keyboard');
|
||||||
|
await this.sendUserConfigToKeyboard(json);
|
||||||
|
this.logService.debug('[DeviceOperation] USB[T]: Write user configuration to EEPROM');
|
||||||
|
await this.device.writeConfigToEeprom(EepromTransfer.WriteUserConfig);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
this.logService.error('[DeviceOperation] Transferring error', error);
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
this.device.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IpcMain handler. Send the UserConfiguration to the UHK Device and send a response with the result.
|
||||||
|
* @param {string} json - UserConfiguration in JSON format
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private async sendUserConfigToKeyboard(json: string): Promise<void> {
|
||||||
|
const buffer: Buffer = new Buffer(JSON.parse(json).data);
|
||||||
|
const fragments = getTransferBuffers(UsbCommand.UploadUserConfig, buffer);
|
||||||
|
for (const fragment of fragments) {
|
||||||
|
await this.device.write(fragment);
|
||||||
|
}
|
||||||
|
this.logService.debug('[DeviceOperation] USB[T]: Apply user configuration to keyboard');
|
||||||
|
const applyBuffer = new Buffer([UsbCommand.ApplyConfig]);
|
||||||
|
await this.device.write(applyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
private getFirmwarePath(): string {
|
private getFirmwarePath(): string {
|
||||||
const firmware = path.join(this.rootDir, 'packages/firmware/devices/uhk60-right/firmware.hex');
|
const firmware = path.join(this.rootDir, 'packages/firmware/devices/uhk60-right/firmware.hex');
|
||||||
|
|
||||||
|
|||||||
31
packages/usb/write-userconfig.ts
Executable file
31
packages/usb/write-userconfig.ts
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env ts-node
|
||||||
|
///<reference path="./node_modules/@types/node/index.d.ts"/>
|
||||||
|
|
||||||
|
import { UhkBlhost, UhkHidDevice, UhkOperations } from 'uhk-usb';
|
||||||
|
import { LogService } from 'uhk-common';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
if (process.argv.length < 3) {
|
||||||
|
console.log(`use: write-userconfig <path to config file.bin>`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileContent = fs.readFileSync(process.argv[2]);
|
||||||
|
const json = JSON.stringify(fileContent);
|
||||||
|
const logger = new LogService();
|
||||||
|
const uhkDevice = new UhkHidDevice(logger);
|
||||||
|
const uhkBlHost = new UhkBlhost(logger, '.');
|
||||||
|
const uhkOperations = new UhkOperations(logger, uhkBlHost, uhkDevice, '.');
|
||||||
|
|
||||||
|
const init = async (): Promise<void> => {
|
||||||
|
await uhkOperations.saveUserConfiguration(json);
|
||||||
|
};
|
||||||
|
|
||||||
|
init()
|
||||||
|
.then(() => {
|
||||||
|
console.log('Success');
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
process.exit(-1);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user