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:
Róbert Kiss
2019-01-18 17:37:31 +01:00
committed by László Monda
parent bfc08edfce
commit 3964698cf7
53 changed files with 1784 additions and 249 deletions

View File

@@ -0,0 +1,6 @@
export const encodeStringToParams = (data: string): Int8Array => {
// const buffer = Buffer.from(data);
// return new Int8Array(buffer, 0);
return new Int8Array(0);
};

View File

@@ -0,0 +1,22 @@
export * from './encode-string-to-parameters';
export * from './response-parser';
export * from './usb';
export const convertToHexString = (arr: number[] | Buffer): string => {
let str = '';
for (const n of arr) {
let hex = n.toString(16);
if (hex.length < 2) {
hex = '0' + hex;
}
if (str.length > 0) {
str += ' ';
}
str += hex;
}
return str;
};

View File

@@ -0,0 +1,21 @@
import { ResponseCodes, ResponseTags } from '../enums';
export const convertLittleEndianNumber = (data: Buffer): number => {
let value = 0;
for (let i = 0; i < data.length; i++) {
value += data[i] << (8 * i);
}
return value;
};
export const getResponseCode = (response: Buffer): ResponseCodes => {
const data = response.slice(8, 11);
return convertLittleEndianNumber(data);
};
export const getResponseTag = (response: Buffer): ResponseTags => {
return response[4];
};

View File

@@ -0,0 +1 @@
export const snooze = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

View File

@@ -0,0 +1,18 @@
import { CommandResponse } from '../../models';
import { getResponseCode, getResponseTag } from '../response-parser';
export const decodeCommandResponse = (response: Buffer): CommandResponse => {
if (response.length < 8) {
throw new Error('Invalid response length!');
}
if (response[0] !== 3) {
throw new Error(`Invalid response command channel!`);
}
return {
code: getResponseCode(response),
tag: getResponseTag(response),
raw: response
};
};

View File

@@ -0,0 +1,22 @@
import { isNullOrUndefined } from 'util';
import { Device } from 'node-hid';
import { USB } from '../../models';
export const deviceFinder = (usb: USB) => {
return (device: Device): boolean => {
if (device.productId !== usb.productId) {
return false;
}
if (device.vendorId !== usb.vendorId) {
return false;
}
// TODO: Add interface, usage and usePage filtering
// if (!isNullOrUndefined(usb.interface) && device.interface !== -1 && device.interface === usb.interface) {
// return true;
// }
return true;
};
};

View File

@@ -0,0 +1,46 @@
import { isNullOrUndefined } from 'util';
import { pack } from 'byte-data';
import { CommandOption } from '../../models';
/**
* Encode the USB Command.
* @param option
*/
export const encodeCommandOption = (option: CommandOption): number[] => {
const payload = [
option.command,
option.hasDataPhase ? 1 : 0,
0, // Reserved. Should be 0
option.params ? option.params.length / 4 >> 0 : 0 // number of parameters
];
if (option.params) {
payload.push(...option.params);
}
const header = [
1, // Communication channel
0, // TODO: What is it?
...pack(payload.length, { bits: 16 }) // payload length in 2 byte
];
const placeholders = new Array(32 - payload.length)
.fill(0);
return [...header, ...payload, ...placeholders];
};
export const validateCommandParams = (params: any[]): void => {
if (isNullOrUndefined(params)) {
return;
}
if (!Array.isArray(params)) {
throw new Error('Command parameters must be an array!');
}
if (params.length > 28) {
throw new Error('Maximum 7 (28 bytes) command parameters allowed!');
}
};

View File

@@ -0,0 +1,2 @@
export { deviceFinder } from './device-finder';
export { encodeCommandOption } from './encode-command-option';