Skip to content
This repository was archived by the owner on Dec 15, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions packages/uhk-common/src/models/uhk-products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface VidPidPair {

export interface UhkDeviceProduct {
id: UHK_DEVICE_IDS_TYPE;
// The reference of the device when provided as CLI argument
asCliArg: string;
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS_TYPE,
// Use it in logs instead of the name because UHK 80 left and right have the same name.
// But we have to differentiate them in the logs
Expand All @@ -28,6 +30,7 @@ export interface UhkDeviceProduct {

export const UNKNOWN_DEVICE: UhkDeviceProduct = {
id: 0 as UHK_DEVICE_IDS_TYPE,
asCliArg: '',
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS.KBOOT,
logName: 'Unknown',
name: 'Unknown',
Expand All @@ -39,6 +42,7 @@ export const UNKNOWN_DEVICE: UhkDeviceProduct = {

export const UHK_60_DEVICE: UhkDeviceProduct = {
id: UHK_DEVICE_IDS.UHK60V1_RIGHT,
asCliArg: 'uhk60v1',
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS.KBOOT,
logName: 'UHK 60 v1',
name: 'UHK 60 v1',
Expand Down Expand Up @@ -73,6 +77,7 @@ export const UHK_60_DEVICE: UhkDeviceProduct = {

export const UHK_60_V2_DEVICE: UhkDeviceProduct = {
id: UHK_DEVICE_IDS.UHK60V2_RIGHT,
asCliArg: 'uhk60v2',
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS.KBOOT,
logName: 'UHK 60 v2',
name: 'UHK 60 v2',
Expand Down Expand Up @@ -107,6 +112,7 @@ export const UHK_60_V2_DEVICE: UhkDeviceProduct = {

export const UHK_80_DEVICE_LEFT: UhkDeviceProduct = {
id: UHK_DEVICE_IDS.UHK80_LEFT,
asCliArg: 'uhk80left',
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS.MCUBOOT,
logName: 'UHK 80 left',
name: 'UHK 80',
Expand All @@ -122,13 +128,13 @@ export const UHK_80_DEVICE_LEFT: UhkDeviceProduct = {
pid: 0x0006, // decimal 6
},
],
// TODO: Implement when we know
buspal: [],
reportId: 4,
};

export const UHK_80_DEVICE: UhkDeviceProduct = {
id: UHK_DEVICE_IDS.UHK80_RIGHT,
asCliArg: 'uhk80',
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS.MCUBOOT,
logName: 'UHK 80 right',
name: 'UHK 80',
Expand All @@ -144,13 +150,13 @@ export const UHK_80_DEVICE: UhkDeviceProduct = {
pid: 0x0008, // decimal 8
},
],
// TODO: Implement when we know
buspal: [],
reportId: 4,
};

export const UHK_DONGLE: UhkDeviceProduct = {
id: UHK_DEVICE_IDS.UHK_DONGLE,
asCliArg: 'dongle',
firmwareUpgradeMethod: FIRMWARE_UPGRADE_METHODS.MCUBOOT,
logName: 'UHK Dongle',
name: 'UHK Dongle',
Expand All @@ -166,7 +172,6 @@ export const UHK_DONGLE: UhkDeviceProduct = {
pid: 0x0004, // decimal 4
},
],
// TODO: Implement when we know
buspal: [],
reportId: 4,
};
Expand Down
118 changes: 118 additions & 0 deletions packages/usb/wait-for-device.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning

import { devicesAsync } from 'node-hid';
import { SerialPort } from 'serialport';
import {
ALL_UHK_DEVICES,
FIRMWARE_UPGRADE_METHODS,
VidPidPair,
} from 'uhk-common';
import {
isUhkCommunicationUsage,
snooze,
} from 'uhk-usb';

import { yargs } from './src/index.js';

const REENUMERATION_MODES = ['device', 'bootloader', 'buspal'];
const reenumerationOptions = REENUMERATION_MODES.join('|');
const devicesOptions = ALL_UHK_DEVICES.map(uhkDevice => uhkDevice.asCliArg).join('|');

const argv = yargs
.scriptName('./wait-for-device.ts')
.usage(`Usage: $0 {${devicesOptions}} {${reenumerationOptions}} timeout`)
.demandCommand(2, 'Device and enumeration mode are required. Timeout in seconds is optional, default value 5 seconds.')
.argv;

const deviceArg = argv._[0] as string;
const enumerationModeArg = argv._[1] as string;
const timeoutArg = argv._[2] as string;

const uhkDeviceProduct = ALL_UHK_DEVICES.find(uhkDevice => uhkDevice.asCliArg === deviceArg);

if (!uhkDeviceProduct) {
console.error(`Invalid device: ${deviceArg}. Available options: ${devicesOptions}`);
process.exit(1);
}

const reenumerationMode = REENUMERATION_MODES.find(value => value === enumerationModeArg);

if (!reenumerationMode) {
console.error(`Invalid reenumeration mode: ${enumerationModeArg}. Available options: ${reenumerationOptions}`);
process.exit(1);
}

if (reenumerationMode === 'buspal' && uhkDeviceProduct.buspal.length === 0) {
console.error(`${deviceArg} does not support buspal reenumeration mode.`);
process.exit(1);
}

let timeout = 5000;

if (timeoutArg) {
const tmpTimeout = Number(timeoutArg);
if (Number.isNaN(tmpTimeout)) {
console.error(`Invalid timeout: ${timeoutArg}. Please provide a number.`);
process.exit(1);
}

timeout = tmpTimeout;
}


let vidPids: VidPidPair[];

if (reenumerationMode === 'device') {
vidPids = uhkDeviceProduct.keyboard;
}
else if (reenumerationMode === 'bootloader') {
vidPids = uhkDeviceProduct.bootloader;
}
else if (reenumerationMode === 'buspal') {
vidPids = uhkDeviceProduct.buspal;
}
else {
console.error(`Not implemented reenumeration mode mapping: ${reenumerationMode}`);
}

const startTime = new Date();

let found = false;

while (new Date().getTime() - startTime.getTime() < timeout && !found) {

if (reenumerationMode === 'bootloader' && uhkDeviceProduct.firmwareUpgradeMethod === FIRMWARE_UPGRADE_METHODS.MCUBOOT) {
const serialDevices = await SerialPort.list();

for (const serialDevice of serialDevices) {
found = vidPids.some(vidPid => Number.parseInt(serialDevice.vendorId, 16) === vidPid.vid && Number.parseInt(serialDevice.productId, 16) === vidPid.pid);

if (found) {
break;
}
}
}
else {
const hidDevices = await devicesAsync();
for (const hidDevice of hidDevices) {
found = vidPids.some(vidPid => {
return vidPid.vid === hidDevice.vendorId && vidPid.pid === hidDevice.productId
&& (reenumerationMode !== 'device' || isUhkCommunicationUsage(hidDevice));
});

if (found) {
break;
}
}
}

await snooze(100);
}

if (found) {
process.exit(0);
}
else {
console.error('Cannot find device within timeout');
process.exit(1);
}