package evdev /* #include 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 }