Browse Source

Added cfgchip device name write

TC 2 weeks ago
parent
commit
e1ba1feb5c

+ 9 - 9
remdeskd/main.go

@@ -62,15 +62,6 @@ func main() {
 			log.Fatal(err)
 		}
 
-		/*
-			log.Println("Starting in Configure Chip mode...")
-			time.Sleep(2 * time.Second) // Wait for the controller to initialize
-			_, err = usbKVM.WriteChipProperties()
-			if err != nil {
-				log.Fatalf("Failed to write chip properties: %v", err)
-				return
-			}
-		*/
 		time.Sleep(1 * time.Second) // Wait for the controller to initialize
 		log.Println("Updating chip baudrate to 115200...")
 		//Configure the HID controller
@@ -80,6 +71,15 @@ func main() {
 			return
 		}
 		time.Sleep(1 * time.Second)
+
+		log.Println("Setting chip USB device properties...")
+		time.Sleep(2 * time.Second) // Wait for the controller to initialize
+		_, err = usbKVM.WriteChipProperties()
+		if err != nil {
+			log.Fatalf("Failed to write chip properties: %v", err)
+			return
+		}
+
 		log.Println("Configuration command sent. Unplug the device and plug it back in to apply the changes.")
 	case "usbkvm":
 

+ 7 - 4
remdeskd/mod/remdeshid/ch9329.go

@@ -38,6 +38,7 @@ func (c *Controller) ConfigureChipTo115200() error {
 		return errors.New("failed to get reply")
 	}
 
