Checkpoint

master
Kuba Orlik 6 years ago
commit 7b1446982c

1
.gitignore vendored

@ -0,0 +1 @@
node_modules

@ -0,0 +1,103 @@
const WiiDevice = require("./wii-device.js");
const LoggerConfig = require("./logger-config.js");
const Config = require("./config");
const KeyboardSimulator = require("./keyboard-simulator.js");
const XboxPadSimulator = require("./xbox-pad-simulator.js");
class ClassicController extends WiiDevice {
constructor(...args) {
super(...args);
this.setupButtons({
A: 48,
B: 49,
Y: 52,
X: 51,
MINUS: 156,
HOME: 60,
PLUS: 151,
RIGHT: 106,
LEFT: 105,
UP: 103,
DOWN: 108,
ZR: 57,
R: 55,
ZL: 56,
L: 54,
});
this.configs = {
"Xbox360 controller": new Config(XboxPadSimulator, {
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
A: "BTN_A",
B: "BTN_B",
Y: "BTN_Y",
X: "BTN_X",
UP: "BTN_DPAD_UP",
DOWN: "BTN_DPAD_DOWN",
LEFT: "BTN_DPAD_LEFT",
RIGHT: "BTN_DPAD_RIGHT",
PLUS: "BTN_START",
MINUS: "BTN_SELECT",
HOME: "BTN_MODE",
R: "BTN_TR",
L: "BTN_TL",
ZL: "BTN_TL2",
ZR: "BTN_TR2",
},
}),
"Xbox360 controller - swap DPAD X/Y (starwhal)": new Config(
XboxPadSimulator,
{
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
A: "BTN_A",
B: "BTN_B",
Y: "BTN_Y",
X: "BTN_X",
UP: "BTN_DPAD_LEFT",
DOWN: "BTN_DPAD_RIGHT",
LEFT: "BTN_DPAD_UP",
RIGHT: "BTN_DPAD_DOWN",
PLUS: "BTN_START",
MINUS: "BTN_SELECT",
HOME: "BTN_MODE",
R: "BTN_TR",
L: "BTN_TL",
ZL: "BTN_TL2",
ZR: "BTN_TR2",
},
}
),
logger: new LoggerConfig(),
"literal abxy (keyboard)": new Config(KeyboardSimulator, {
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
A: "KEY_A",
B: "KEY_B",
Y: "KEY_Y",
X: "KEY_X",
MINUS: "KEY_MINUS",
HOME: "KEY_ESC",
PLUS: "KEY_EQUAL",
RIGHT: "KEY_RIGHT",
LEFT: "KEY_LEFT",
UP: "KEY_UP",
DOWN: "KEY_DOWN",
ZR: "KEY_Z",
R: "KEY_R",
ZL: "KEY_Q",
L: "KEY_L",
},
}),
};
}
}
WiiDevice.registerType(
'"Nintendo Wii Remote Classic Controller"',
ClassicController
);
module.exports = ClassicController;

@ -0,0 +1,35 @@
class Config {
constructor(
simulator_class,
{ button_to_original_keycode, button_to_simulated_event_name }
) {
this.button_to_original_keycode = button_to_original_keycode;
this.button_to_simulated_event_name = button_to_simulated_event_name;
this.original_keycodes_to_button = {};
this.simulator_class = simulator_class;
for (let button in this.button_to_original_keycode) {
this.original_keycodes_to_button[
this.button_to_original_keycode[button]
] = button;
}
}
start(wiimote) {
this.simulator = new this.simulator_class();
wiimote.on("input", event => {
if (event.key_code == 0) {
return;
}
this.simulator.simulateEvent({
key_name: this.button_to_simulated_event_name[
event.button_name
],
direction: event.direction,
});
});
}
}
module.exports = Config;

@ -0,0 +1,41 @@
const WiiDevices = require("./wii-devices.js");
const WiiDevice = require("./wii-device.js");
const sleep = require("./sleep.js");
const inquirer = require("inquirer");
async function wait_for_wii_devices() {
const wii_devices = WiiDevices.get_wii_devices();
if (wii_devices.length) {
return wii_devices;
}
console.log("Waiting for wii_devices...");
await sleep(1000);
return wii_devices.length ? wii_devices : await wait_for_wii_devices();
}
async function pick_wii_device() {
let wii_devices = WiiDevices.get_wii_devices();
if (wii_devices.length === 1) {
return wii_devices[0];
}
console.log("Press any button on the wii_device you want to configure");
return (await WiiDevices.wait_for_event()).wii_device;
}
async function main() {
await wait_for_wii_devices();
const wii_device = await pick_wii_device();
const { mode } = await inquirer.prompt([
{
type: "list",
name: "mode",
message: "which mode do you choose?",
choices: Object.keys(wii_device.configs),
},
]);
wii_device.setConfig(mode);
console.log(`Started ${wii_device.name} in '${mode}' mode`);
wii_device.setup_permanent_listener();
}
main();

