1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
const fs = require("fs")
, util = require("util")
, EventEmitter = require("events").EventEmitter
, {eviocgrab, eviocgid} = require("bindings")("ioctl.node")
, events = require("./Events")
, codes = {
EV_KEY : require("./Events/EV_KEY"),
EV_ABS : require("./Events/EV_ABS"),
EV_SYN : require("./Events/EV_SYN")
};
const arch = (process.arch.indexOf("64")>=0)?64:32;
function Device(path) {
this.grabbed = false;
if (path) this.open(path);
}
util.inherits(Device, EventEmitter);
Device.prototype.open = function(path) {
this.stream = fs
.createReadStream(path, {flags: "r", autoClose: true})
.on("error", e => this.emit("error", e))
.on("open", fd => { this.fd = fd;
try { this.id = eviocgid(fd); }
catch(e) { this.emit("error",
new Error("Reader eviocgid error:"+e)); }
if (this.grabbed) eviocgrab(this.fd, 1);
this.emit("open", fd); })
.on("data", buf => {
var i, j, chunk = (arch===64)?24:16;
for (i=0, j=buf.length; i<j; i+=chunk) {
const e = parse(buf.slice(i, i+chunk));
this.emit("event", e);
this.emit(e.type, e);
}});
};
Device.prototype.close = function() {
this.stream.close();
delete this.stream;
delete this.fd;
delete this.id;
};
Device.prototype.grab = function() {
if (this.grabbed) return; this.grabbed = true;
if (this.fd) eviocgrab(this.fd, 1);
};
Device.prototype.ungrab = function() {
if (!this.grabbed) return; this.grabbed = false;
if (this.fd) eviocgrab(this.fd, 0);
};
// struct input_event {
// struct timeval {
// long tv_sec; // s32/64 (arch)
// long tv_usec; // LE (always?)
// } time;
// __u16 type;
// __u16 code;
// __s32 value;
// };
function parse(buf) {
var e = {time: {sec: null, usec: null},
type: null, code: null, value: null};
var offset;
if (arch === 64) { offset = 16;
e.time.sec = buf.readBigInt64LE(0);
e.time.usec = buf.readBigInt64LE(8);
} else { offset = 8;
e.time.sec = buf.readInt32LE(0);
e.time.usec = buf.readInt32LE(4);
}
e.type = buf.readUInt16LE(offset);
e.code = buf.readUInt16LE(offset + 2);
e.value = buf.readInt32LE(offset + 4);
if (events[e.type]) e.type = events[e.type];
if (codes[e.type] && codes[e.type][e.code])
e.code = codes[e.type][e.code];
return e;
};
module.exports = Device;
|