-
Notifications
You must be signed in to change notification settings - Fork 0
/
raw.go
76 lines (65 loc) · 2.2 KB
/
raw.go
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
package uinput
import (
"context"
"encoding/binary"
"fmt"
"io"
"os"
"syscall"
"time"
"unsafe"
)
//go:generate go run gen/gen_constants.go ../../../../../../../third_party/kernel/v4.14/include/uapi/linux/input-event-codes.h generated_constants.go
//go:generate go fmt generated_constants.go
// RawEventWriter supports injecting raw input events into a device.
type RawEventWriter struct {
w io.WriteCloser // device
nowFunc func() time.Time
}
// Device returns a RawEventWriter for injecting input events into the input event device at path.
func RawDevice(ctx context.Context, path string) (*RawEventWriter, error) {
f, err := os.OpenFile(path, os.O_WRONLY, 0600)
if err != nil {
return nil, err
}
return &RawEventWriter{f, time.Now}, nil
}
// Close closes the device.
func (ew *RawEventWriter) Close() error {
return ew.w.Close()
}
// Event injects an event containing the supplied values into the device.
func (ew *RawEventWriter) Event(et EventType, ec EventCode, val int32) error {
tv := syscall.NsecToTimeval(ew.nowFunc().UnixNano())
// input_event contains a timeval struct, which uses "long" for its members.
// binary.Write wants explicitly-sized data, so we need to pass a different
// struct depending on the system's int size.
var ev interface{}
switch intSize := unsafe.Sizeof(int(1)); intSize {
case 4:
ev = &event32{int32(tv.Sec), int32(tv.Usec), uint16(et), uint16(ec), val}
case 8:
ev = &event64{tv, uint16(et), uint16(ec), val}
default:
return fmt.Errorf("[errors] unexpected int size of %d byte(s)", intSize)
}
// Little-endian is appropriate regardless of the system's underlying endianness.
return binary.Write(ew.w, binary.LittleEndian, ev)
}
// event32 corresponds to a 32-bit input_event struct.
type event32 struct {
Sec, Usec int32
Type, Code uint16
Val int32
}
// event64 corresponds to a 64-bit input_event struct.
type event64 struct {
Tv syscall.Timeval
Type, Code uint16
Val int32
}
// Sync writes a synchronization event delineating a packet of input data occurring at a single point in time.
// It's shorthand for Event(t, EV_SYN, SYN_REPORT, 0).
func (ew *RawEventWriter) Sync() error {
return ew.Event(EV_SYN, SYN_REPORT.EventCode(), 0)
}