/* RemdesKVM USB-KVM Firmware for PCB design v4 or above Author: tobychui Upload Settings CH552G 24Mhz (Internal) */ #include #define MAX_CMD_LEN 32 //Recv buffer from control software uint8_t cmdBuf[MAX_CMD_LEN]; uint8_t cmdIndex = 0; uint8_t cmdMaxLen = 0; //Expected length of the LTV command //Recv buffer from CH9329 uint8_t kbCmdBuf[MAX_CMD_LEN]; uint8_t kbCmdIndex = 0; uint8_t kbCmdCounter = MAX_CMD_LEN; //How many index left to terminate /* Function Prototypes */ //ch9329_utils.ino void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length); void flush_cmd_resp(); //keyboard_emu.ino void keyboard_get_info(); void keyboard_reset(); void handle_keyboard_get_info_reply(); int keyboard_press_key(uint8_t keycode); int keyboard_release_key(uint8_t keycode); int keyboard_press_modkey(uint8_t opcode); int keyboard_release_modkey(uint8_t opcode); // Set the USB descriptor exposed to the slave device 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(); } //This function will trigger the target handler to handle the buffer data recv from CH9329 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); } } //This function will handle the incoming cmd from RemdesKVM control software void handle_ctrl_cmd() { uint8_t cmd = cmdBuf[1]; //Type of operation uint8_t value = cmdBuf[2]; //values for 2 bytes cmd switch (cmd) { case 0x01: //keyboard press keyboard_press_key(value); break; case 0x02: //keyboard release keyboard_release_key(value); break; case 0x03: //keyboard modifier key press keyboard_press_modkey(value); break; case 0x04: //keyboard modifier key release keyboard_release_modkey(value); break; default: //unknown operation, do nothing break; } } void setup() { USBSerial_println("Ready"); Serial0_begin(9600); // CH9329 UART default baudd delay(100); setup_keyboard_chip_cfg(); } void loop() { // Read characters into buffer while (USBSerial_available()) { uint8_t c = USBSerial_read(); if (c == 0xFF) { //Reset keyboard_reset(); memset(cmdBuf, 0, sizeof(cmdBuf)); cmdIndex = 0; cmdMaxLen = 0; continue; } if (cmdIndex == 0) { //This is the length value cmdMaxLen = c + 1; } cmdBuf[cmdIndex] = c; cmdIndex++; cmdMaxLen--; if (cmdMaxLen == 0) { //End of ctrl cmd, handle it handle_ctrl_cmd(); //Clear ctrl cmd buf memset(cmdBuf, 0, sizeof(cmdBuf)); cmdIndex = 0; cmdMaxLen = 0; } } 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; } } }