ソースを参照

Added more firmware for v4 pcb

Toby Chui 1 日 前
コミット
f3131d8c08
2 ファイル変更338 行追加58 行削除
  1. 227 0
      usbkvm/usbkvm_fw2/keyboard_emu.ino
  2. 111 58
      usbkvm/usbkvm_fw2/usbkvm_fw2.ino

+ 227 - 0
usbkvm/usbkvm_fw2/keyboard_emu.ino

@@ -0,0 +1,227 @@
+/*
+  ketboard_emu.ino
+
+  This file handle keyboard emulation and key writes
+*/
+#define MAX_KEYBOARD_HID_KEYCODE_NO 6
+#define ENABLE_KEYBOARD_DEBUG_PRINTOUT
+
+/* Modifier keycode for CH9329 */
+#define MOD_LCTRL 0x01
+#define MOD_LSHIFT 0x02
+#define MOD_LALT 0x04
+#define MOD_LGUI 0x08
+#define MOD_RCTRL 0x10
+#define MOD_RSHIFT 0x20
+#define MOD_RALT 0x40
+#define MOD_RGUI 0x80
+
+/* Runtime variables */
+uint8_t keyboard_state[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+//byte 0: Computer connected
+//byte 1:
+//      bit 0: NUM LOCK
+//      bit 1: CAPS LOCK
+//      bit 2: SCROLL LOCK
+uint8_t keyboard_leds[2] = { 0x00, 0x00 };
+extern uint8_t kbCmdBuf[MAX_CMD_LEN];
+extern uint8_t kbCmdIndex;
+extern uint8_t kbCmdCounter;
+
+/* Function Prototypes */
+void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length);
+
+/* Request CH9329 response with current keyboard status */
+void keyboard_get_info() {
+  send_cmd(0x01, NULL, 0x00);
+}
+
+/* Callback handler for setting keyboard status */
+void handle_keyboard_get_info_reply() {
+  keyboard_leds[0] = kbCmdBuf[6];
+  keyboard_leds[1] = kbCmdBuf[7];
+
+#ifdef ENABLE_KEYBOARD_DEBUG_PRINTOUT
+  for (int i = 0; i < kbCmdIndex; i++) {
+    uint8_t b = kbCmdBuf[i];
+    USBSerial_print("0x");
+    if (b < 0x10) USBSerial_print("0");
+    USBSerial_print(b, HEX);
+    USBSerial_print(" ");
+  }
+
+  USBSerial_println(keyboard_leds[0] ? "Connected" : "Not Connected");
+  USBSerial_println((keyboard_leds[1] & 0x01) ? "NUMLOCK ON" : "NUMLOCK OFF");
+  USBSerial_println((keyboard_leds[1] & 0x02) ? "CAPSLOCK ON" : "CAPSLOCK OFF");
+  USBSerial_println((keyboard_leds[1] & 0x04) ? "SCROLLLOCK ON" : "SCROLLLOCK OFF");
+#endif
+}
+
+/* helper to write an array of uint8_t to CH9329 */
+void Serial0_writeBuf(const uint8_t* data, uint8_t len) {
+  for (uint8_t i = 0; i < len; i++) {
+    Serial0_write(data[i]);
+  }
+}
+
+/* Send key combinations, keycode must be an array with length 6 */
+int keyboard_send_key_combinations(uint8_t modifiers, uint8_t* keycode, uint8_t length) {
+  if (length != MAX_KEYBOARD_HID_KEYCODE_NO) {
+    //This function must take in an array of 6 keycodes
+    return -1;
+  }
+  uint8_t packet[14] = {
+    0x57, 0xAB, 0x00, 0x02, 0x08,
+    modifiers, 0x00,
+    keycode[0], keycode[1], keycode[2], keycode[3], keycode[4], keycode[5],
+    0x00
+  };
+  packet[13] = calcChecksum(packet, 13);
+  Serial0_writeBuf(packet, 14);
+  return 0;
+}
+
+/* Release all keypress on the current emulated keyboard */
+void keyboard_release_all_keys() {
+  uint8_t packet[] = {
+    0x57, 0xAB, 0x00, 0x02, 0x08,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00  // checksum placeholder
+  };
+  packet[13] = calcChecksum(packet, 13);
+  Serial0_writeBuf(packet, 14);
+}
+
+/* Convert JavaScrpt Keycode into HID keycode */
+uint8_t javascript_keycode_to_hid_opcode(uint8_t keycode) {
+  // Letters A-Z
+  if (keycode >= 65 && keycode <= 90) {
+    return (keycode - 65) + 0x04;  // 'A' is 0x04
+  }
+
+  // Numbers 1-9 (top row, not numpad)
+  if (keycode >= 49 && keycode <= 57) {
+    return (keycode - 48) + 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
+  }
+
+  switch (keycode) {
+    case 8:
+      return 0x2A;  // Backspace
+    case 9:
+      return 0x2B;  // Tab
+    case 13:
+      return 0x28;  // Enter
+    case 16:
+      return 0xE1;  //Left shift
+    case 17:
+      return 0xE0;  //Left Ctrl
+    case 18:
+      return 0xE6;  //Left Alt
+    case 20:
+      return 0x39;  // Caps Lock
+    case 27:
+      return 0x29;  // Escape
+    case 32:
+      return 0x2C;  // Spacebar
+    case 33:
+      return 0x4B;  // Page Up
+    case 34:
+      return 0x4E;  // Page Down
+    case 35:
+      return 0x4D;  // End
+    case 36:
+      return 0x4A;  // Home
+    case 37:
+      return 0x50;  // Left Arrow
+    case 38:
+      return 0x52;  // Up Arrow
+    case 39:
+      return 0x4F;  // Right Arrow
+    case 40:
+      return 0x51;  // Down Arrow
+    case 44:
+      return 0x46;  //Print Screen or F13 (Firefox)
+    case 45:
+      return 0x49;  // Insert
+    case 46:
+      return 0x4C;  // Delete
+    case 48:
+      return 0x27;  // 0 (not Numpads)
+
+    // 49 - 57 Number row 1 - 9 handled above
+    // 58 not supported
+    case 59:
+      return 0x33;  // ';'
+
+    // 60 not supported
+    case 61:
+      return 0x2E;  // '='
+
+    //62 - 90 not supported
+    case 91:
+      return 0xE3;  // Left GUI (Windows)
+    case 92:
+      return 0xE7;  // Right GUI
+    case 93:
+      return 0x65;  // Menu key
+    // 64 - 65 not supported
+    case 96:
+      return 0x62;  //0 (Numpads)
+    //Numpad 1 to 9 handled above
+    case 106:
+      return 0x55;  //* (Numpads)
+    case 107:
+      return 0x57;  //+ (Numpads)
+    case 109:
+      return 0x56;  //- (Numpads)
+    case 110:
+      return 0x63;  // dot (Numpads)
+    case 111:
+      return 0x54;  // divide (Numpads)
+
+    // 112 - 123 F1 to F12 handled above
+    // 124 - 143 F13 to F32 not supported
+    case 144:
+      return 0x53;  // Num Lock
+    case 145:
+      return 0x47;  // Scroll Lock
+
+    // 146 - 185 not supported or not exists
+    case 186:
+      return 0x33;  // ;
+    case 187:
+      return 0x2E;  // =
+    case 188:
+      return 0x36;  // ,
+    case 189:
+      return 0x2D;  // -
+    case 190:
+      return 0x37;  // .
+    case 191:
+      return 0x38;  // /
+    case 192:
+      return 0x35;  // `
+    case 219:
+      return 0x2F;  // [
+    case 220:
+      return 0x31;  // backslash
+    case 221:
+      return 0x30;  // ]
+    case 222:
+      return 0x34;  // '
+
+    default:
+      return 0x00;  // Unknown / unsupported
+  }
+}