+	fmt.Println()
 	fmt.Print("Reply: ")
 	for _, b := range resp {
 		fmt.Printf("0x%02X ", b)
@@ -50,13 +51,14 @@ func (c *Controller) ConfigureChipTo115200() error {
 func (c *Controller) WriteChipProperties() ([]byte, error) {
 	manufacturerString := []byte{
 		0x57, 0xAB, 0x00, 0x0B,
+		0x09, // Length of payload
 		0x00, // Set manufacturer string
-		0x07, // Length of the string
+		0x07, // Length of the USB manufacturer string
 		'i', 'm', 'u', 's', 'l', 'a', 'b',
 		0x00, // Checksum placeholder
 	}
 
-	manufacturerString[13] = calcChecksum(manufacturerString[:13])
+	manufacturerString[14] = calcChecksum(manufacturerString[:14])
 	// Send set manufacturer string
 	err := c.Send(manufacturerString)
 	if err != nil {
@@ -69,13 +71,14 @@ func (c *Controller) WriteChipProperties() ([]byte, error) {
 
 	productString := []byte{
 		0x57, 0xAB, 0x00, 0x0B,
+		0x0B, // Length of the payload
 		0x01, // Set product string
-		0x09, // Length of the string
+		0x09, // Length of the USB product string
 		'R', 'e', 'm', 'd', 'e', 's', 'K', 'V', 'M',
 		0x00, // Checksum placeholder
 	}
 
-	productString[15] = calcChecksum(productString[:15])
+	productString[16] = calcChecksum(productString[:16])
 	// Send set product string
 	err = c.Send(productString)
 	if err != nil {

+ 18 - 5
remdeskd/mod/remdeshid/keyboard.go

@@ -193,11 +193,6 @@ func javaScriptKeycodeToHIDOpcode(keycode uint8) uint8 {
 		return (keycode - 49) + 0x1E // '1' is 0x1E
 	}
 
-	// Numpad 1-9
-	if keycode >= 97 && keycode <= 105 {
-		return (keycode - 97) + 0x59 // '1' (numpad) is 0x59
-	}
-
 	// F1 to F12
 	if keycode >= 112 && keycode <= 123 {
 		return (keycode - 112) + 0x3A // 'F1' is 0x3A
@@ -260,6 +255,24 @@ func javaScriptKeycodeToHIDOpcode(keycode uint8) uint8 {
 		return 0x65 // Menu key
 	case 96:
 		return 0x62 // 0 (Numpads)
+	case 97:
+		return 0x59 // 1 (Numpads)
+	case 98:
+		return 0x5A // 2 (Numpads)
+	case 99:
+		return 0x5B // 3 (Numpads)
+	case 100:
+		return 0x5C // 4 (Numpads)
+	case 101:
+		return 0x5D // 5 (Numpads)
+	case 102:
+		return 0x5E // 6 (Numpads)
+	case 103:
+		return 0x5F // 7 (Numpads)
+	case 104:
+		return 0x60 // 8 (Numpads)
+	case 105:
+		return 0x61 // 9 (Numpads)
 	case 106:
 		return 0x55 // * (Numpads)
 	case 107:

+ 73 - 1
remdeskd/mod/usbcapture/audio_device.go

@@ -97,8 +97,64 @@ func GetDefaultAudioConfig() *AudioConfig {
 	}
 }
 
+// Downsample48kTo24kStereo downsamples a 48kHz stereo audio buffer to 24kHz.
+// It assumes the input buffer is in 16-bit stereo format (2 bytes per channel).
+// The output buffer will also be in 16-bit stereo format.
+func downsample48kTo24kStereo(buf []byte) []byte {
+	const frameSize = 4 // 2 bytes per channel × 2 channels
+	if len(buf)%frameSize != 0 {
+		// Trim incomplete frame (rare case)
+		buf = buf[:len(buf)-len(buf)%frameSize]
+	}
+
+	out := make([]byte, 0, len(buf)/2)
+
+	for i := 0; i < len(buf); i += frameSize * 2 {
+		// Copy every other frame (drop 1 in 2)
+		if i+frameSize <= len(buf) {
+			out = append(out, buf[i:i+frameSize]...)
+		}
+	}
+
+	return out
+}
+
+// Downsample48kTo16kStereo downsamples a 48kHz stereo audio buffer to 16kHz.
+// It assumes the input buffer is in 16-bit stereo format (2 bytes per channel).
+// The output buffer will also be in 16-bit stereo format.
+func downsample48kTo16kStereo(buf []byte) []byte {
+	const frameSize = 4 // 2 bytes per channel × 2 channels
+	if len(buf)%frameSize != 0 {
+		// Trim incomplete frame (rare case)
+		buf = buf[:len(buf)-len(buf)%frameSize]
+	}
+
+	out := make([]byte, 0, len(buf)/3)
+
+	for i := 0; i < len(buf); i += frameSize * 3 {
+		// Copy every third frame (drop 2 in 3)
+		if i+frameSize <= len(buf) {
+			out = append(out, buf[i:i+frameSize]...)
+		}
+	}
+
+	return out
+}
+
 // AudioStreamingHandler handles incoming WebSocket connections for audio streaming.
 func (i Instance) AudioStreamingHandler(w http.ResponseWriter, r *http.Request) {
+
+	// Check if the request contains ?quality=low
+	quality := r.URL.Query().Get("quality")
+	qualityKey := []string{"low", "standard", "high"}
+	selectedQuality := "standard"
+	for _, q := range qualityKey {
+		if quality == q {
+			selectedQuality = q
+			break
+		}
+	}
+
 	conn, err := upgrader.Upgrade(w, r, nil)
 	if err != nil {
 		log.Println("Failed to upgrade to websocket:", err)
@@ -196,9 +252,25 @@ func (i Instance) AudioStreamingHandler(w http.ResponseWriter, r *http.Request)
 				continue
 			}
 
+			downsampled := buf[:n] // Default to original buffer if no downsampling
+			switch selectedQuality {
+			case "high":
+				// Keep original 48kHz stereo
+
+			case "standard":
+				// Downsample to 24kHz stereo
+				downsampled = downsample48kTo24kStereo(buf[:n]) // Downsample to 24kHz stereo
+				copy(buf, downsampled)                          // Copy downsampled data back into buf
+				n = len(downsampled)                            // Update n to the new length
+			case "low":
+				downsampled = downsample48kTo16kStereo(buf[:n]) // Downsample to 16kHz stereo
+				copy(buf, downsampled)                          // Copy downsampled data back into buf
+				n = len(downsampled)                            // Update n to the new length
+			}
+
 			//log.Println("Read bytes:", n, "size of buffer:", len(buf))
 			//Send only the bytes read to WebSocket
-			err = conn.WriteMessage(websocket.BinaryMessage, buf[:n])
+			err = conn.WriteMessage(websocket.BinaryMessage, downsampled[:n])
 			if err != nil {
 				log.Println("WebSocket send error:", err)
 				goto DONE

+ 42 - 54
remdeskd/www/index.html

@@ -3,33 +3,21 @@
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <meta name="description" content="A basic Hello World HTML page with metadata and OpenGraph headers">
-    <meta name="author" content="Your Name">
-    <title>Hello World</title>
+    <meta name="description" content="RemdesKVM Management Interface">
+    <meta name="author" content="imuslab">
+    <title>Connected | RemdesKVM</title>
     
     <!-- OpenGraph Metadata -->
-    <meta property="og:title" content="Hello World">
-    <meta property="og:description" content="A basic Hello World HTML page with metadata and OpenGraph headers">
+    <meta property="og:title" content="RemdesKVM Management Interface">
+    <meta property="og:description" content="A web-based management interface for RemdesKVM">
     <meta property="og:type" content="website">
-    <meta property="og:url" content="http://example.com">
-    <meta property="og:image" content="http://example.com/image.jpg">
+    <meta property="og:url" content="https://kvm.aroz.org">
+    <meta property="og:image" content="https://kvm.aroz.org/og.jpg">
     <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
-    <style>
-        body{
-            margin: 0;
-        }
-
-        #remoteCapture{
-            width: 100%;
-        }
-
-    </style>
+    <link rel="stylesheet" href="/main.css">
 </head>
 <body>
-    <button onclick="startAudioWebSocket()">Start Audio</button>
-    <button onclick="stopAudioWebSocket()">Stop Audio</button>
     <img id="remoteCapture" src="/stream" oncontextmenu="return false;"></img>
-    
     <script>
         let socket;
         let protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
@@ -37,22 +25,16 @@
         let socketURL = `${protocol}://${window.location.hostname}:${port}/hid`;
         let mouseMoveAbsolte = true; // Set to true for absolute mouse coordinates, false for relativeZ
         let mouseIsOutside = false;
-        let mouseButtonState = [0, 0, 0]; // Array to track mouse button states, left, middle, right
+        let audioFrontendStarted = false;
 
         /* Mouse events */
         function handleMouseMove(event) {
-            const mouseButtonBits = mouseButtonState.reduce((acc, state, index) => {
-                return acc | (state << index);
-            }, 0);
             const hidCommand = {
                 event: 2,
                 mouse_x: event.clientX,
                 mouse_y: event.clientY,
-                //mouse_move_button_state: mouseButtonBits // Combine mouse button states into a single bitmask
             };
 
-
-
             const rect = event.target.getBoundingClientRect();
             const relativeX = event.clientX - rect.left;
             const relativeY = event.clientY - rect.top;
@@ -68,9 +50,9 @@
             hidCommand.mouse_x = Math.round(percentageX);
             hidCommand.mouse_y = Math.round(percentageY);
 
-            console.log(`Mouse move: (${event.clientX}, ${event.clientY})`);
-            console.log(`Mouse move relative: (${relativeX}, ${relativeY})`);
-            console.log(`Mouse move percentage: (${hidCommand.mouse_x}, ${hidCommand.mouse_y})`);
+            //console.log(`Mouse move: (${event.clientX}, ${event.clientY})`);
+            //console.log(`Mouse move relative: (${relativeX}, ${relativeY})`);
+            //console.log(`Mouse move percentage: (${hidCommand.mouse_x}, ${hidCommand.mouse_y})`);
 
             if (socket && socket.readyState === WebSocket.OPEN) {
                 socket.send(JSON.stringify(hidCommand));
@@ -98,12 +80,7 @@
                 mouse_button: buttonMap[event.button] || 0
             };
 
-            // Update mouse button state
-            if (event.button >= 0 && event.button < mouseButtonState.length) {
-                mouseButtonState[event.button] = 1; // Set button state to pressed
-            }
             // Log the mouse button state
-
             console.log(`Mouse down: ${hidCommand.mouse_button}`);
 
             if (socket && socket.readyState === WebSocket.OPEN) {
@@ -111,6 +88,11 @@
             } else {
                 console.error("WebSocket is not open.");
             }
+
+            if (!audioFrontendStarted){
+                startAudioWebSocket();
+                audioFrontendStarted = true;
+            }
         }
 
         function handleMouseRelease(event) {
@@ -131,11 +113,6 @@
                 mouse_button: buttonMap[event.button] || 0
             };
 
-            // Update mouse button state
-            if (event.button >= 0 && event.button < mouseButtonState.length) {
-                mouseButtonState[event.button] = 0; // Set button state to released
-            }
-
             console.log(`Mouse release: ${hidCommand.mouse_button}`);
 
             if (socket && socket.readyState === WebSocket.OPEN) {
@@ -166,10 +143,11 @@
         }
 
         // Attach mouse event listeners
-        document.addEventListener('mousemove', handleMouseMove);
-        document.addEventListener('mousedown', handleMousePress);
-        document.addEventListener('mouseup', handleMouseRelease);
-        document.addEventListener('wheel', handleMouseScroll);
+        let remoteCaptureEle = document.getElementById('remoteCapture');
+        remoteCaptureEle.addEventListener('mousemove', handleMouseMove);
+        remoteCaptureEle.addEventListener('mousedown', handleMousePress);
+        remoteCaptureEle.addEventListener('mouseup', handleMouseRelease);
+        remoteCaptureEle.addEventListener('wheel', handleMouseScroll);
 
         /* Keyboard */
         function isNumpadEvent(event) {
@@ -251,7 +229,7 @@
             });
 
             socket.addEventListener('message', function(event) {
-                console.log('Message from server ', event.data);
+                //console.log('Message from server ', event.data);
             });
 
             document.addEventListener('keydown', handleKeyDown);
@@ -270,26 +248,21 @@
             document.removeEventListener('keyup', handleKeyUp);
         }
 
-
-        $(document).ready(function(){
-            startWebSocket();
-        });
-
-
         /* Audio Streaming Frontend */
         let audioSocket;
         let audioContext;
         let audioQueue = [];
         let audioPlaying = false;
 
-        function startAudioWebSocket() {
+        //accept low, standard, high quality audio mode
+        function startAudioWebSocket(quality="standard") {
             if (audioSocket) {
                 console.warn("Audio WebSocket already started");
                 return;
             }
             let protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
             let port = window.location.port ? window.location.port : (protocol === 'wss' ? 443 : 80);
-            let audioSocketURL = `${protocol}://${window.location.hostname}:${port}/audio`;
+            let audioSocketURL = `${protocol}://${window.location.hostname}:${port}/audio?quality=${quality}`;
 
             audioSocket = new WebSocket(audioSocketURL);
             audioSocket.binaryType = 'arraybuffer';
@@ -301,7 +274,16 @@
                 }
             };
 
+
             const MAX_AUDIO_QUEUE = 8;
+            let PCM_SAMPLE_RATE;
+            if (quality == "high"){
+                PCM_SAMPLE_RATE = 48000; // Use 48kHz for high quality
+            } else if (quality == "low") {
+                PCM_SAMPLE_RATE = 16000; // Use 24kHz for low quality
+            } else {
+                PCM_SAMPLE_RATE = 24000; // Default to 24kHz for standard quality
+            }
             let scheduledTime = 0;
             audioSocket.onmessage = function(event) {
                 if (!audioContext) return;
@@ -350,7 +332,7 @@
                 while (audioQueue.length > 0) {
                     let floatBuf = audioQueue.shift();
                     let frameCount = floatBuf.length / 2;
-                    let buffer = audioContext.createBuffer(2, frameCount, 48000);
+                    let buffer = audioContext.createBuffer(2, frameCount, PCM_SAMPLE_RATE);
                     for (let ch = 0; ch < 2; ch++) {
                         let channelData = buffer.getChannelData(ch);
                         for (let i = 0; i < frameCount; i++) {
@@ -386,6 +368,12 @@
                 audioContext = null;
             }
         }
+
+        startWebSocket();
+
+        window.addEventListener('beforeunload', function() {
+            stopAudioWebSocket();
+        });
     </script>
 </body>
 </html>

+ 22 - 0
remdeskd/www/main.css

@@ -0,0 +1,22 @@
+body {
+    margin: 0;
+    padding: 0;
+    height: 100vh;
+    width: 100vw;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    box-sizing: border-box;
+    overflow: hidden;
+    background-color: black;
+}
+
+#remoteCapture {
+    max-width: 100vw;
+    max-height: 100vh;
+    width: auto;
+    height: auto;
+    display: block;
+    margin: auto;
+    object-fit: contain;
+}