// Copyright 2014-2025 Jesper Larsson
//
// This file is part of Klipspringer, <https://klipspringer.avadeaux.net/>
//
// Klipspringer is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Klipspringer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Klipspringer. If
// not, see <https://www.gnu.org/licenses/>.
import { createReadStream } from 'fs';
import { nextTick } from 'process';
import { log } from './log.js';
const read = (b, off, size, bigE) => {
let v = 0;
let p, d;
if (bigE) {
p = off;
d = 1;
} else {
p = off+size-1;
d = -1;
}
for (let i = 0; i < size; i++) {
v = (v << 8) + b.readUInt8(p);
p += d;
}
return v;
}
// Parameter 'device' is device handle name, e.g. '/dev/input/event0'.
//
// Parameter 'eventSizes' is the list that is output from 'eventsizes.c'.
//
// Parameter 'actions' is a list of lists where each list is
//
// [type, code, value, fun]
//
// where type, code, and value are integers that specify an event, and
// fun is a callback function with arguments (type, code, value,
// time), where time is milliseconds since the epoch.
//
// See /usr/include/linux/input-event-codes.h for meanings of event
// type and code. For normal key events the values are
//
// type: 1 (EV_KEY)
// code: a key/button event code
// value: 1 for button pressed, 0 for released, 2 for repeat (events
// with value 2 keep coming for repeating keys, until the key
// is released, resulting in a value 0 event)
export const listenForEvents = (device, eventSizes, getCallable, actions) => {
const [eventSize,
secOff, secSize,
usecOff, usecSize,
typeOff, typeSize,
codeOff, codeSize,
valueOff, valueSize,
bigE]
= eventSizes;
const k = (type, code, value) => [Number(type), Number(code), Number(value)].toString();
const tbl = { };
for (const e of actions) {
tbl[k(e[0], e[1], e[2])] = e[3];
}
let saved = 0, evOff = 0;
const saveBuf = Buffer.alloc(eventSize);
createReadStream(device).on('data', chunk => {
let off = 0;
while (saved+off+eventSize <= chunk.length) {
let b, p;
if (saved) {
chunk.copy(saveBuf, saved, off, eventSize-saved);
b = saveBuf;
p = 0;
} else {
b = chunk;
p = off;
}
const type = read(b, p+typeOff, typeSize, bigE);
const code = read(b, p+codeOff, codeSize, bigE);
const value = read(b, p+valueOff, valueSize, bigE);
log.debug([type, code, value]);
const f = tbl[k(type, code, value)];
if (f) {
const sec = read(b, p+secOff, secSize, bigE);
const usec = read(b, p+usecOff, usecSize, bigE);
Promise.resolve()
.then(() => getCallable())
.then(callable => { f(callable, type, code, value, sec*1000+usec/1000) })
.catch(err => log.debug("Failed to handle event: "+err));
}
off += eventSize-saved;
saved = 0;
}
if (saved+off < chunk.length) {
chunk.copy(saveBuf, saved, off, chunk.length-off);
saved += chunk.length-off;
}
}).on('error', err => { log.error("Error on device "+device) });
}
Version: v4.3.2.2 (2026-05-16T17:03:34+02:00)
Raw file
Source code overview
Klipspringer home