+ 111 - 58
usbkvm/usbkvm_fw2/usbkvm_fw2.ino

@@ -8,81 +8,134 @@
   CH552G  
   24Mhz (Internal)
 */
-
 #include <Serial.h>
 
-// Simple mapping: A-Z → HID code 0x04 - 0x1D
-uint8_t asciiToHID(char c) {
-    if (c >= 'A' && c <= 'Z') return (c - 'A') + 0x04;
-    if (c >= 'a' && c <= 'z') return (c - 'a') + 0x04;
-    return 0x00;
-}
+#define MAX_CMD_LEN 32
+
+uint8_t cmdBuf[MAX_CMD_LEN];
+uint8_t cmdIndex = 0;
+//Buffer and state machine for CH9329 UART COMM
+uint8_t kbCmdBuf[MAX_CMD_LEN];
+uint8_t kbCmdIndex = 0;
+uint8_t kbCmdCounter = MAX_CMD_LEN;  //How many index left to terminate
+
+/* Function Prototypes */
+void keyboard_get_info();
+void handle_keyboard_get_info_reply();
 
 // Checksum = sum of all bytes except last
 uint8_t calcChecksum(uint8_t* data, uint8_t len) {
-    uint8_t sum = 0;
-    for (uint8_t i = 0; i < len; i++) sum += data[i];
-    return sum;
+  uint8_t sum = 0;
+  for (uint8_t i = 0; i < len; i++) sum += data[i];
+  return sum;
 }
 