107
io.js

@ -0,0 +1,107 @@
// from https://github.com/jehervy/node-virtual-gamepads/blob/master/lib/io.js
var io = {};
io["int"] = 4;
io["char"] = 1;
io["char*"] = 8;
io.UINPUT_IOCTL_BASE = "U".charCodeAt();
io._IOC_NONE = 0;
io._IOC_WRITE = 1;
io._IOC_READ = 2;
io._IOC_NRBITS = 8;
io._IOC_TYPEBITS = 8;
io._IOC_SIZEBITS = 14;
io._IOC_DIRBITS = 2;
io._IOC_NRMASK = (1 << io._IOC_NRBITS) - 1;
io._IOC_TYPEMASK = (1 << io._IOC_TYPEBITS) - 1;
io._IOC_SIZEMASK = (1 << io._IOC_SIZEBITS) - 1;
io._IOC_DIRMASK = (1 << io._IOC_DIRBITS) - 1;
io._IOC_NRSHIFT = 0;
io._IOC_TYPESHIFT = io._IOC_NRSHIFT + io._IOC_NRBITS;
io._IOC_SIZESHIFT = io._IOC_TYPESHIFT + io._IOC_TYPEBITS;
io._IOC_DIRSHIFT = io._IOC_SIZESHIFT + io._IOC_SIZEBITS;
io.sizeof = function(n) {
switch (typeof n) {
case "number":
return n;
case "string":
return n.length;
case "object":
return n.length ? n.length : 0;
case "undefined":
return 0;
}
};
io._IOC = function(dir, type, nr, size) {
return (
(dir << io._IOC_DIRSHIFT) |
(type << io._IOC_TYPESHIFT) |
(nr << io._IOC_NRSHIFT) |
(size << io._IOC_SIZESHIFT)
);
};
io._IOC_TYPECHECK = function(t) {
return io.sizeof(t);
};
io._IO = function(type, nr) {
return io._IOC(io._IOC_NONE, type, nr, 0);
};
io._IOR = function(type, nr, size) {
return io._IOC(io._IOC_READ, type, nr, io._IOC_TYPECHECK(size));
};
io._IOW = function(type, nr, size) {
return io._IOC(io._IOC_WRITE, type, nr, io._IOC_TYPECHECK(size));
};
io._IOWR = function(type, nr, size) {
return io._IOC(
io._IOC_READ | io._IOC_WRITE,
type,
nr,
io._IOC_TYPECHECK(size)
);
};
io._IOR_BAD = function(type, nr, size) {
return io._IOC(io._IOC_READ, type, nr, io.sizeof(size));
};
io._IOW_BAD = function(type, nr, size) {
return io._IOC(io._IOC_WRITE, type, nr, io.sizeof(size));
};
io._IOWR_BAD = function(type, nr, size) {
return io._IOC(io._IOC_READ | io._IOC_WRITE, type, nr, io.sizeof(size));
};
/* used to decode ioctl numbers.. */
io._IOC_DIR = function(nr) {
return (nr >> io._IOC_DIRSHIFT) & io._IOC_DIRMASK;
};
io._IOC_TYPE = function(nr) {
return (nr >> io._IOC_TYPESHIFT) & io._IOC_TYPEMASK;
};
io._IOC_NR = function(nr) {
return (nr >> io._IOC_NRSHIFT) & io._IOC_NRMASK;
};
io._IOC_SIZE = function(nr) {
return (nr >> io._IOC_SIZESHIFT) & io._IOC_SIZEMASK;
};
module.exports = io;

@ -0,0 +1,23 @@
const Simulator = require("./simulator.js");
const uinput = require("./uinput");
class KeyboardSimulator extends Simulator {
constructor() {
const event_names = Object.keys(uinput).filter(event_name =>
event_name.startsWith("KEY_")
);
console.log(event_names);
super(
{
name: "Custom device",
vendor: 0x1337,
product: 0x1010,
version: 1,
},
event_names
);
}
}
module.exports = KeyboardSimulator;

