usbkvm.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package main
  2. /*
  3. usbkvm.go
  4. Handles the USB KVM device connections and auxiliary devices
  5. running in USB KVM mode. This mode only support 1 USB KVM device
  6. at a time.
  7. For running multiple USB KVM devices, use the ipkvm mode.
  8. */
  9. import (
  10. "encoding/json"
  11. "log"
  12. "net/http"
  13. "os"
  14. "os/signal"
  15. "syscall"
  16. "imuslab.com/dezukvm/dezukvmd/mod/remdesaux"
  17. "imuslab.com/dezukvm/dezukvmd/mod/remdeshid"
  18. "imuslab.com/dezukvm/dezukvmd/mod/usbcapture"
  19. )
  20. type UsbKvmConfig struct {
  21. ListeningAddress string
  22. USBKVMDevicePath string
  23. AuxMCUDevicePath string
  24. VideoCaptureDevicePath string
  25. AudioCaptureDevicePath string
  26. CaptureResolutionWidth int
  27. CaptureResolutionHeight int
  28. CaptureResolutionFPS int
  29. USBKVMBaudrate int
  30. AuxMCUBaudrate int
  31. }
  32. var (
  33. /* Internal variables for USB-KVM mode only */
  34. usbKVM *remdeshid.Controller
  35. auxMCU *remdesaux.AuxMcu
  36. usbCaptureDevice *usbcapture.Instance
  37. defaultUsbKvmConfig = &UsbKvmConfig{
  38. ListeningAddress: ":9000",
  39. USBKVMDevicePath: "/dev/ttyUSB0",
  40. AuxMCUDevicePath: "/dev/ttyACM0",
  41. VideoCaptureDevicePath: "/dev/video0",
  42. AudioCaptureDevicePath: "/dev/snd/pcmC1D0c",
  43. CaptureResolutionWidth: 1920,
  44. CaptureResolutionHeight: 1080,
  45. CaptureResolutionFPS: 25,
  46. USBKVMBaudrate: 115200,
  47. AuxMCUBaudrate: 115200,
  48. }
  49. )
  50. func loadUsbKvmConfig() (*UsbKvmConfig, error) {
  51. if _, err := os.Stat(usbKvmConfigPath); os.IsNotExist(err) {
  52. file, err := os.OpenFile(usbKvmConfigPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
  53. if err != nil {
  54. return nil, err
  55. }
  56. // Save default config as JSON
  57. enc := json.NewEncoder(file)
  58. enc.SetIndent("", " ")
  59. if err := enc.Encode(defaultUsbKvmConfig); err != nil {
  60. file.Close()
  61. return nil, err
  62. }
  63. file.Close()
  64. return defaultUsbKvmConfig, nil
  65. }
  66. // Load config from file
  67. file, err := os.Open(usbKvmConfigPath)
  68. if err != nil {
  69. return nil, err
  70. }
  71. cfg := &UsbKvmConfig{}
  72. dec := json.NewDecoder(file)
  73. if err := dec.Decode(cfg); err != nil {
  74. file.Close()
  75. return nil, err
  76. }
  77. file.Close()
  78. return cfg, nil
  79. }
  80. func startUsbKvmMode(config *UsbKvmConfig) error {
  81. log.Println("Starting in USB KVM mode...")
  82. // Initiate the HID controller
  83. usbKVM = remdeshid.NewHIDController(&remdeshid.Config{
  84. PortName: config.USBKVMDevicePath,
  85. BaudRate: config.USBKVMBaudrate,
  86. ScrollSensitivity: 0x01, // Set mouse scroll sensitivity
  87. })
  88. //Start the HID controller
  89. err := usbKVM.Connect()
  90. if err != nil {
  91. return err
  92. }
  93. //Start auxiliary MCU connections
  94. auxMCU, err = remdesaux.NewAuxOutbandController(config.AuxMCUDevicePath, config.AuxMCUBaudrate)
  95. if err != nil {
  96. return err
  97. }
  98. //Try get the UUID from the auxiliary MCU
  99. uuid, err := auxMCU.GetUUID()
  100. if err != nil {
  101. log.Println("Get UUID failed:", err, " - Auxiliary MCU may not be connected.")
  102. //Register dummy AUX routes if failed to get UUID
  103. registerDummyLocalAuxRoutes()
  104. } else {
  105. log.Println("Auxiliary MCU found with UUID:", uuid)
  106. //Register the AUX routes if success
  107. registerLocalAuxRoutes()
  108. }
  109. // Initiate the video capture device
  110. usbCaptureDevice, err = usbcapture.NewInstance(&usbcapture.Config{
  111. VideoDeviceName: config.VideoCaptureDevicePath,
  112. AudioDeviceName: config.AudioCaptureDevicePath,
  113. AudioConfig: usbcapture.GetDefaultAudioConfig(),
  114. })
  115. if err != nil {
  116. log.Println("Video capture device init failed:", err, " - Video capture device may not be connected.")
  117. return err
  118. }
  119. //Get device information for debug
  120. usbcapture.PrintV4L2FormatInfo(config.VideoCaptureDevicePath)
  121. //Start the video capture device
  122. err = usbCaptureDevice.StartVideoCapture(&usbcapture.CaptureResolution{
  123. Width: config.CaptureResolutionWidth,
  124. Height: config.CaptureResolutionHeight,
  125. FPS: config.CaptureResolutionFPS,
  126. })
  127. if err != nil {
  128. return err
  129. }
  130. // Handle program exit to close the HID controller
  131. c := make(chan os.Signal, 1)
  132. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  133. go func() {
  134. <-c
  135. log.Println("Shutting down usbKVM...")
  136. if auxMCU != nil {
  137. auxMCU.Close()
  138. }
  139. log.Println("Shutting down capture device...")
  140. if usbCaptureDevice != nil {
  141. usbCaptureDevice.Close()
  142. }
  143. os.Exit(0)
  144. }()
  145. // Register the rest of the API routes
  146. registerAPIRoutes()
  147. addr := config.ListeningAddress
  148. log.Printf("Serving on%s\n", addr)
  149. err = http.ListenAndServe(addr, nil)
  150. return err
  151. }