-//Wrapper for writing an array to serial
-void Serial0_writeBuf(const uint8_t* data, uint8_t len) {
-    for (uint8_t i = 0; i < len; i++) {
-        Serial0_write(data[i]);
-    }
+// flush the serial RX
+void flush_cmd_resp() {
+  delay(100);
+  while (Serial0_available()) {
+    uint8_t b = Serial0_read();
+    USBSerial_print("0x");
+    if (b < 0x10) USBSerial_print("0");
+    USBSerial_print(b, HEX);
+    USBSerial_print(" ");
+  }
+  USBSerial_println("");
 }
 
-void sendKeyPress(char key) {
-    uint8_t packet[] = {
-        0x57, 0xAB, 0x00, 0x02, 0x08, // Header, addr, CMD, len
-        0x00, 0x00, asciiToHID(key), 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00 // checksum placeholder
-    };
-    packet[13] = calcChecksum(packet, 13);
-    Serial0_writeBuf(packet, 14);
+void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length) {
+  uint8_t sum = 0;
+  Serial0_write(0x57);
+  sum += 0x57;
+  Serial0_write(0xAB);
+  sum += 0xAB;
+  Serial0_write(0x00);
+
+  Serial0_write(cmd);
+  sum += cmd;
+  Serial0_write(length);
+  sum += length;
+  for (int i = 0; i < length; i++) {
+    Serial0_write(data[i]);
+    sum += data[i];
+  }
+  Serial0_write(sum);
 }
 
-void sendKeyRelease() {
-    uint8_t packet[] = {
-        0x57, 0xAB, 0x00, 0x02, 0x08,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00 // checksum placeholder
-    };
-    packet[13] = calcChecksum(packet, 13);
-    Serial0_writeBuf(packet, 14);
+void setup_keyboard_chip_cfg() {
+  //Set manufacturer string
+  uint8_t manufacturer_string[9] = { 0x00, 0x07, 'i', 'm', 'u', 's', 'l', 'a', 'b' };
+  send_cmd(0x0B, manufacturer_string, 9);
+  flush_cmd_resp();
+  //Set product string
+  uint8_t product_string[11] = { 0x01, 0x09, 'R', 'e', 'm', 'd', 'e', 's', 'K', 'V', 'M' };
+  send_cmd(0x0B, product_string, 11);
+  flush_cmd_resp();
 }
 
-void setup() {
-    USBSerial_println("Ready. Type a letter to send to CH9329.");
+//This function will trigger the target handler to handle the buffer data in kbCmdBuf
+void handle_cmd_processing(uint8_t cmd) {
+  switch (cmd) {
+    case 0x81:
+      handle_keyboard_get_info_reply();
+      break;
+    default:
+      //Unknown reply
+      USBSerial_print("Unknown cmd recv: 0x");
+      USBSerial_println(cmd, HEX);
+  }
+}
 
-    Serial0_begin(9600); // CH9329 UART default baud
+void setup() {
+  USBSerial_println("Ready");
+  Serial0_begin(9600);  // CH9329 UART default baudd
+  delay(100);
+  setup_keyboard_chip_cfg();
 }
 
 void loop() {
-    if (USBSerial_available()) {
-        char c = USBSerial_read();
-
-        if (asciiToHID(c)) {
-            USBSerial_print("Sending key: ");
-            USBSerial_println((char)c);
-
-            sendKeyPress(c);
-            delay(50);
-            sendKeyRelease();
-        } else {
-            USBSerial_print("Unsupported char: ");
-            USBSerial_println((int)c);  // show ASCII code for debugging
-        }
+  // Read characters into buffer
+  while (USBSerial_available()) {
+    uint8_t c = USBSerial_read();
+    USBSerial_println(c);
+    if (c == 'k') {
+      keyboard_get_info();
     }
-
-    // Echo UART response from CH9329 to USB
-    while (Serial1_available()) {
-        uint8_t b = Serial1_read();
-
-        USBSerial_print("CH9329 >> 0x");
-        if (b < 0x10) USBSerial_print("0");
-        USBSerial_println(b, HEX);
+  }
+
+  // Debug: Echo CH9329 response
+  while (Serial0_available()) {
+    uint8_t b = Serial0_read();
+    if (b == 0x57) {
+      //Start of a new cmd. Clear the buffer
+      memset(kbCmdBuf, 0, sizeof(kbCmdBuf));
+      kbCmdIndex = 0;
+      kbCmdCounter = MAX_CMD_LEN;
+    } else if (kbCmdIndex == 4) {
+      //Data length of this cmd
+      kbCmdCounter = b + 0x02;  //Sum byte + this Byte
     }
 
-}
-
+    //Append to buffer
+    kbCmdBuf[kbCmdIndex] = b;
+    kbCmdIndex++;
+    kbCmdCounter--;
+    if (kbCmdCounter == 0) {
+      //End of command, verify checksum
+      uint8_t expected_sum = kbCmdBuf[kbCmdIndex - 1];
+      for (int i = 0; i < kbCmdIndex - 1; i++) {
+        expected_sum -= kbCmdBuf[i];
+      }
+      if (expected_sum == 0) {
+        //Correct, process the command
+        handle_cmd_processing(kbCmdBuf[3]);
+      } else {
+        USBSerial_println("Invalid checksum or cmd too long, skipping");
+      }
+      //Clear the buffer
+      memset(kbCmdBuf, 0, sizeof(kbCmdBuf));
+      kbCmdIndex = 0;
+      kbCmdCounter = MAX_CMD_LEN;
+    }
+  }
+}