Browse Source

Added Aux MCU APIs

TC 2 weeks ago
parent
commit
227cd03d3b
3 changed files with 264 additions and 9 deletions
  1. 46 9
      remdeskd/main.go
  2. 78 0
      remdeskd/mod/remdesaux/handlers.go
  3. 140 0
      remdeskd/mod/remdesaux/remdesaux.go

+ 46 - 9
remdeskd/main.go

@@ -11,6 +11,7 @@ import (
 	"syscall"
 	"time"
 
+	"imuslab.com/remdeskvm/remdeskd/mod/remdesaux"
 	"imuslab.com/remdeskvm/remdeskd/mod/remdeshid"
 	"imuslab.com/remdeskvm/remdeskd/mod/usbcapture"
 )
@@ -18,13 +19,18 @@ import (
 const defaultDevMode = true
 
 var (
-	developent        = flag.Bool("dev", defaultDevMode, "Enable development mode with local static files")
-	mode              = flag.String("mode", "usbkvm", "Mode of operation: kvm or capture")
-	usbKVMDeviceName  = flag.String("usbkvm", "/dev/ttyUSB0", "USB KVM device file path")
-	usbKVMBaudRate    = flag.Int("baudrate", 115200, "USB KVM baud rate")
-	captureDeviceName = flag.String("capture", "/dev/video0", "Video capture device file path")
-	usbKVM            *remdeshid.Controller
-	videoCapture      *usbcapture.Instance
+	developent            = flag.Bool("dev", defaultDevMode, "Enable development mode with local static files")
+	mode                  = flag.String("mode", "usbkvm", "Mode of operation: kvm or capture")
+	usbKVMDeviceName      = flag.String("usbhid", "/dev/ttyUSB0", "USB KVM device file path")
+	usbAuxilaryDeviceName = flag.String("auxmcu", "/dev/ttyACM0", "USB Auxiliary MCU device file path")
+	usbKVMBaudRate        = flag.Int("baudrate", 115200, "USB KVM baud rate")
+	usbAuxBaudRate        = flag.Int("auxbaudrate", 115200, "USB Auxiliary MCU baud rate")
+	captureDeviceName     = flag.String("capture", "/dev/video0", "Video capture device file path")
+
+	/* Internal Modules */
+	usbKVM       *remdeshid.Controller
+	auxMCU       *remdesaux.AuxMcu
+	videoCapture *usbcapture.Instance
 )
 
 /* Web Server Static Files */
@@ -91,6 +97,20 @@ func main() {
 			log.Fatal(err)
 		}
 
+		//Start auxiliary MCU connections
+		auxMCU, err = remdesaux.NewAuxOutbandController(*usbAuxilaryDeviceName, *usbAuxBaudRate)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		//Try get the UUID from the auxiliary MCU
+		uuid, err := auxMCU.GetUUID()
+		if err != nil {
+			log.Println("Get UUID failed:", err)
+		} else {
+			log.Println("Auxiliary MCU UUID:", uuid)
+		}
+
 		// Initiate the video capture device
 		videoCapture, err = usbcapture.NewInstance(&usbcapture.Config{
 			DeviceName:  *captureDeviceName,
@@ -121,9 +141,17 @@ func main() {
 		go func() {
 			<-c
 			log.Println("Shutting down usbKVM...")
-			//usbKVM.Close() //To fix close stuck layer
+			if usbKVM != nil {
+				//usbKVM.Close()
+			}
+
+			if auxMCU != nil {
+				auxMCU.Close()
+			}
 			log.Println("Shutting down capture device...")
-			videoCapture.Close()
+			if videoCapture != nil {
+				videoCapture.Close()
+			}
 			os.Exit(0)
 		}()
 
@@ -132,6 +160,15 @@ func main() {
 		http.HandleFunc("/hid", usbKVM.HIDWebSocketHandler)
 		http.HandleFunc("/audio", videoCapture.AudioStreamingHandler)
 		http.HandleFunc("/stream", videoCapture.ServeVideoStream)
+
+		http.HandleFunc("/aux/switchusbkvm", auxMCU.HandleSwitchUSBToKVM)
+		http.HandleFunc("/aux/switchusbremote", auxMCU.HandleSwitchUSBToRemote)
+		http.HandleFunc("/aux/presspower", auxMCU.HandlePressPowerButton)
+		http.HandleFunc("/aux/releasepower", auxMCU.HandleReleasePowerButton)
+		http.HandleFunc("/aux/pressreset", auxMCU.HandlePressResetButton)
+		http.HandleFunc("/aux/releasereset", auxMCU.HandleReleaseResetButton)
+		http.HandleFunc("/aux/getuuid", auxMCU.HandleGetUUID)
+
 		addr := ":9000"
 		log.Printf("Serving on http://localhost%s\n", addr)
 		log.Fatal(http.ListenAndServe(addr, nil))

+ 78 - 0
remdeskd/mod/remdesaux/handlers.go

@@ -0,0 +1,78 @@
+package remdesaux
+
+import (
+	"encoding/json"
+	"net/http"
+)
+
+// Handler for switching USB to KVM side
+func (c *AuxMcu) HandleSwitchUSBToKVM(w http.ResponseWriter, r *http.Request) {
+	if err := c.SwitchUSBToKVM(); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+}
+
+// Handler for switching USB to Remote side
+func (c *AuxMcu) HandleSwitchUSBToRemote(w http.ResponseWriter, r *http.Request) {
+	if err := c.SwitchUSBToRemote(); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+}
+
+// Handler for pressing the power button
+func (c *AuxMcu) HandlePressPowerButton(w http.ResponseWriter, r *http.Request) {
+	if err := c.PressPowerButton(); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+}
+
+// Handler for releasing the power button
+func (c *AuxMcu) HandleReleasePowerButton(w http.ResponseWriter, r *http.Request) {
+	if err := c.ReleasePowerButton(); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+}
+
+// Handler for pressing the reset button
+func (c *AuxMcu) HandlePressResetButton(w http.ResponseWriter, r *http.Request) {
+	if err := c.PressResetButton(); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+}
+
+// Handler for releasing the reset button
+func (c *AuxMcu) HandleReleaseResetButton(w http.ResponseWriter, r *http.Request) {
+	if err := c.ReleaseResetButton(); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+}
+
+// Handler for getting the UUID
+func (c *AuxMcu) HandleGetUUID(w http.ResponseWriter, r *http.Request) {
+	uuid, err := c.GetUUID()
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(map[string]string{"uuid": uuid})
+}
+
+// Handler for getting the USB mass storage side
+func (c *AuxMcu) HandleGetUSBMassStorageSide(w http.ResponseWriter, r *http.Request) {
+	side := c.GetUSBMassStorageSide()
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(map[string]interface{}{"usb_mass_storage_side": side})
+}

+ 140 - 0
remdeskd/mod/remdesaux/remdesaux.go

@@ -0,0 +1,140 @@
+package remdesaux
+
+/*
+	RemdesAux - Auxiliary MCU Control for RemdeskVM
+
+	This module provides functions to interact with the auxiliary MCU (CH552G)
+	used in RemdeskVM for managing USB switching and power/reset button simulation.
+*/
+
+import (
+	"bufio"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/tarm/serial"
+)
+
+type USB_mass_storage_side int
+
+const (
+	USB_MASS_STORAGE_KVM USB_mass_storage_side = iota
+	USB_MASS_STORAGE_REMOTE
+)
+
+type AuxMcu struct {
+	usb_mass_storage_side USB_mass_storage_side
+	port                  *serial.Port
+	reader                *bufio.Reader
+	mu                    sync.Mutex
+}
+
+// NewAuxOutbandController initializes a new AuxMcu instance
+func NewAuxOutbandController(portName string, baudRate int) (*AuxMcu, error) {
+	c := &serial.Config{
+		Name:        portName,
+		Baud:        baudRate,
+		ReadTimeout: time.Second * 2,
+	}
+	port, err := serial.OpenPort(c)
+	if err != nil {
+		return nil, err
+	}
+	return &AuxMcu{
+		usb_mass_storage_side: USB_MASS_STORAGE_KVM, //Default to KVM side, defined in MCU firmware
+		port:                  port,
+		reader:                bufio.NewReader(port),
+	}, nil
+}
+
+func (c *AuxMcu) Close() error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.port != nil {
+		return c.port.Close()
+	}
+	return nil
+}
+
+// sendCommand writes a single byte command to the serial port
+func (c *AuxMcu) sendCommand(cmd byte) error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	_, err := c.port.Write([]byte{cmd})
+	return err
+}
+
+// SwitchUSBToKVM switches USB mass storage to KVM side
+func (c *AuxMcu) SwitchUSBToKVM() error {
+	c.usb_mass_storage_side = USB_MASS_STORAGE_KVM
+	return c.sendCommand('m')
+}
+
+// SwitchUSBToRemote switches USB mass storage to remote computer
+func (c *AuxMcu) SwitchUSBToRemote() error {
+	c.usb_mass_storage_side = USB_MASS_STORAGE_REMOTE
+	return c.sendCommand('n')
+}
+
+// PressPowerButton simulates pressing the power button
+func (c *AuxMcu) PressPowerButton() error {
+	return c.sendCommand('p')
+}
+
+// ReleasePowerButton simulates releasing the power button
+func (c *AuxMcu) ReleasePowerButton() error {
+	return c.sendCommand('s')
+}
+
+// PressResetButton simulates pressing the reset button
+func (c *AuxMcu) PressResetButton() error {
+	return c.sendCommand('r')
+}
+
+// ReleaseResetButton simulates releasing the reset button
+func (c *AuxMcu) ReleaseResetButton() error {
+	return c.sendCommand('d')
+}
+
+// GetUUID requests the device UUID and returns it as a string
+func (c *AuxMcu) GetUUID() (string, error) {
+	if err := c.sendCommand('u'); err != nil {
+		return "", err
+	}
+	line, err := c.reader.ReadString('\n')
+	if err != nil {
+		return "", err
+	}
+
+	line = strings.TrimSpace(line)
+	return line, nil
+}
+
+func (c *AuxMcu) GetUSBMassStorageSide() USB_mass_storage_side {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	return c.usb_mass_storage_side
+}
+
+// Example usage
+/*
+func Example() {
+	dev, err := NewCH552G("/dev/ttyUSB0", 115200)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer dev.Close()
+
+	if err := dev.SwitchUSBToKVM(); err != nil {
+		log.Println("Switch to KVM failed:", err)
+	}
+	uuid, err := dev.GetUUID()
+	if err != nil {
+		log.Println("Get UUID failed:", err)
+	} else {
+		fmt.Println("Device UUID:", uuid)
+	}
+}
+
+*/