@ -0,0 +1,14 @@
class LoggerConfig {
constructor() {}
start(device) {
device.on("input", event => {
if (event.key_code == 0) {
return;
}
console.log(event.key_code);
});
}
}
module.exports = LoggerConfig;

1632
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,22 @@
{
"name": "wiimote-pads",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"blessed": "^0.1.81",
"inquirer": "^6.2.2",
"ioctl": "^2.0.1",
"linux-device": "^2.0.15",
"node-hid": "^0.7.7",
"react": "^16.8.6",
"react-blessed": "^0.5.0",
"restruct": "^0.1.3",
"uuid": "^3.3.2"
}
}

@ -0,0 +1,58 @@
const fs = require("fs");
const ioctl = require("ioctl");
const uinput = require("./uinput");
const { O_NONBLOCK, O_WRONLY } = fs.constants;
class Simulator {
constructor({ name, vendor, product, version }, event_names) {
this.fd = fs.openSync("/dev/uinput", O_WRONLY | O_NONBLOCK);
const bustype = 0x3; // USB
const buff = Buffer.alloc(1116);
buff.fill(0);
buff.write(name, 0, 80);
buff.writeUInt16LE(bustype, 80);
buff.writeUInt16LE(vendor, 82);
buff.writeUInt16LE(product, 84);
buff.writeUInt16LE(version, 86);
fs.writeSync(this.fd, buff, 0, buff.length, null);
ioctl(this.fd, uinput.UI_SET_EVBIT, uinput.EV_KEY);
for (let event_name of event_names) {
console.log("registering event", event_name, uinput[event_name]);
ioctl(this.fd, uinput.UI_SET_KEYBIT, uinput[event_name]);
}
ioctl(this.fd, uinput.UI_DEV_CREATE, 0);
}
simulateEvent({ key_name, direction }) {
//usage: simulateEvent({key_name: "KEY_A", direction: "down" | "up"});
var ev = Buffer.alloc(24);
ev.fill(0);
var tv_sec = Math.round(Date.now() / 1000),
tv_usec = Math.round((Date.now() % 1000) * 1000),
type = 0x01, // EV_KEY,
code = uinput[key_name],
value = direction == "down" ? 1 : 0;
ev.writeInt32LE(tv_sec, 0);
ev.writeInt32LE(tv_usec, 8);
ev.writeInt16LE(type, 16);
ev.writeInt16LE(code, 18);
ev.writeInt32LE(value, 20);
var ev_sync_report = Buffer.alloc(24);
ev_sync_report.fill(0);
ev_sync_report.writeInt32LE(tv_sec, 0);
ev_sync_report.writeInt32LE(tv_usec, 8);
fs.writeSync(this.fd, ev, 0, ev.length, null);
fs.writeSync(this.fd, ev_sync_report, 0, ev_sync_report.length, null);
}
}
module.exports = Simulator;

@ -0,0 +1,3 @@
const util = require("util");
module.exports = util.promisify((time, cb) => setTimeout(cb, time));

