This repository has been archived by the owner on May 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
input_linux.go
152 lines (134 loc) · 4.14 KB
/
input_linux.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package main
// #cgo pkg-config: libevdev
// #include <libevdev/libevdev.h>
// #include <libevdev/libevdev-uinput.h>
// #include <string.h>
import "C"
import (
"fmt"
"os"
"unsafe"
)
// Absolute axis constants
const (
AbsX Abs = C.ABS_X
AbsY Abs = C.ABS_Y
AbsRX Abs = C.ABS_RX
AbsRY Abs = C.ABS_RY
)
// Button constants
const (
BtnA Button = C.BTN_A
BtnB Button = C.BTN_B
BtnX Button = C.BTN_X
BtnY Button = C.BTN_Y
BtnStart Button = C.BTN_START
BtnSelect Button = C.BTN_SELECT
BtnForward Button = C.BTN_FORWARD
BtnBack Button = C.BTN_BACK
BtnLeft Button = C.BTN_LEFT
BtnRight Button = C.BTN_RIGHT
BtnDpadUp Button = C.BTN_DPAD_UP
BtnDpadDown Button = C.BTN_DPAD_DOWN
BtnDpadLeft Button = C.BTN_DPAD_LEFT
BtnDpadRight Button = C.BTN_DPAD_RIGHT
)
type linuxInputer struct {
uidev *C.struct_libevdev_uinput
f *os.File
}
func NewInput(name string, flags FeatureFlag) (*linuxInputer, error) {
var rc C.int
var dev *C.struct_libevdev
var uidev *C.struct_libevdev_uinput
dev = C.libevdev_new()
C.libevdev_set_name(dev, C.CString(name))
// Build up some basic absolute axis defaults
var abs C.struct_input_absinfo
abs.value = 0
abs.minimum = -100
abs.maximum = 100
abs.fuzz = 5
abs.flat = 0
abs.resolution = 1
// Absolute axis (sticks)
C.libevdev_enable_event_type(dev, C.EV_ABS)
if flags&LeftAnalogStick == LeftAnalogStick {
C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_X, unsafe.Pointer(&abs))
C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_Y, unsafe.Pointer(&abs))
}
if flags&RightAnalogStick == RightAnalogStick {
C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_RX, unsafe.Pointer(&abs))
C.libevdev_enable_event_code(dev, C.EV_ABS, C.ABS_RY, unsafe.Pointer(&abs))
}
// Face buttons
C.libevdev_enable_event_type(dev, C.EV_KEY)
if flags&StartButton == StartButton {
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_START, nil)
}
if flags&SelectButton == SelectButton {
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_SELECT, nil)
}
if flags&ABButtons == ABButtons {
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_A, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_B, nil)
}
if flags&XYButtons == XYButtons {
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_X, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_Y, nil)
}
if flags&DPad == DPad {
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_UP, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_DOWN, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_LEFT, nil)
C.libevdev_enable_event_code(dev, C.EV_KEY, C.BTN_DPAD_RIGHT, nil)
}
// Open uinput
f, err := os.OpenFile("/dev/uinput", os.O_RDWR, 0660)
if err != nil {
e := C.strerror(rc)
return nil, fmt.Errorf("Error %d (%s) opening /dev/uinput : %s", rc, C.GoString(e), err)
}
// Get file hanadle
var fd C.int
fd = C.int(f.Fd())
// Create new uinput device
rc = C.libevdev_uinput_create_from_device(dev, fd, &uidev)
if rc < 0 {
f.Close()
e := C.strerror(rc)
return nil, fmt.Errorf("Error %d creating uinput device: %s", rc, C.GoString(e))
}
return &linuxInputer{
uidev: uidev,
f: f,
}, nil
}
func (i *linuxInputer) Close() error {
C.libevdev_uinput_destroy(i.uidev)
return i.f.Close()
}
// SendAbs sends an absolute axis value, such as an analog stick on a gamepad.
func (i linuxInputer) SendAbs(abs Abs, value int) error {
if err := i.send(C.EV_ABS, C.uint(abs), C.int(value)); err != nil {
return err
}
return i.send(C.EV_SYN, C.SYN_REPORT, 0)
}
// SendButton sends a button value, such as a button press on a gamepad.
func (i linuxInputer) SendButton(btn Button, state int) error {
if err := i.send(C.EV_KEY, C.uint(btn), C.int(state)); err != nil {
return err
}
return i.send(C.EV_SYN, C.SYN_REPORT, 0)
}
// send writes an arbitrary event and sync through uinput, converting the
// return code into an appropriate error.
func (i linuxInputer) send(t C.uint, c C.uint, v C.int) error {
var rc C.int
if rc = C.libevdev_uinput_write_event(i.uidev, t, c, v); rc < 0 {
e := C.strerror(rc)
return fmt.Errorf("Error %d sending event: %s", rc, C.GoString(e))
}
return nil
}