package main import ( "flag" "fmt" "log" "net/http" "github.com/gvalkov/golang-evdev" ) const ( gamepadChanBufSize = 16 // Logitech gamepad codes codeLeftAnalogX = 0 codeLeftAnalogY = 1 codeLeftAnalogZ = 2 codeRightAnalogX = 3 codeRightAnalogY = 4 codeRightAnalogZ = 5 codeDPadX = 16 codeDPadY = 17 codeA = 304 codeB = 305 codeX = 307 codeY = 308 codeLeft = 310 codeRight = 311 codeBack = 314 codeStart = 315 codeLogitech = 316 codeLeftAnalog = 317 codeRightAnalog = 318 // event types button = iota axisX axisY axisZ ) type event struct { code int value int32 } func (e event) String() string { var code string switch e.code { case button: code = "button" case axisX: code = "X" case axisY: code = "Y" case axisZ: code = "Z" } return fmt.Sprintf("%v %v", code, e.value) } type gamepadEvents struct { leftAnalog, rightAnalog, dpad chan event a, b, x, y chan event left, right chan event back, start, logitech chan event } func main() { var ( gamepad string listen string ) flag.StringVar(&gamepad, "gamepad", "/dev/input/event0", "the gamepad device path") flag.StringVar(&listen, "listen", "localhost:8080", "the HTTP listen address and port") flag.Parse() if !evdev.IsInputDevice(gamepad) { log.Fatalf("%v is not an input device", gamepad) } device, err := evdev.Open(gamepad) if err != nil { log.Fatalf("error opening gamepad: %v", err) } events := &gamepadEvents{ leftAnalog: make(chan event, gamepadChanBufSize), rightAnalog: make(chan event, gamepadChanBufSize), dpad: make(chan event, gamepadChanBufSize), a: make(chan event, gamepadChanBufSize), b: make(chan event, gamepadChanBufSize), x: make(chan event, gamepadChanBufSize), y: make(chan event, gamepadChanBufSize), left: make(chan event, gamepadChanBufSize), right: make(chan event, gamepadChanBufSize), back: make(chan event, gamepadChanBufSize), start: make(chan event, gamepadChanBufSize), logitech: make(chan event, gamepadChanBufSize), } go control(events) go gamepadRead(device, events) log.Fatalf("error listening and serving: %v", http.ListenAndServe(listen, nil)) } func control(events *gamepadEvents) { for { select { case e := <-events.leftAnalog: log.Println("left analog", e) case e := <-events.rightAnalog: log.Println("right analog", e) case e := <-events.dpad: log.Println("dpad", e) case e := <-events.a: log.Println("a", e) case e := <-events.b: log.Println("b", e) case e := <-events.x: log.Println("x", e) case e := <-events.y: log.Println("y", e) case e := <-events.left: log.Println("left", e) case e := <-events.right: log.Println("right", e) case e := <-events.back: log.Println("back", e) case e := <-events.start: log.Println("start", e) case e := <-events.logitech: log.Println("logitech", e) } } } func gamepadRead(device *evdev.InputDevice, events *gamepadEvents) { for { e, err := device.ReadOne() if err != nil { log.Fatalf("error reading from gamepad: %v", err) } switch e.Type { case evdev.EV_ABS: switch e.Code { case codeLeftAnalogX: events.leftAnalog <- event{code: axisX, value: e.Value} case codeLeftAnalogY: events.leftAnalog <- event{code: axisY, value: e.Value} case codeLeftAnalogZ: events.leftAnalog <- event{code: axisZ, value: e.Value} case codeRightAnalogX: events.rightAnalog <- event{code: axisX, value: e.Value} case codeRightAnalogY: events.rightAnalog <- event{code: axisY, value: e.Value} case codeRightAnalogZ: events.rightAnalog <- event{code: axisZ, value: e.Value} case codeDPadX: events.dpad <- event{code: axisX, value: e.Value} case codeDPadY: events.dpad <- event{code: axisY, value: e.Value} } case evdev.EV_KEY: switch e.Code { case codeA: events.a <- event{code: button, value: e.Value} case codeB: events.b <- event{code: button, value: e.Value} case codeX: events.x <- event{code: button, value: e.Value} case codeY: events.y <- event{code: button, value: e.Value} case codeLeft: events.left <- event{code: button, value: e.Value} case codeRight: events.right <- event{code: button, value: e.Value} case codeBack: events.back <- event{code: button, value: e.Value} case codeStart: events.start <- event{code: button, value: e.Value} case codeLogitech: events.logitech <- event{code: button, value: e.Value} case codeLeftAnalog: events.leftAnalog <- event{code: button, value: e.Value} case codeRightAnalog: events.rightAnalog <- event{code: button, value: e.Value} } } } }