@ -0,0 +1,185 @@
// from http://art.vexillium.org/posts/nodejs-gamepad-driver/content/uinput.js
// http://art.vexillium.org/posts/nodejs-gamepad-driver/
// types of events from: /usr/include/linux/input-event-codes.h
var restruct = require("restruct"),
io = require("./io");
var uinput = {};
uinput.UI_SET_EVBIT = io._IOW(io.UINPUT_IOCTL_BASE, 100, io["int"]);
uinput.UI_SET_KEYBIT = io._IOW(io.UINPUT_IOCTL_BASE, 101, io["int"]);
uinput.UI_SET_RELBIT = io._IOW(io.UINPUT_IOCTL_BASE, 102, io["int"]);
uinput.UI_SET_ABSBIT = io._IOW(io.UINPUT_IOCTL_BASE, 103, io["int"]);
//https://github.com/torvalds/linux/blob/1fc7f56db7a7c467e46a5d2e2a009d2f337e0338/include/uapi/linux/input.h#L182
uinput.EVIOCGRAB = io._IOW("E".charCodeAt(0), 0x90, io["int"]);
// https://github.com/torvalds/linux/blob/1fc7f56db7a7c467e46a5d2e2a009d2f337e0338/include/uapi/linux/input.h#L178
uinput.EVIOCSFF = io._IOW("E".charCodeAt(0), 0x80, io["ff_effect"]);
uinput.UI_DEV_CREATE = io._IO(io.UINPUT_IOCTL_BASE, 1);
uinput.UI_DEV_DESTROY = io._IO(io.UINPUT_IOCTL_BASE, 2);
uinput.EV_SYN = 0x00;
uinput.EV_KEY = 0x01;
uinput.EV_REL = 0x02;
uinput.EV_ABS = 0x03;
uinput.BTN_MOUSE = 0x110;
uinput.BTN_LEFT = 0x110;
uinput.BTN_RIGHT = 0x111;
uinput.BTN_MIDDLE = 0x112;
uinput.BTN_MOUSE = 0x110;
uinput.BTN_LEFT = 0x110;
uinput.BTN_RIGHT = 0x111;
uinput.BTN_MIDDLE = 0x112;
uinput.BTN_SIDE = 0x113;
uinput.BTN_EXTRA = 0x114;
uinput.BTN_FORWARD = 0x115;
uinput.BTN_BACK = 0x116;
uinput.BTN_TASK = 0x117;
uinput.BTN_JOYSTICK = 0x120;
uinput.BTN_TRIGGER = 0x120;
uinput.BTN_THUMB = 0x121;
uinput.BTN_THUMB2 = 0x122;
uinput.BTN_TOP = 0x123;
uinput.BTN_TOP2 = 0x124;
uinput.BTN_PINKIE = 0x125;
uinput.BTN_BASE = 0x126;
uinput.BTN_BASE2 = 0x127;
uinput.BTN_BASE3 = 0x128;
uinput.BTN_BASE4 = 0x129;
uinput.BTN_BASE5 = 0x12a;
uinput.BTN_BASE6 = 0x12b;
uinput.BTN_DEAD = 0x12f;
uinput.BTN_GAMEPAD = 0x130;
uinput.BTN_A = 0x130;
uinput.BTN_B = 0x131;
uinput.BTN_C = 0x132;
uinput.BTN_X = 0x133;
uinput.BTN_Y = 0x134;
uinput.BTN_Z = 0x135;
uinput.BTN_TL = 0x136;
uinput.BTN_TR = 0x137;
uinput.BTN_TL2 = 0x138;
uinput.BTN_TR2 = 0x139;
uinput.BTN_SELECT = 0x13a;
uinput.BTN_START = 0x13b;
uinput.BTN_MODE = 0x13c;
uinput.BTN_THUMBL = 0x13d;
uinput.BTN_THUMBR = 0x13e;
uinput.REL_X = 0x00;
uinput.REL_Y = 0x01;
uinput.REL_WHEEL = 0x08;
uinput.ABS_X = 0x00;
uinput.ABS_Y = 0x01;
uinput.ABS_Z = 0x02;
uinput.ABS_RX = 0x03;
uinput.ABS_RY = 0x04;
uinput.ABS_RZ = 0x05;
uinput.ABS_HAT0X = 0x10;
uinput.ABS_HAT0Y = 0x11;
uinput.ABS_MISC = 0x28;
uinput.ID_BUS = 0;
uinput.BUS_USB = 0x3;
uinput.KEY_RESERVED = 0;
uinput.KEY_ESC = 1;
uinput.KEY_1 = 2;
uinput.KEY_2 = 3;
uinput.KEY_3 = 4;
uinput.KEY_4 = 5;
uinput.KEY_5 = 6;
uinput.KEY_6 = 7;
uinput.KEY_7 = 8;
uinput.KEY_8 = 9;
uinput.KEY_9 = 10;
uinput.KEY_0 = 11;
uinput.KEY_MINUS = 12;
uinput.KEY_EQUAL = 13;
uinput.KEY_BACKSPACE = 14;
uinput.KEY_TAB = 15;
uinput.KEY_Q = 16;
uinput.KEY_W = 17;
uinput.KEY_E = 18;
uinput.KEY_R = 19;
uinput.KEY_T = 20;
uinput.KEY_Y = 21;
uinput.KEY_U = 22;
uinput.KEY_I = 23;
uinput.KEY_O = 24;
uinput.KEY_P = 25;
uinput.KEY_LEFTBRACE = 26;
uinput.KEY_RIGHTBRACE = 27;
uinput.KEY_ENTER = 28;
uinput.KEY_LEFTCTRL = 29;
uinput.KEY_A = 30;
uinput.KEY_S = 31;
uinput.KEY_D = 32;
uinput.KEY_F = 33;
uinput.KEY_G = 34;
uinput.KEY_H = 35;
uinput.KEY_J = 36;
uinput.KEY_K = 37;
uinput.KEY_L = 38;
uinput.KEY_SEMICOLON = 39;
uinput.KEY_APOSTROPHE = 40;
uinput.KEY_GRAVE = 41;
uinput.KEY_LEFTSHIFT = 42;
uinput.KEY_BACKSLASH = 43;
uinput.KEY_Z = 44;
uinput.KEY_X = 45;
uinput.KEY_C = 46;
uinput.KEY_V = 47;
uinput.KEY_B = 48;
uinput.KEY_N = 49;
uinput.KEY_M = 50;
uinput.KEY_COMMA = 51;
uinput.KEY_DOT = 52;
uinput.KEY_SLASH = 53;
uinput.KEY_RIGHTSHIFT = 54;
uinput.KEY_KPASTERISK = 55;
uinput.KEY_LEFTALT = 56;
uinput.KEY_SPACE = 57;
uinput.KEY_CAPSLOCK = 58;
uinput.KEY_F1 = 59;
uinput.KEY_F2 = 60;
uinput.KEY_F3 = 61;
uinput.KEY_F4 = 62;
uinput.KEY_F5 = 63;
uinput.KEY_F6 = 64;
uinput.KEY_F7 = 65;
uinput.KEY_F8 = 66;
uinput.KEY_F9 = 67;
uinput.KEY_F10 = 68;
uinput.BTN_DPAD_UP = 0x220;
uinput.BTN_DPAD_DOWN = 0x221;
uinput.BTN_DPAD_LEFT = 0x222;
uinput.BTN_DPAD_RIGHT = 0x223;
uinput.UINPUT_MAX_NAME_SIZE = 80;
uinput.input_id = restruct
.int16lu("bustype")
.int16lu("vendor")
.int16lu("product")
.int16lu("version")
.pad(1012);
uinput.uinput_user_dev = restruct
.string("name", uinput.UINPUT_MAX_NAME_SIZE)
.struct("id", uinput.input_id)
.int32ls("absmax")
.int32ls("absmin")
.int32ls("absfuzz")
.int32ls("absflat");
for (var i in uinput) {
module.exports[i] = uinput[i];
}

