Browse Source

Read from Logitech gamepad

Douglas Thrift 1 year ago
parent
commit
71396e2230
4 changed files with 198 additions and 0 deletions
  1. 3 0
      go.mod
  2. 2 0
      go.sum
  3. 1 0
      rover/.gitignore
  4. 192 0
      rover/main.go

+ 3 - 0
go.mod

@@ -0,0 +1,3 @@
+module douglasthrift.net/dtrobots
+
+require github.com/gvalkov/golang-evdev v0.0.0-20180516222720-b6f418b1fe5a

+ 2 - 0
go.sum

@@ -0,0 +1,2 @@
+github.com/gvalkov/golang-evdev v0.0.0-20180516222720-b6f418b1fe5a h1:PpqPstphGuFEdiuje4K8NmWN+Qzvu15NN/oFa1w/lGM=
+github.com/gvalkov/golang-evdev v0.0.0-20180516222720-b6f418b1fe5a/go.mod h1:SAzVFKCRezozJTGavF3GX8MBUruETCqzivVLYiywouA=

+ 1 - 0
rover/.gitignore

@@ -0,0 +1 @@
+rover

+ 192 - 0
rover/main.go

@@ -0,0 +1,192 @@
+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}
+			}
+		}
+	}
+}