浏览代码

Added cfgchip device name write

TC 2 周之前
父节点
当前提交
e1ba1feb5c

+ 9 - 9
remdeskd/main.go

@@ -62,15 +62,6 @@ func main() {
 			log.Fatal(err)
 			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
 		time.Sleep(1 * time.Second) // Wait for the controller to initialize
 		log.Println("Updating chip baudrate to 115200...")
 		log.Println("Updating chip baudrate to 115200...")
 		//Configure the HID controller
 		//Configure the HID controller
@@ -80,6 +71,15 @@ func main() {
 			return
 			return
 		}
 		}
 		time.Sleep(1 * time.Second)
 		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.")
 		log.Println("Configuration command sent. Unplug the device and plug it back in to apply the changes.")
 	case "usbkvm":
 	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")
 		return errors.New("failed to get reply")
 	}
 	}
 
 
+	fmt.Println()
 	fmt.Print("Reply: ")
 	fmt.Print("Reply: ")
 	for _, b := range resp {
 	for _, b := range resp {
 		fmt.Printf("0x%02X ", b)
 		fmt.Printf("0x%02X ", b)
@@ -50,13 +51,14 @@ func (c *Controller) ConfigureChipTo115200() error {
 func (c *Controller) WriteChipProperties() ([]byte, error) {
 func (c *Controller) WriteChipProperties() ([]byte, error) {
 	manufacturerString := []byte{
 	manufacturerString := []byte{
 		0x57, 0xAB, 0x00, 0x0B,
 		0x57, 0xAB, 0x00, 0x0B,
+		0x09, // Length of payload
 		0x00, // Set manufacturer string
 		0x00, // Set manufacturer string
-		0x07, // Length of the string
+		0x07, // Length of the USB manufacturer string
 		'i', 'm', 'u', 's', 'l', 'a', 'b',
 		'i', 'm', 'u', 's', 'l', 'a', 'b',
 		0x00, // Checksum placeholder
 		0x00, // Checksum placeholder
 	}
 	}
 
 
-	manufacturerString[13] = calcChecksum(manufacturerString[:13])
+	manufacturerString[14] = calcChecksum(manufacturerString[:14])
 	// Send set manufacturer string
 	// Send set manufacturer string
 	err := c.Send(manufacturerString)
 	err := c.Send(manufacturerString)
 	if err != nil {
 	if err != nil {
@@ -69,13 +71,14 @@ func (c *Controller) WriteChipProperties() ([]byte, error) {
 
 
 	productString := []byte{
 	productString := []byte{
 		0x57, 0xAB, 0x00, 0x0B,
 		0x57, 0xAB, 0x00, 0x0B,
+		0x0B, // Length of the payload
 		0x01, // Set product string
 		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',
 		'R', 'e', 'm', 'd', 'e', 's', 'K', 'V', 'M',
 		0x00, // Checksum placeholder
 		0x00, // Checksum placeholder
 	}
 	}
 
 
-	productString[15] = calcChecksum(productString[:15])
+	productString[16] = calcChecksum(productString[:16])
 	// Send set product string
 	// Send set product string
 	err = c.Send(productString)
 	err = c.Send(productString)
 	if err != nil {
 	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
 		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
 	// F1 to F12
 	if keycode >= 112 && keycode <= 123 {
 	if keycode >= 112 && keycode <= 123 {
 		return (keycode - 112) + 0x3A // 'F1' is 0x3A
 		return (keycode - 112) + 0x3A // 'F1' is 0x3A
@@ -260,6 +255,24 @@ func javaScriptKeycodeToHIDOpcode(keycode uint8) uint8 {
 		return 0x65 // Menu key
 		return 0x65 // Menu key
 	case 96:
 	case 96:
 		return 0x62 // 0 (Numpads)
 		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:
 	case 106:
 		return 0x55 // * (Numpads)
 		return 0x55 // * (Numpads)
 	case 107:
 	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.
 // AudioStreamingHandler handles incoming WebSocket connections for audio streaming.
 func (i Instance) AudioStreamingHandler(w http.ResponseWriter, r *http.Request) {
 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)
 	conn, err := upgrader.Upgrade(w, r, nil)
 	if err != nil {
 	if err != nil {
 		log.Println("Failed to upgrade to websocket:", err)
 		log.Println("Failed to upgrade to websocket:", err)
@@ -196,9 +252,25 @@ func (i Instance) AudioStreamingHandler(w http.ResponseWriter, r *http.Request)
 				continue
 				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))
 			//log.Println("Read bytes:", n, "size of buffer:", len(buf))
 			//Send only the bytes read to WebSocket
 			//Send only the bytes read to WebSocket
-			err = conn.WriteMessage(websocket.BinaryMessage, buf[:n])
+			err = conn.WriteMessage(websocket.BinaryMessage, downsampled[:n])
 			if err != nil {
 			if err != nil {
 				log.Println("WebSocket send error:", err)
 				log.Println("WebSocket send error:", err)
 				goto DONE
 				goto DONE

+ 42 - 54
remdeskd/www/index.html

@@ -3,33 +3,21 @@
 <head>
 <head>
     <meta charset="UTF-8">
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <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 -->
     <!-- 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: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>
     <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>
 </head>
 <body>
 <body>
-    <button onclick="startAudioWebSocket()">Start Audio</button>
-    <button onclick="stopAudioWebSocket()">Stop Audio</button>
     <img id="remoteCapture" src="/stream" oncontextmenu="return false;"></img>
     <img id="remoteCapture" src="/stream" oncontextmenu="return false;"></img>
-    
     <script>
     <script>
         let socket;
         let socket;
         let protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
         let protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
@@ -37,22 +25,16 @@
         let socketURL = `${protocol}://${window.location.hostname}:${port}/hid`;
         let socketURL = `${protocol}://${window.location.hostname}:${port}/hid`;
         let mouseMoveAbsolte = true; // Set to true for absolute mouse coordinates, false for relativeZ
         let mouseMoveAbsolte = true; // Set to true for absolute mouse coordinates, false for relativeZ
         let mouseIsOutside = false;
         let mouseIsOutside = false;
-        let mouseButtonState = [0, 0, 0]; // Array to track mouse button states, left, middle, right
+        let audioFrontendStarted = false;
 
 
         /* Mouse events */
         /* Mouse events */
         function handleMouseMove(event) {
         function handleMouseMove(event) {
-            const mouseButtonBits = mouseButtonState.reduce((acc, state, index) => {
-                return acc | (state << index);
-            }, 0);
             const hidCommand = {
             const hidCommand = {
                 event: 2,
                 event: 2,
                 mouse_x: event.clientX,
                 mouse_x: event.clientX,
                 mouse_y: event.clientY,
                 mouse_y: event.clientY,
-                //mouse_move_button_state: mouseButtonBits // Combine mouse button states into a single bitmask
             };
             };
 
 
-
-
             const rect = event.target.getBoundingClientRect();
             const rect = event.target.getBoundingClientRect();
             const relativeX = event.clientX - rect.left;
             const relativeX = event.clientX - rect.left;
             const relativeY = event.clientY - rect.top;
             const relativeY = event.clientY - rect.top;
@@ -68,9 +50,9 @@
             hidCommand.mouse_x = Math.round(percentageX);
             hidCommand.mouse_x = Math.round(percentageX);
             hidCommand.mouse_y = Math.round(percentageY);
             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) {
             if (socket && socket.readyState === WebSocket.OPEN) {
                 socket.send(JSON.stringify(hidCommand));
                 socket.send(JSON.stringify(hidCommand));
@@ -98,12 +80,7 @@
                 mouse_button: buttonMap[event.button] || 0
                 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
             // Log the mouse button state
-
             console.log(`Mouse down: ${hidCommand.mouse_button}`);
             console.log(`Mouse down: ${hidCommand.mouse_button}`);
 
 
             if (socket && socket.readyState === WebSocket.OPEN) {
             if (socket && socket.readyState === WebSocket.OPEN) {
@@ -111,6 +88,11 @@
             } else {
             } else {
                 console.error("WebSocket is not open.");
                 console.error("WebSocket is not open.");
             }
             }
+
+            if (!audioFrontendStarted){
+                startAudioWebSocket();
+                audioFrontendStarted = true;
+            }
         }
         }
 
 
         function handleMouseRelease(event) {
         function handleMouseRelease(event) {
@@ -131,11 +113,6 @@
                 mouse_button: buttonMap[event.button] || 0
                 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}`);
             console.log(`Mouse release: ${hidCommand.mouse_button}`);
 
 
             if (socket && socket.readyState === WebSocket.OPEN) {
             if (socket && socket.readyState === WebSocket.OPEN) {
@@ -166,10 +143,11 @@
         }
         }
 
 
         // Attach mouse event listeners
         // 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 */
         /* Keyboard */
         function isNumpadEvent(event) {
         function isNumpadEvent(event) {
@@ -251,7 +229,7 @@
             });
             });
 
 
             socket.addEventListener('message', function(event) {
             socket.addEventListener('message', function(event) {
-                console.log('Message from server ', event.data);
+                //console.log('Message from server ', event.data);
             });
             });
 
 
             document.addEventListener('keydown', handleKeyDown);
             document.addEventListener('keydown', handleKeyDown);
@@ -270,26 +248,21 @@
             document.removeEventListener('keyup', handleKeyUp);
             document.removeEventListener('keyup', handleKeyUp);
         }
         }
 
 
-
-        $(document).ready(function(){
-            startWebSocket();
-        });
-
-
         /* Audio Streaming Frontend */
         /* Audio Streaming Frontend */
         let audioSocket;
         let audioSocket;
         let audioContext;
         let audioContext;
         let audioQueue = [];
         let audioQueue = [];
         let audioPlaying = false;
         let audioPlaying = false;
 
 
-        function startAudioWebSocket() {
+        //accept low, standard, high quality audio mode
+        function startAudioWebSocket(quality="standard") {
             if (audioSocket) {
             if (audioSocket) {
                 console.warn("Audio WebSocket already started");
                 console.warn("Audio WebSocket already started");
                 return;
                 return;
             }
             }
             let protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
             let protocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
             let port = window.location.port ? window.location.port : (protocol === 'wss' ? 443 : 80);
             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 = new WebSocket(audioSocketURL);
             audioSocket.binaryType = 'arraybuffer';
             audioSocket.binaryType = 'arraybuffer';
@@ -301,7 +274,16 @@
                 }
                 }
             };
             };
 
 
+
             const MAX_AUDIO_QUEUE = 8;
             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;
             let scheduledTime = 0;
             audioSocket.onmessage = function(event) {
             audioSocket.onmessage = function(event) {
                 if (!audioContext) return;
                 if (!audioContext) return;
@@ -350,7 +332,7 @@
                 while (audioQueue.length > 0) {
                 while (audioQueue.length > 0) {
                     let floatBuf = audioQueue.shift();
                     let floatBuf = audioQueue.shift();
                     let frameCount = floatBuf.length / 2;
                     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++) {
                     for (let ch = 0; ch < 2; ch++) {
                         let channelData = buffer.getChannelData(ch);
                         let channelData = buffer.getChannelData(ch);
                         for (let i = 0; i < frameCount; i++) {
                         for (let i = 0; i < frameCount; i++) {
@@ -386,6 +368,12 @@
                 audioContext = null;
                 audioContext = null;
             }
             }
         }
         }
+
+        startWebSocket();
+
+        window.addEventListener('beforeunload', function() {
+            stopAudioWebSocket();
+        });
     </script>
     </script>
 </body>
 </body>
 </html>
 </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;
+}