April 3, 2018

Reading linux mouse input with golang

I think mouse input in linux is generally awful. It always feels terrible in any window manager and I have begun digging into the whys. It seems mostly related with X adding acceleration. In my ventures I learned how to read from a mouse device without X. Lets read the mouse input from linux!

In UNIX’y operating systems everything is a file which many people seem to enjoy shouting off at irrelevant times with no context. For our purposes, this means the mouse will be represented as a file somewhere.

If you only have one mouse (why would you have two? freak) you can check /dev/input/mouse0

$ file /dev/input/mouse0

/dev/input/mouse0: character special (13/32)

With that we can see the mouse is a so called special’ which is short for a special file’, aka device file

A quick and dirty example in go to get the relative x/y update and whether or not left/right/middle is down would look something like this. Note this is blocking and could be drastically better

package main

import (
    "os"
    "log"
    "fmt"
)

// TODO https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/input.h#n28

func main() {
    f, err := os.OpenFile("/dev/input/mouse0", os.O_RDONLY, 0600)
    if err != nil {
        log.Fatal(err)
    }

    data := make([]byte,  3)

    for {
        nr, err := f.Read(data)
        if err != nil {
            log.Fatal(err)
        }

        if nr == 0 {
            break
        }
        
        left := data[0] & 0x1 != 0;
        right := data[0] & 0x2 != 0;
        middle := data[0] & 0x4 != 0;
        x := int8(data[1])
        y := int8(data[2])
        fmt.Printf("\r x=%d y=%d left=%v right=%v middle=%v ",
            x, y, left, right, middle)
    }
}

Assuming you have your GOPATH setup correctly (or use the default of ~/go), save this in a package called eg, linux-mouse-events.

Then you can test it like so (CTRL-C to exit):

$ go install linux-mouse-events
$ sudo ~/go/bin/linux-mouse-events
x=1 y=0 left=false right=false middle=false ^C

Amazing! Next we will move to timing evdev events to see if anything mucks with raw mouse report rate


Previous post
‘Le Potato’ boot serial port The AML-S905X-CC (Le Potato) is a strange beast. It doesn’t have reams of friendly documentations and is fairly barebones. I decided to start
Next post
NetBSD cross-compiling tutorial Lets build NetBSD starting from nothing! Thanks the to the great system I’ve already gushed about, cross-compiling NetBSD from any other POSIX’y