forked from micmonay/keybd_event
-
Notifications
You must be signed in to change notification settings - Fork 0
/
keybd_linux.go
549 lines (520 loc) · 11.2 KB
/
keybd_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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
package keybd_event
/*
#include <linux/uinput.h>
*/
import "C"
import (
"encoding/binary"
"errors"
"os"
"syscall"
)
type uinput_user_dev C.struct_uinput_user_dev
type timeval C.struct_timeval
type input_event C.struct_input_event
var fd *os.File
var X11 = true
const (
_EV_KEY = C.EV_KEY
_EV_SYN = C.EV_SYN
_UI_SET_EVBIT = C.UI_SET_EVBIT
_UI_SET_KEYBIT = C.UI_SET_KEYBIT
_UI_DEV_CREATE = C.UI_DEV_CREATE
_UI_DEV_DESTROY = C.UI_DEV_DESTROY
_UINPUT_MAX_NAME_SIZE = C.UINPUT_MAX_NAME_SIZE
_VK_LEFTCTRL = 29
_VK_RIGHTCTRL = 97
_VK_CTRL = 29
_VK_LEFTSHIFT = 42
_VK_RIGHTSHIFT = 54
_VK_SHIFT = 42
_VK_LEFTALT = 56
_VK_RIGHTALT = 100
_VK_ALT = 56
_VK_LEFTMETA = 125
_VK_RIGHTMETA = 126
)
func initKeyBD() error {
if fd != nil {
return nil
}
path, err := getFileUInput()
if err != nil {
return err
}
fdInit, err := os.OpenFile(path, os.O_WRONLY|syscall.O_NONBLOCK, os.ModeDevice)
fd = fdInit
if err != nil {
if os.IsPermission(err) {
return errors.New("permission error for " + path + " try cmd : sudo chmod +0666 " + path)
} else {
return err
}
}
_, _, errCall := syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), _UI_SET_EVBIT, uintptr(_EV_KEY))
if errCall != 0 {
return err
}
_, _, errCall = syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), _UI_SET_EVBIT, uintptr(_EV_SYN))
if errCall != 0 {
return err
}
keyEventSet()
uidev := uinput_user_dev{}
for i, c := range "keybd interface" {
uidev.name[i] = C.char(c)
}
uidev.id.bustype = C.BUS_USB
uidev.id.vendor = 0x1
uidev.id.product = 0x1
uidev.id.version = 0x1
err = binary.Write(fd, binary.LittleEndian, &uidev)
if err != nil {
return err
}
//Create device
_, _, errCall = syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), _UI_DEV_CREATE, 0)
if errCall != 0 {
return err
}
return nil
}
//actualy don't use
func destroyLinuxUInput() {
syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), _UI_DEV_DESTROY, 0)
fd.Close()
}
func getFileUInput() (string, error) {
if _, err := os.Stat("/dev/uinput"); err == nil {
return "/dev/uinput", nil
}
if _, err := os.Stat("/dev/input/uinput"); err == nil {
return "/dev/input/uinput", nil
}
err := errors.New("Not found uinput file. Try this cmd 'sudo modprobe uinput'")
return "", err
}
// Press key(s)
func (k *KeyBonding) Press() error {
var err error
if k.hasALT {
err = downKey(_VK_ALT)
if err != nil {
return err
}
}
if k.hasSHIFT {
err = downKey(_VK_SHIFT)
if err != nil {
return err
}
}
if k.hasCTRL {
err = downKey(_VK_CTRL)
if err != nil {
return err
}
}
if k.hasRSHIFT {
err = downKey(_VK_RIGHTSHIFT)
if err != nil {
return err
}
}
if k.hasRCTRL {
err = downKey(_VK_RIGHTCTRL)
if err != nil {
return err
}
}
if k.hasALTGR {
err = downKey(_VK_RIGHTALT)
if err != nil {
return err
}
}
if k.hasSuper {
err = downKey(_VK_LEFTMETA)
if err != nil {
return err
}
}
for _, key := range k.keys {
err = downKey(key)
if err != nil {
return err
}
}
err = sync()
if err != nil {
return err
}
return nil
}
// Release key(s)
func (k *KeyBonding) Release() error {
var err error
if k.hasALT {
err = upKey(_VK_ALT)
if err != nil {
return err
}
}
if k.hasSHIFT {
err = upKey(_VK_SHIFT)
if err != nil {
return err
}
}
if k.hasCTRL {
err = upKey(_VK_CTRL)
if err != nil {
return err
}
}
if k.hasRSHIFT {
err = upKey(_VK_RIGHTSHIFT)
if err != nil {
return err
}
}
if k.hasRCTRL {
err = upKey(_VK_RIGHTCTRL)
if err != nil {
return err
}
}
if k.hasALTGR {
err = upKey(_VK_RIGHTALT)
if err != nil {
return err
}
}
if k.hasSuper {
err := upKey(_VK_LEFTMETA)
if err != nil {
return err
}
}
for _, key := range k.keys {
err = upKey(key)
if err != nil {
return err
}
}
err = sync()
if err != nil {
return err
}
//Destroy device
return nil
}
// Launch key bounding
func (k *KeyBonding) Launching() error {
k.Press()
//key up
k.Release()
return nil
}
func keyEventSet() error {
for i := 0; i < 256; i++ {
_, _, errCall := syscall.Syscall(syscall.SYS_IOCTL, fd.Fd(), _UI_SET_KEYBIT, uintptr(i))
if errCall != 0 {
return errCall
}
}
return nil
}
func downKey(key int) error {
ev := input_event{}
ev._type = _EV_KEY
ev.code = C.__u16(key)
ev.value = 1
err := binary.Write(fd, binary.LittleEndian, &ev)
if err != nil {
return err
}
return nil
}
func sync() error {
ev := input_event{}
ev._type = _EV_SYN
ev.code = 0
ev.value = 0
err := binary.Write(fd, binary.LittleEndian, &ev)
if err != nil {
return err
}
return nil
}
func upKey(key int) error {
ev := input_event{}
ev._type = _EV_KEY
ev.code = C.__u16(key)
ev.value = 0
err := binary.Write(fd, binary.LittleEndian, &ev)
if err != nil {
return err
}
return nil
}
const (
VK_SP1 = 41
VK_SP2 = 12
VK_SP3 = 13
VK_SP4 = 26
VK_SP5 = 27
VK_SP6 = 39
VK_SP7 = 40
VK_SP8 = 43
VK_SP9 = 51
VK_SP10 = 52
VK_SP11 = 53
VK_SP12 = 86
VK_UP = 103
VK_DOWN = 108
VK_LEFT = 105
VK_RIGHT = 106
VK_ESC = 1
VK_1 = 2
VK_2 = 3
VK_3 = 4
VK_4 = 5
VK_5 = 6
VK_6 = 7
VK_7 = 8
VK_8 = 9
VK_9 = 10
VK_0 = 11
VK_Q = 16
VK_W = 17
VK_E = 18
VK_R = 19
VK_T = 20
VK_Y = 21
VK_U = 22
VK_I = 23
VK_O = 24
VK_P = 25
VK_A = 30
VK_S = 31
VK_D = 32
VK_F = 33
VK_G = 34
VK_H = 35
VK_J = 36
VK_K = 37
VK_L = 38
VK_Z = 44
VK_X = 45
VK_C = 46
VK_V = 47
VK_B = 48
VK_N = 49
VK_M = 50
VK_F1 = 59
VK_F2 = 60
VK_F3 = 61
VK_F4 = 62
VK_F5 = 63
VK_F6 = 64
VK_F7 = 65
VK_F8 = 66
VK_F9 = 67
VK_F10 = 68
VK_F11 = 87
VK_F12 = 88
VK_NUMLOCK = 69
VK_SCROLLLOCK = 70
VK_RESERVED = 0
VK_MINUS = 12
VK_EQUAL = 13
VK_BACKSPACE = 14
VK_TAB = 15
VK_LEFTBRACE = 26
VK_RIGHTBRACE = 27
VK_ENTER = 28
VK_SEMICOLON = 39
VK_APOSTROPHE = 40
VK_GRAVE = 41
VK_BACKSLASH = 43
VK_COMMA = 51
VK_DOT = 52
VK_SLASH = 53
VK_SPACE = 57
VK_CAPSLOCK = 58
VK_KP0 = 82
VK_KP1 = 79
VK_KP2 = 80
VK_KP3 = 81
VK_KP4 = 75
VK_KP5 = 76
VK_KP6 = 77
VK_KP7 = 71
VK_KP8 = 72
VK_KP9 = 73
VK_KPMINUS = 74
VK_KPPLUS = 78
VK_KPDOT = 83
VK_KPJPCOMMA = 95
VK_KPENTER = 96
VK_KPSLASH = 98
VK_KPASTERISK = 55
VK_KPEQUAL = 117
VK_KPPLUSMINUS = 118
VK_KPCOMMA = 121
VK_ZENKAKUHANKAKU = 85
VK_102ND = 86
VK_RO = 89
VK_KATAKANA = 90
VK_HIRAGANA = 91
VK_HENKAN = 92
VK_KATAKANAHIRAGANA = 93
VK_MUHENKAN = 94
VK_SYSRQ = 99
VK_LINEFEED = 101
VK_HOME = 102
VK_PAGEUP = 104
VK_END = 107
VK_PAGEDOWN = 109
VK_INSERT = 110
VK_DELETE = 111
VK_MACRO = 112
VK_MUTE = 113
VK_VOLUMEDOWN = 114
VK_VOLUMEUP = 115
VK_POWER = 116 /* SC System Power Down */
VK_PAUSE = 119
VK_SCALE = 120 /* AL Compiz Scale (Expose) */
VK_HANGEUL = 122
VK_HANGUEL = VK_HANGEUL
VK_HANJA = 123
VK_YEN = 124
VK_LEFTMETA = 125
VK_RIGHTMETA = 126
VK_COMPOSE = 127
VK_STOP = 128 /* AC Stop */
VK_AGAIN = 129
VK_PROPS = 130 /* AC Properties */
VK_UNDO = 131 /* AC Undo */
VK_FRONT = 132
VK_COPY = 133 /* AC Copy */
VK_OPEN = 134 /* AC Open */
VK_PASTE = 135 /* AC Paste */
VK_FIND = 136 /* AC Search */
VK_CUT = 137 /* AC Cut */
VK_HELP = 138 /* AL Integrated Help Center */
VK_MENU = 139 /* Menu (show menu) */
VK_CALC = 140 /* AL Calculator */
VK_SETUP = 141
VK_SLEEP = 142 /* SC System Sleep */
VK_WAKEUP = 143 /* System Wake Up */
VK_FILE = 144 /* AL Local Machine Browser */
VK_SENDFILE = 145
VK_DELETEFILE = 146
VK_XFER = 147
VK_PROG1 = 148
VK_PROG2 = 149
VK_WWW = 150 /* AL Internet Browser */
VK_MSDOS = 151
VK_COFFEE = 152 /* AL Terminal Lock/Screensaver */
VK_SCREENLOCK = VK_COFFEE
VK_ROTATE_DISPLAY = 153 /* Display orientation for e.g. tablets */
VK_DIRECTION = VK_ROTATE_DISPLAY
VK_CYCLEWINDOWS = 154
VK_MAIL = 155
VK_BOOKMARKS = 156 /* AC Bookmarks */
VK_COMPUTER = 157
VK_BACK = 158 /* AC Back */
VK_FORWARD = 159 /* AC Forward */
VK_CLOSECD = 160
VK_EJECTCD = 161
VK_EJECTCLOSECD = 162
VK_NEXTSONG = 163
VK_PLAYPAUSE = 164
VK_PREVIOUSSONG = 165
VK_STOPCD = 166
VK_RECORD = 167
VK_REWIND = 168
VK_PHONE = 169 /* Media Select Telephone */
VK_ISO = 170
VK_CONFIG = 171 /* AL Consumer Control Configuration */
VK_HOMEPAGE = 172 /* AC Home */
VK_REFRESH = 173 /* AC Refresh */
VK_EXIT = 174 /* AC Exit */
VK_MOVE = 175
VK_EDIT = 176
VK_SCROLLUP = 177
VK_SCROLLDOWN = 178
VK_KPLEFTPAREN = 179
VK_KPRIGHTPAREN = 180
VK_NEW = 181 /* AC New */
VK_REDO = 182 /* AC Redo/Repeat */
VK_F13 = 183
VK_F14 = 184
VK_F15 = 185
VK_F16 = 186
VK_F17 = 187
VK_F18 = 188
VK_F19 = 189
VK_F20 = 190
VK_F21 = 191
VK_F22 = 192
VK_F23 = 193
VK_F24 = 194
VK_PLAYCD = 200
VK_PAUSECD = 201
VK_PROG3 = 202
VK_PROG4 = 203
VK_DASHBOARD = 204 /* AL Dashboard */
VK_SUSPEND = 205
VK_CLOSE = 206 /* AC Close */
VK_PLAY = 207
VK_FASTFORWARD = 208
VK_BASSBOOST = 209
VK_PRINT = 210 /* AC Print */
VK_HP = 211
VK_CAMERA = 212
VK_SOUND = 213
VK_QUESTION = 214
VK_EMAIL = 215
VK_CHAT = 216
VK_SEARCH = 217
VK_CONNECT = 218
VK_FINANCE = 219 /* AL Checkbook/Finance */
VK_SPORT = 220
VK_SHOP = 221
VK_ALTERASE = 222
VK_CANCEL = 223 /* AC Cancel */
VK_BRIGHTNESSDOWN = 224
VK_BRIGHTNESSUP = 225
VK_MEDIA = 226
VK_SWITCHVIDEOMODE = 227 /* Cycle between available video
outputs (Monitor/LCD/TV-out/etc) */
VK_KBDILLUMTOGGLE = 228
VK_KBDILLUMDOWN = 229
VK_KBDILLUMUP = 230
VK_SEND = 231 /* AC Send */
VK_REPLY = 232 /* AC Reply */
VK_FORWARDMAIL = 233 /* AC Forward Msg */
VK_SAVE = 234 /* AC Save */
VK_DOCUMENTS = 235
VK_BATTERY = 236
VK_BLUETOOTH = 237
VK_WLAN = 238
VK_UWB = 239
VK_UNKNOWN = 240
VK_VIDEO_NEXT = 241 /* drive next video source */
VK_VIDEO_PREV = 242 /* drive previous video source */
VK_BRIGHTNESS_CYCLE = 243 /* brightness up, after max is min */
VK_BRIGHTNESS_AUTO = 244 /* Set Auto Brightness: manual
brightness control is off,
rely on ambient */
VK_BRIGHTNESS_ZERO = VK_BRIGHTNESS_AUTO
VK_DISPLAY_OFF = 245 /* display device to off state */
VK_WWAN = 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
VK_WIMAX = VK_WWAN
VK_RFKILL = 247 /* Key that controls all radios */
VK_MICMUTE = 248 /* Mute / unmute the microphone */
)
//http://thiemonge.org/getting-started-with-uinput