@ -0,0 +1,117 @@
const fs = require("fs");
const ioctl = require("ioctl");
const uinput = require("./uinput");
const uuid = require("uuid/v1");
const EventEmitter = require("events");
const { spawn } = require("child_process");
const KeyboardSimulator = require("./keyboard-simulator.js");
class WiiDeviceEvent {
constructor(buffer, wii_device) {
this.key_code = buffer[18];
this.button_name = wii_device.keycodes[this.key_code];
this.type = buffer[20] ? "press" : "release";
this.direction = buffer[20] ? "down" : "up";
this.buffer = buffer;
this.wii_device = wii_device;
}
}
const WIIMOTE_EVENT_BYTESIZE = 24;
const types = {};
class WiiDevice extends EventEmitter {
constructor({ name, handlers }) {
super();
this.handlers = handlers;
this.name = name;
this.handler_file = this.get_handler_file(handlers);
this.id = uuid();
this.setup_temporary_listener();
this.buttons = {};
this.keycodes = {};
}
static registerType(name, constructor) {
types[name] = constructor;
}
static fromDesc(desc) {
return new types[desc.name](desc);
}
static getPossibleTypes() {
return Object.keys(types);
}
setupButtons(button_name_to_original_evcode) {
this.buttons = button_name_to_original_evcode;
this.keycodes = {};
for (let button in this.buttons) {
this.keycodes[this.buttons[button]] = button;
}
}
setup_temporary_listener() {
this.cat = spawn("cat", [this.handler_file]);
this.stream = this.cat.stdout;
this.pressed_buttons_count = 0;
this.stream.on("data", buf => {
while (buf.length) {
let slice = buf.slice(0, WIIMOTE_EVENT_BYTESIZE);
this.emit("input", new WiiDeviceEvent(slice, this));
buf = buf.slice(WIIMOTE_EVENT_BYTESIZE);
}
});
}
setup_permanent_listener() {
if (this.cat) {
this.cat.kill();
}
const handler_file_fd = fs.openSync(this.handler_file);
try {
// grabbing device: https://unix.stackexchange.com/questions/492909/access-grab-state-of-evdev-device
ioctl(handler_file_fd, uinput.EVIOCGRAB, 0x1);
console.log("grabbed device");
} catch (e) {
console.error("Couldn't grab device.");
console.error(e);
process.exit(13);
}
const stream = fs.createReadStream("any", { fd: handler_file_fd });
stream.on("data", buf => {
while (buf.length) {
let slice = buf.slice(0, WIIMOTE_EVENT_BYTESIZE);
this.emit("input", new WiiDeviceEvent(slice, this));
buf = buf.slice(WIIMOTE_EVENT_BYTESIZE);
}
});
}
has_handler(handler_name) {
return this.handlers.includes(handler_name);
}
get_handler_file(handlers) {
return `/dev/input/${
handlers.filter(handler => handler.startsWith("event"))[0]
}`;
}
setConfig(config_key) {
this.configs[config_key].start(this);
}
close() {
// console.log("Closing the stream for", this.id);
this.removeAllListeners();
}
}
module.exports = WiiDevice;
require("./wiimote.js");
require("./classic-controller.js");

