/* package input is a thing Go wrapper around the Linux kernel input event * system. */ package input import "gitlab.com/beoran/galago/os/linux" import "os" import "unsafe" import "syscall" import "fmt" import "path/filepath" // Device models an input device type Device struct { *os.File } const Directory = "/dev/input" func Open(name string) (*Device, error) { f, err := os.OpenFile(filepath.Join(Directory, name), os.O_RDWR, 0666) if err != nil { return nil, err } return &Device{File: f}, nil } func List() ([]string, error) { dir, err := os.Open(Directory) if err != nil { return nil, err } return dir.Readdirnames(-1) } // Icotl performs an ioctl on the given de func (d * Device) Ioctl(code uint32, pointer unsafe.Pointer) error { fmt.Printf("ioctl: %d %d %d\n", uintptr(d.Fd()), uintptr(code), uintptr(pointer)) _, _, errno := syscall.Syscall( syscall.SYS_IOCTL, uintptr(d.Fd()), uintptr(code), uintptr(pointer)) if (errno != 0) { return errno } return nil } func (d * Device) DriverVersion() (int32, error) { res := int32(0) data := unsafe.Pointer(&res) err := d.Ioctl(linux.EVIOCGVERSION, data) return res, err } func (d * Device) Name() (string, error) { buffer := [256]byte{} err := d.Ioctl(linux.EVIOCGNAME(uintptr(len(buffer))), unsafe.Pointer(&buffer)) return string(buffer[0:len(buffer)]), err } func BitsToLong(bits int) int { var ul linux.UnsignedLong return ((bits) + 8 * unsafe.Sizeof(ul) - 1) / (8 * unsafe.Sizeof(ul)) } func TestBit(bit int, array []uint8) { const BITS_PER_LONG = sizeof(long) * 8) #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) #define OFF(x) ((x)%BITS_PER_LONG) #define BIT(x) (1UL<> OFF(bit)) & 1) func (d * Device) Id() (linux.INPUT_id, error) { var result linux.INPUT_id err := d.Ioctl(linux.EVIOCGID, unsafe.Pointer(&result)) return result, err int fd, rd, i, j, k; struct input_event ev[64]; int version; unsigned short id[4]; unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; char name[256] = "Unknown"; int abs[5]; func (d * Device) SupportedEvents() ([]uint32, error) ( var bit [linux.EV_MAX] uint64 device.Ioctl(fd, EVIOCGBIT(0, EV_MAX), unsafe.Pointer(&bit)); printf("Supported events:\n"); for (i = 0; i < EV_MAX; i++) if (test_bit(i, bit[0])) { } printf("Testing ... (interrupt to exit)\n"); while (1) { rd = read(fd, ev, sizeof(struct input_event) * 64); if (rd < (int) sizeof(struct input_event)) { printf("yyy\n"); perror("\nevtest: error reading"); return 1; } for (i = 0; i < rd / sizeof(struct input_event); i++) if (ev[i].type == EV_SYN) { printf("Event: time %ld.%06ld, -------------- %s ------------\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" ); } else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) { printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %02x\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?", ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", ev[i].value); } else { printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n", ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type, events[ev[i].type] ? events[ev[i].type] : "?", ev[i].code, names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?", ev[i].value); } } }