You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.9 KiB
JavaScript

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) {
const ret = `/dev/input/${
handlers.filter((handler) => handler.startsWith("event"))[0]
}`;
console.log(ret);
return ret;
}
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");