@ -0,0 +1,124 @@
const fs = require("fs");
const WiiDevice = require("./wii-device.js");
const EventEmitter = require("events");
const { spawn } = require("child_process");
class WiiDevices extends EventEmitter {
constructor() {
super();
this.wii_devices = [];
this.refresh_wii_devices();
this.inotify = spawn("inotifywait", [
"-m",
"-r",
"-e",
"CREATE",
"-e",
"DELETE",
"/dev/input",
]).stdout;
this.inotify.on("data", () => this.refresh_wii_devices());
}
static parseDevice(string) {
const obj = {};
string
.split("\n")
.map(line => line.split(": "))
.filter(line_elements => ["N", "H"].includes(line_elements[0]))
.map(line_elements => line_elements[1])
.map(prop_desc => prop_desc.split("="))
.forEach(
prop_desc_elements =>
(obj[prop_desc_elements[0].toLowerCase()] =
prop_desc_elements[1])
);
if (obj.handlers) {
obj.handlers = obj.handlers.trim().split(" ");
}
return obj;
}
is_wii_device_new(description) {
return !description.handlers
.filter(h => h != "kbd")
.some(handler =>
this.wii_devices.some(wii_device =>
wii_device.has_handler(handler)
)
);
}
add_wii_device_if_new(description) {
if (this.is_wii_device_new(description)) {
const wii_device = WiiDevice.fromDesc(description);
this.wii_devices.push(wii_device);
this.emit("change");
}
}
remove_wii_device_if_not_in_list(devices_list, wii_device) {
if (
!devices_list
.map(e => e.handlers)
.reduce((a, b) => a.concat(b), [])
.filter(handler => handler != "kbd")
.filter(handler => wii_device.has_handler(handler)).length
) {
wii_device.close();
this.wii_devices.splice(
this.wii_devices
.map(wii_device => wii_device.id)
.indexOf(wii_device.id),
1
);
this.emit("change");
}
}
refresh_wii_devices() {
try {
const devices = fs
.readFileSync("/proc/bus/input/devices", "utf-8")
.trim();
const entries = devices
.split("\n\n")
.map(WiiDevices.parseDevice)
.filter(d => WiiDevice.getPossibleTypes().includes(d.name));
entries.forEach(wii_device_description =>
this.add_wii_device_if_new(wii_device_description)
);
this.wii_devices.forEach(wii_device =>
this.remove_wii_device_if_not_in_list(entries, wii_device)
);
return this.wii_devices;
} catch (e) {
console.error(e);
return this.refresh_wii_devices();
}
}
get_wii_devices() {
return this.wii_devices;
}
quit() {
this.wii_devices.forEach(wii_device => wii_device.close());
}
async wait_for_event() {
return new Promise((resolve, reject) => {
const listener = event => {
this.wii_devices.forEach(wii_device =>
wii_device.removeListener("input", listener)
);
resolve(event);
};
this.wii_devices.forEach(wii_device =>
wii_device.once("input", listener)
);
});
}
}
module.exports = new WiiDevices();

