main.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "github.com/gvalkov/golang-evdev"
  8. )
  9. const (
  10. // Logitech gamepad codes
  11. codeLeftAnalogX = 0
  12. codeLeftAnalogY = 1
  13. codeLeftAnalogZ = 2
  14. codeRightAnalogX = 3
  15. codeRightAnalogY = 4
  16. codeRightAnalogZ = 5
  17. codeDPadX = 16
  18. codeDPadY = 17
  19. codeA = 304
  20. codeB = 305
  21. codeX = 307
  22. codeY = 308
  23. codeLeft = 310
  24. codeRight = 311
  25. codeBack = 314
  26. codeStart = 315
  27. codeLogitech = 316
  28. codeLeftAnalog = 317
  29. codeRightAnalog = 318
  30. )
  31. const (
  32. // event types
  33. button = iota
  34. axisX
  35. axisY
  36. axisZ
  37. )
  38. const gamepadChanBufSize = 16
  39. type event struct {
  40. code int
  41. value int32
  42. }
  43. func (e event) String() string {
  44. var code string
  45. switch e.code {
  46. case button:
  47. code = "button"
  48. case axisX:
  49. code = "X"
  50. case axisY:
  51. code = "Y"
  52. case axisZ:
  53. code = "Z"
  54. }
  55. return fmt.Sprintf("%v %v", code, e.value)
  56. }
  57. type gamepadEvents struct {
  58. leftAnalog, rightAnalog, dpad chan event
  59. a, b, x, y chan event
  60. left, right chan event
  61. back, start, logitech chan event
  62. }
  63. const (
  64. // drive modes
  65. tank = iota
  66. joystick
  67. )
  68. const driveModeCount = 2
  69. type driveMode int
  70. func (d driveMode) String() string {
  71. switch d {
  72. case tank:
  73. return "tank"
  74. case joystick:
  75. return "joystick"
  76. default:
  77. return "unknown"
  78. }
  79. }
  80. func (d *driveMode) Set(value string) error {
  81. switch value {
  82. case "tank":
  83. *d = tank
  84. case "joystick":
  85. *d = joystick
  86. default:
  87. return fmt.Errorf("unknown drive mode: %v", value)
  88. }
  89. return nil
  90. }
  91. func main() {
  92. var (
  93. gamepad string
  94. listen string
  95. mode driveMode
  96. )
  97. flag.StringVar(&gamepad, "gamepad", "/dev/input/event0", "the gamepad device path")
  98. flag.StringVar(&listen, "listen", "localhost:8080", "the HTTP listen address and port")
  99. flag.Var(&mode, "mode", "the drive mode (default \"tank\")")
  100. flag.Parse()
  101. if !evdev.IsInputDevice(gamepad) {
  102. log.Fatalf("%v is not an input device", gamepad)
  103. }
  104. device, err := evdev.Open(gamepad)
  105. if err != nil {
  106. log.Fatalf("error opening gamepad: %v", err)
  107. }
  108. events := &gamepadEvents{
  109. leftAnalog: make(chan event, gamepadChanBufSize),
  110. rightAnalog: make(chan event, gamepadChanBufSize),
  111. dpad: make(chan event, gamepadChanBufSize),
  112. a: make(chan event, gamepadChanBufSize),
  113. b: make(chan event, gamepadChanBufSize),
  114. x: make(chan event, gamepadChanBufSize),
  115. y: make(chan event, gamepadChanBufSize),
  116. left: make(chan event, gamepadChanBufSize),
  117. right: make(chan event, gamepadChanBufSize),
  118. back: make(chan event, gamepadChanBufSize),
  119. start: make(chan event, gamepadChanBufSize),
  120. logitech: make(chan event, gamepadChanBufSize),
  121. }
  122. go control(mode, events)
  123. go gamepadRead(device, events)
  124. log.Print("HTTP server started")
  125. log.Fatalf("error listening and serving: %v", http.ListenAndServe(listen, nil))
  126. }
  127. func control(mode driveMode, events *gamepadEvents) {
  128. log.Printf("control loop started (drive mode: %v)", mode)
  129. for {
  130. select {
  131. case e := <-events.leftAnalog:
  132. log.Println("left analog", e)
  133. case e := <-events.rightAnalog:
  134. log.Println("right analog", e)
  135. case e := <-events.dpad:
  136. log.Println("dpad", e)
  137. case e := <-events.a:
  138. log.Println("a", e)
  139. case e := <-events.b:
  140. log.Println("b", e)
  141. case e := <-events.x:
  142. log.Println("x", e)
  143. case e := <-events.y:
  144. log.Println("y", e)
  145. case e := <-events.left:
  146. log.Println("left", e)
  147. case e := <-events.right:
  148. log.Println("right", e)
  149. case e := <-events.back:
  150. log.Println("back", e)
  151. case e := <-events.start:
  152. log.Println("start", e)
  153. case e := <-events.logitech:
  154. if e.value > 0 {
  155. mode++
  156. mode %= driveModeCount
  157. log.Printf("switched drive mode: %v", mode)
  158. }
  159. }
  160. }
  161. }
  162. func gamepadRead(device *evdev.InputDevice, events *gamepadEvents) {
  163. log.Print("gamepad read loop started")
  164. for {
  165. e, err := device.ReadOne()
  166. if err != nil {
  167. log.Fatalf("error reading from gamepad: %v", err)
  168. }
  169. switch e.Type {
  170. case evdev.EV_ABS:
  171. switch e.Code {
  172. case codeLeftAnalogX:
  173. events.leftAnalog <- event{code: axisX, value: e.Value}
  174. case codeLeftAnalogY:
  175. events.leftAnalog <- event{code: axisY, value: e.Value}
  176. case codeLeftAnalogZ:
  177. events.leftAnalog <- event{code: axisZ, value: e.Value}
  178. case codeRightAnalogX:
  179. events.rightAnalog <- event{code: axisX, value: e.Value}
  180. case codeRightAnalogY:
  181. events.rightAnalog <- event{code: axisY, value: e.Value}
  182. case codeRightAnalogZ:
  183. events.rightAnalog <- event{code: axisZ, value: e.Value}
  184. case codeDPadX:
  185. events.dpad <- event{code: axisX, value: e.Value}
  186. case codeDPadY:
  187. events.dpad <- event{code: axisY, value: e.Value}
  188. }
  189. case evdev.EV_KEY:
  190. switch e.Code {
  191. case codeA:
  192. events.a <- event{code: button, value: e.Value}
  193. case codeB:
  194. events.b <- event{code: button, value: e.Value}
  195. case codeX:
  196. events.x <- event{code: button, value: e.Value}
  197. case codeY:
  198. events.y <- event{code: button, value: e.Value}
  199. case codeLeft:
  200. events.left <- event{code: button, value: e.Value}
  201. case codeRight:
  202. events.right <- event{code: button, value: e.Value}
  203. case codeBack:
  204. events.back <- event{code: button, value: e.Value}
  205. case codeStart:
  206. events.start <- event{code: button, value: e.Value}
  207. case codeLogitech:
  208. events.logitech <- event{code: button, value: e.Value}
  209. case codeLeftAnalog:
  210. events.leftAnalog <- event{code: button, value: e.Value}
  211. case codeRightAnalog:
  212. events.rightAnalog <- event{code: button, value: e.Value}
  213. }
  214. }
  215. }
  216. }