You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
keyboard-reader/evdev/evdev.go

182 lines
3.1 KiB

package evdev
/*
#include <linux/input.h>
static int _EVIOCGBIT(int ev, int len) {return EVIOCGBIT(ev, len);}
*/
import "C"
import (
"bytes"
"encoding/binary"
"os"
"syscall"
"unsafe"
)
const (
EVIOCGRAB = C.EVIOCGRAB // grab/release device
)
var keyMap = map[uint16]rune{
41: '`',
2: '1',
3: '2',
4: '3',
5: '4',
6: '5',
7: '6',
8: '7',
9: '8',
10: '9',
11: '0',
12: '-',
13: '=',
98: '/',
55: '*',
74: '-',
16: 'Q',
17: 'W',
18: 'E',
19: 'R',
20: 'T',
21: 'Y',
22: 'U',
23: 'I',
24: 'O',
25: 'P',
26: '[',
27: ']',
71: '7',
72: '8',
73: '9',
78: '+',
30: 'A',
31: 'S',
32: 'D',
33: 'F',
34: 'G',
35: 'H',
36: 'J',
37: 'K',
38: 'L',
39: ';',
40: '\'',
75: '4',
76: '5',
77: '6',
44: 'Z',
45: 'X',
46: 'C',
47: 'V',
48: 'B',
49: 'N',
50: 'M',
51: ',',
52: '.',
53: '/',
43: '\\',
79: '1',
80: '2',
81: '3',
57: ' ',
82: '0',
83: '.',
}
var eventSize = int(unsafe.Sizeof(InputEvent{}))
type InputEvent struct {
Time syscall.Timeval // time in seconds since epoch at which event occurred
Type uint16 // event type - one of ecodes.EV_*
Code uint16 // event code related to the event type
Value int32 // event value related to the event type
}
// InputDevice A Linux input device from which events can be read.
type InputDevice struct {
Fn string // path to input device (devnode)
bufLen int // read buffer size
Name string // device name
Phys string // physical topology of device
File *os.File // an open file handle to the input device
}
func EVIOCGBIT(ev, l int) int { return int(C._EVIOCGBIT(C.int(ev), C.int(l))) } // get event bits
// Open an evdev input device.
func Open(devNode string, bufLen int) (*InputDevice, error) {
f, err := os.Open(devNode)
if err != nil {
return nil, err
}
dev := InputDevice{}
dev.Fn = devNode
dev.File = f
dev.bufLen = bufLen
return &dev, nil
}
func (dev *InputDevice) Close() {
if dev.File != nil {
dev.File.Close()
}
}
func ioctl(fd uintptr, name uintptr, data unsafe.Pointer) syscall.Errno {
_, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, fd, name, uintptr(data))
return err
}
// Grab the input device exclusively.
func (dev *InputDevice) Grab() error {
grab := int(1)
if err := ioctl(dev.File.Fd(), uintptr(EVIOCGRAB), unsafe.Pointer(&grab)); err != 0 {
return err
}
return nil
}
// Release a grabbed input device.
func (dev *InputDevice) Release() error {
if err := ioctl(dev.File.Fd(), uintptr(EVIOCGRAB), unsafe.Pointer(nil)); err != 0 {
return err
}
return nil
}
// Read and return a slice of input events from device.
func (dev *InputDevice) Read() ([]InputEvent, error) {
buffer := make([]byte, eventSize*dev.bufLen)
count, err := dev.File.Read(buffer)
if err != nil {
return nil, err
}
events := make([]InputEvent, count/eventSize)
b := bytes.NewBuffer(buffer)
err = binary.Read(b, binary.LittleEndian, &events)
if err != nil {
return nil, err
}
return events, err
}
// GetKey Return appropriate key rune if present
func (event *InputEvent) GetKey() (rune, bool) {
if event.Type != 1 || event.Value != 1 {
return 0, false
}
r, ok := keyMap[event.Code]
return r, ok
}