@ -0,0 +1,133 @@
const WiiDevice = require("./wii-device.js");
const Config = require("./config.js");
const KeyboardSimulator = require("./keyboard-simulator.js");
const XboxPadSimulator = require("./xbox-pad-simulator.js");
const LoggerConfig = require("./logger-config.js");
class Wiimote extends WiiDevice {
constructor(...args) {
super(...args);
this.setupButtons({
A: 48,
B: 49,
MINUS: 156,
HOME: 60,
PLUS: 151,
ONE: 1,
TWO: 2,
RIGHT: 106,
LEFT: 105,
UP: 103,
DOWN: 108,
});
this.configs = {
"Xbox360 controller": new Config(XboxPadSimulator, {
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
TWO: "BTN_A",
ONE: "BTN_B",
B: "BTN_Y",
A: "BTN_X",
UP: "BTN_DPAD_LEFT",
DOWN: "BTN_DPAD_RIGHT",
LEFT: "BTN_DPAD_DOWN",
RIGHT: "BTN_DPAD_UP",
PLUS: "BTN_START",
MINUS: "BTN_SELECT",
HOME: "BTN_MODE",
},
}),
"Xbox360 controller - Towerfall": new Config(XboxPadSimulator, {
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
TWO: "BTN_B",
ONE: "BTN_Y",
B: "BTN_TR",
A: "BTN_X",
UP: "BTN_DPAD_LEFT",
DOWN: "BTN_DPAD_RIGHT",
LEFT: "BTN_DPAD_DOWN",
RIGHT: "BTN_DPAD_UP",
PLUS: "BTN_START",
MINUS: "BTN_A",
HOME: "BTN_MODE",
},
}),
"Xbox360 controller - swap dpad X/Y (Starwhal)": new Config(
XboxPadSimulator,
{
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
TWO: "BTN_A",
ONE: "BTN_B",
B: "BTN_Y",
A: "BTN_X",
UP: "BTN_DPAD_UP",
DOWN: "BTN_DPAD_DOWN",
LEFT: "BTN_DPAD_RIGHT",
RIGHT: "BTN_DPAD_LEFT",
PLUS: "BTN_START",
MINUS: "BTN_SELECT",
HOME: "BTN_MODE",
},
}
),
wsad: new Config(KeyboardSimulator, {
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
A: "KEY_Q",
B: "KEY_E",
UP: "KEY_A",
DOWN: "KEY_D",
LEFT: "KEY_S",
RIGHT: "KEY_W",
HOME: "KEY_ESC",
MINUS: "KEY_Z",
PLUS: "KEY_X",
ONE: "KEY_1",
TWO: "KEY_2",
},
}),
"Keyboard - 0123..": new Config(KeyboardSimulator, {
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
A: "KEY_0",
B: "KEY_1",
UP: "KEY_2",
DOWN: "KEY_3",
LEFT: "KEY_4",
RIGHT: "KEY_5",
TWO: "KEY_6",
MINUS: "KEY_7",
PLUS: "KEY_8",
ONE: "KEY_9",
HOME: "KEY_ESC",
},
}),
"Keyboard - QWERTY": new Config(KeyboardSimulator, {
button_to_original_keycode: this.buttons,
button_to_original_keycode: this.buttons,
button_to_simulated_event_name: {
A: "KEY_Q",
B: "KEY_W",
UP: "KEY_E",
DOWN: "KEY_R",
LEFT: "KEY_T",
RIGHT: "KEY_Y",
TWO: "KEY_U",
MINUS: "KEY_I",
PLUS: "KEY_O",
ONE: "KEY_P",
HOME: "KEY_ESC",
},
}),
logger: new LoggerConfig(),
};
}
}
WiiDevice.registerType('"Nintendo Wii Remote"', Wiimote);
module.exports = Wiimote;

@ -0,0 +1,34 @@
const Simulator = require("./simulator.js");
class XboxControllerSimulator extends Simulator {
constructor() {
super(
// https://www.the-sz.com/products/usbid/index.php?v=0x045E
{
name: "Microsoft X-Box 360 pad",
vendor: 0x045e,
product: 0x028e,
version: 1,
},
[
"A",
"B",
"X",
"Y",
"TR",
"TL",
"TR2",
"TL2",
"SELECT",
"START",
"MODE",
"DPAD_UP",
"DPAD_DOWN",
"DPAD_LEFT",
"DPAD_RIGHT",
].map(btn_name => `BTN_${btn_name}`)
);
}
}
module.exports = XboxControllerSimulator;
Loading…
Cancel
Save