-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathuinput_iface_keyboard.go
145 lines (113 loc) · 2.68 KB
/
uinput_iface_keyboard.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
package uinput
import (
"fmt"
"io"
"os"
"time"
"unsafe"
)
// Keyboard interface
type Keyboard interface {
KeyPress(key uint16) error
KeyDown(key uint16) error
KeyUp(key uint16) error
io.Closer
}
type vKeyboard struct {
devFile *os.File
}
func setupKeyboard(devFile *os.File) error {
var usetup uinputSetup
// TODO: add possibility to change those values
usetup.name = uinputSetupNameToBytes([]byte("GoUinputDevice"))
usetup.id.BusType = BusVirtual
usetup.id.Vendor = 1
usetup.id.Product = 2
usetup.id.Version = 3
err := ioctl(devFile, uiSetEvBit, EvKey)
if err != nil {
err = fmt.Errorf("Could not perform UI_SET_EVBIT ioctl: %v", err)
goto err
}
for i := 0; i < KeyMax; i++ {
err = ioctl(devFile, uiSetKeyBit, uintptr(i))
if err != nil {
err = fmt.Errorf("Could not perform UI_SET_KEYBIT ioctl: %v", err)
goto err
}
}
err = ioctl(devFile, uiDevSetup, uintptr(unsafe.Pointer(&usetup)))
if err != nil {
err = fmt.Errorf("Could not perform UI_DEV_SETUP ioctl: %v", err)
goto err
}
err = ioctl(devFile, uiDevCreate, uintptr(0))
if err != nil {
err = fmt.Errorf("Could not perform UI_DEV_CREATE ioctl: %v", err)
goto err
}
time.Sleep(time.Millisecond * 200)
return nil
err:
destroyDevice(devFile)
return err
}
func emitKeyDown(devFile *os.File, code uint16) error {
err := emitEvent(devFile, EvKey, code, 1)
if err != nil {
return fmt.Errorf("Could not emit key down event: %v", err)
}
err = emitEvent(devFile, EvSyn, SynReport, 0)
if err != nil {
return fmt.Errorf("Could not emit sync event: %v", err)
}
return err
}
func emitKeyUp(devFile *os.File, code uint16) error {
err := emitEvent(devFile, EvKey, code, 0)
if err != nil {
return fmt.Errorf("Could not emit key up event: %v", err)
}
err = emitEvent(devFile, EvSyn, SynReport, 0)
if err != nil {
return fmt.Errorf("Could not emit sync event: %v", err)
}
return err
}
// CreateKeyboard creates virtual input device that emulates keyboard
func CreateKeyboard() (Keyboard, error) {
dev, err := openUinputDev()
if err != nil {
return nil, err
}
err = setupKeyboard(dev)
if err != nil {
return nil, err
}
return vKeyboard{devFile: dev}, err
}
// KeyPreess emits key press event
func (vk vKeyboard) KeyPress(key uint16) error {
err := vk.KeyDown(key)
err = vk.KeyUp(key)
return err
}
// KeyDown emits key down event
func (vk vKeyboard) KeyDown(key uint16) error {
err := emitKeyDown(vk.devFile, key)
if err != nil {
return err
}
return err
}
// KeyUp emits key up event
func (vk vKeyboard) KeyUp(key uint16) error {
err := emitKeyUp(vk.devFile, key)
if err != nil {
return err
}
return err
}
func (vk vKeyboard) Close() error {
return destroyDevice(vk.devFile)
}