feat: kboot package (#894)
* feat: kboot package * feat: kboot package * fix: wait 1 sec after device is available * test: fix unit test * refactor: clean unused codes * doc: improve readme.md * doc: improve readme.md * test: fix unit test * chore: fix lint settings * style: fix linting issues
This commit is contained in:
committed by
László Monda
parent
bfc08edfce
commit
3964698cf7
36
packages/kboot/test/kboot.spec.ts
Normal file
36
packages/kboot/test/kboot.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { BootloaderVersion, CommandResponse, Commands, KBoot, Peripheral, Properties, ResponseCodes, ResponseTags } from '../src';
|
||||
import { TestPeripheral } from './test-peripheral';
|
||||
|
||||
describe('kboot', () => {
|
||||
let kboot: KBoot;
|
||||
let testPeripheral: Peripheral;
|
||||
|
||||
beforeEach(() => {
|
||||
testPeripheral = new TestPeripheral();
|
||||
kboot = new KBoot(testPeripheral);
|
||||
});
|
||||
|
||||
describe('getBootloaderVersion', () => {
|
||||
it('should works', async () => {
|
||||
const sendCommandResponse: CommandResponse = {
|
||||
code: ResponseCodes.Success,
|
||||
tag: ResponseTags.Property,
|
||||
// tslint:disable-next-line:max-line-length
|
||||
raw: Buffer.from([0x03, 0x00, 0x0c, 0x00, 0xa7, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
|
||||
};
|
||||
spyOn(testPeripheral, 'sendCommand').and.returnValue(Promise.resolve(sendCommandResponse));
|
||||
const version = await kboot.getBootloaderVersion();
|
||||
const expectedVersion: BootloaderVersion = {
|
||||
protocolName: 'K',
|
||||
major: 2,
|
||||
minor: 0,
|
||||
bugfix: 0
|
||||
};
|
||||
expect(version).toEqual(expectedVersion);
|
||||
expect(testPeripheral.sendCommand).toHaveBeenCalledWith({
|
||||
command: Commands.GetProperty,
|
||||
params: [1, 0, 0, 0, 0, 0, 0, 0]
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
27
packages/kboot/test/test-peripheral.ts
Normal file
27
packages/kboot/test/test-peripheral.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { CommandOption, CommandResponse, DataOption, Peripheral, ResponseCodes, ResponseTags } from '../src';
|
||||
|
||||
export class TestPeripheral implements Peripheral {
|
||||
close(): void {
|
||||
}
|
||||
|
||||
open(): void {
|
||||
}
|
||||
|
||||
sendCommand(options: CommandOption): Promise<CommandResponse> {
|
||||
const response = {
|
||||
tag: ResponseTags.Generic,
|
||||
code: ResponseCodes.Success,
|
||||
raw: new Buffer(0)
|
||||
};
|
||||
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
|
||||
writeMemory(data: DataOption): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
readMemory(startAddress: number, count: number): Promise<Buffer> {
|
||||
return Promise.resolve(new Buffer(0));
|
||||
}
|
||||
}
|
||||
33
packages/kboot/test/uhk-helpers/index.ts
Normal file
33
packages/kboot/test/uhk-helpers/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
import * as MemoryMap from 'nrf-intel-hex';
|
||||
|
||||
export enum UhkReenumerationModes {
|
||||
Bootloader = 'bootloader',
|
||||
Buspal = 'buspal',
|
||||
NormalKeyboard = 'normalKeyboard',
|
||||
CompatibleKeyboard = 'compatibleKeyboard'
|
||||
}
|
||||
|
||||
const USB_SCRIPTS_DIR = join(__dirname, '../../../usb');
|
||||
export const reenumerate = (mode: UhkReenumerationModes): void => {
|
||||
const reenumerateScriptFile = join(USB_SCRIPTS_DIR, 'reenumerate.js');
|
||||
const command = [reenumerateScriptFile, mode.toString()].join(' ');
|
||||
|
||||
execSync(
|
||||
command,
|
||||
{
|
||||
cwd: USB_SCRIPTS_DIR,
|
||||
stdio: [0, 1, 2]
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const readBootloaderFirmwareFromHexFile = (): Map<any, any> => {
|
||||
const hexFilePath = join(__dirname, '../../../../tmp/packages/firmware/devices/uhk60-right/firmware.hex');
|
||||
const fileContent = readFileSync(hexFilePath, { encoding: 'utf8' });
|
||||
const memoryMap = MemoryMap.fromHex(fileContent);
|
||||
|
||||
return memoryMap;
|
||||
};
|
||||
10
packages/kboot/test/util/encode-string-to-parameters.spec.ts
Normal file
10
packages/kboot/test/util/encode-string-to-parameters.spec.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { encodeStringToParams } from '../../src/util';
|
||||
|
||||
describe('encodeStringToParams', () => {
|
||||
xit('should convert 8 character to little endian 4 byte array', () => {
|
||||
const result = encodeStringToParams('0403020108070605');
|
||||
|
||||
const expectedResult = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
|
||||
expect(result).toEqual(expectedResult);
|
||||
});
|
||||
});
|
||||
17
packages/kboot/test/util/response-parser.spec.ts
Normal file
17
packages/kboot/test/util/response-parser.spec.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { getResponseCode, ResponseCodes } from '../../src';
|
||||
|
||||
describe('response-parser', () => {
|
||||
describe('getResponseCode', () => {
|
||||
it('should return with success', () => {
|
||||
const buffer = Buffer.from([0x03, 0x00, 0x08, 0x00, 0xa7, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]);
|
||||
const responseCode = getResponseCode(buffer);
|
||||
expect(responseCode).toEqual(ResponseCodes.Success);
|
||||
});
|
||||
|
||||
it('should return with UnknownProperty', () => {
|
||||
const buffer = Buffer.from([0x03, 0x00, 0x08, 0x00, 0xa7, 0x00, 0x00, 0x01, 0x3c, 0x28, 0x00, 0x00]);
|
||||
const responseCode = getResponseCode(buffer);
|
||||
expect(responseCode).toEqual(ResponseCodes.UnknownProperty);
|
||||
});
|
||||
});
|
||||
});
|
||||
16
packages/kboot/test/util/usb/encode-command-option.spec.ts
Normal file
16
packages/kboot/test/util/usb/encode-command-option.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { CommandOption, Commands } from '../../../src';
|
||||
import { encodeCommandOption } from '../../../src/util';
|
||||
|
||||
describe('usb encodeCommandOption', () => {
|
||||
it('should convert correctly', () => {
|
||||
const option: CommandOption = {
|
||||
command: Commands.GetProperty,
|
||||
params: [1, 0, 0, 0, 0, 0, 0, 0]
|
||||
};
|
||||
|
||||
const result = encodeCommandOption(option);
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const expected = [1, 0, 0x0c, 0, 0x07, 0x00, 0x00, 0x02, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
81
packages/kboot/test/zzz-uhk-integration-tests.spec.ts
Normal file
81
packages/kboot/test/zzz-uhk-integration-tests.spec.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { reenumerate, UhkReenumerationModes, readBootloaderFirmwareFromHexFile } from './uhk-helpers';
|
||||
import { BootloaderVersion, UsbPeripheral } from '../src';
|
||||
import { KBoot } from '../src/kboot';
|
||||
import { DataOption } from '../index';
|
||||
|
||||
xdescribe('UHK Integration tests', () => {
|
||||
describe('bootloader', () => {
|
||||
let usb: UsbPeripheral;
|
||||
let kboot: KBoot;
|
||||
beforeEach(() => {
|
||||
reenumerate(UhkReenumerationModes.Bootloader);
|
||||
usb = new UsbPeripheral({ vendorId: 0x1d50, productId: 0x6120 });
|
||||
kboot = new KBoot(usb);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (usb) {
|
||||
usb.close();
|
||||
}
|
||||
|
||||
if (kboot) {
|
||||
kboot.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('get bootloader version', async () => {
|
||||
const expectedVersion: BootloaderVersion = {
|
||||
protocolName: 'K',
|
||||
major: 2,
|
||||
minor: 0,
|
||||
bugfix: 0
|
||||
};
|
||||
const version = await kboot.getBootloaderVersion();
|
||||
|
||||
expect(version).toEqual(expectedVersion);
|
||||
});
|
||||
|
||||
it('disable flash security', () => {
|
||||
const backdoorKey = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
|
||||
|
||||
return kboot
|
||||
.flashSecurityDisable(backdoorKey)
|
||||
.catch(err => {
|
||||
expect(err).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('flash erase region', () => {
|
||||
return kboot
|
||||
.flashEraseRegion(0xc000, 475136)
|
||||
.catch(err => {
|
||||
expect(err).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('read memory', () => {
|
||||
const dataLength = 128;
|
||||
return kboot
|
||||
.readMemory(0xc000, dataLength)
|
||||
.then((data: number[]) => {
|
||||
expect(data).toBeTruthy();
|
||||
expect(data.length).toEqual(dataLength);
|
||||
})
|
||||
.catch(err => {
|
||||
expect(err).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('write memory', async () => {
|
||||
const bootloaderMemoryMap = readBootloaderFirmwareFromHexFile();
|
||||
for (const [startAddress, data] of bootloaderMemoryMap.entries()) {
|
||||
const dataOption: DataOption = {
|
||||
startAddress,
|
||||
data
|
||||
};
|
||||
|
||||
await kboot.writeMemory(dataOption);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user