usbkvm_fw2.ino 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. RemdesKVM USB-KVM
  3. Firmware for PCB design v4 or above
  4. Author: tobychui
  5. Upload Settings
  6. CH552G
  7. 24Mhz (Internal)
  8. */
  9. #include <Serial.h>
  10. #define MAX_CMD_LEN 32
  11. //Recv buffer from control software
  12. uint8_t cmdBuf[MAX_CMD_LEN];
  13. uint8_t cmdIndex = 0;
  14. uint8_t cmdMaxLen = 0; //Expected length of the LTV command
  15. //Recv buffer from CH9329
  16. uint8_t kbCmdBuf[MAX_CMD_LEN];
  17. uint8_t kbCmdIndex = 0;
  18. uint8_t kbCmdCounter = MAX_CMD_LEN; //How many index left to terminate
  19. /* Function Prototypes */
  20. //ch9329_utils.ino
  21. void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length);
  22. void flush_cmd_resp();
  23. //keyboard_emu.ino
  24. void keyboard_get_info();
  25. void keyboard_reset();
  26. void handle_keyboard_get_info_reply();
  27. int keyboard_press_key(uint8_t keycode);
  28. int keyboard_release_key(uint8_t keycode);
  29. int keyboard_press_modkey(uint8_t opcode);
  30. int keyboard_release_modkey(uint8_t opcode);
  31. // Set the USB descriptor exposed to the slave device
  32. void setup_keyboard_chip_cfg() {
  33. //Set manufacturer string
  34. uint8_t manufacturer_string[9] = { 0x00, 0x07, 'i', 'm', 'u', 's', 'l', 'a', 'b' };
  35. send_cmd(0x0B, manufacturer_string, 9);
  36. flush_cmd_resp();
  37. //Set product string
  38. uint8_t product_string[11] = { 0x01, 0x09, 'R', 'e', 'm', 'd', 'e', 's', 'K', 'V', 'M' };
  39. send_cmd(0x0B, product_string, 11);
  40. flush_cmd_resp();
  41. }
  42. //This function will trigger the target handler to handle the buffer data recv from CH9329
  43. void handle_cmd_processing(uint8_t cmd) {
  44. switch (cmd) {
  45. case 0x81:
  46. handle_keyboard_get_info_reply();
  47. break;
  48. default:
  49. //Unknown reply
  50. USBSerial_print("Unknown cmd recv: 0x");
  51. USBSerial_println(cmd, HEX);
  52. }
  53. }
  54. //This function will handle the incoming cmd from RemdesKVM control software
  55. void handle_ctrl_cmd() {
  56. uint8_t cmd = cmdBuf[1]; //Type of operation
  57. uint8_t value = cmdBuf[2]; //values for 2 bytes cmd
  58. switch (cmd) {
  59. case 0x01:
  60. //keyboard press
  61. keyboard_press_key(value);
  62. break;
  63. case 0x02:
  64. //keyboard release
  65. keyboard_release_key(value);
  66. break;
  67. case 0x03:
  68. //keyboard modifier key press
  69. keyboard_press_modkey(value);
  70. break;
  71. case 0x04:
  72. //keyboard modifier key release
  73. keyboard_release_modkey(value);
  74. break;
  75. default:
  76. //unknown operation, do nothing
  77. break;
  78. }
  79. }
  80. void setup() {
  81. USBSerial_println("Ready");
  82. Serial0_begin(9600); // CH9329 UART default baudd
  83. delay(100);
  84. setup_keyboard_chip_cfg();
  85. }
  86. void loop() {
  87. // Read characters into buffer
  88. while (USBSerial_available()) {
  89. uint8_t c = USBSerial_read();
  90. if (c == 0xFF) {
  91. //Reset
  92. keyboard_reset();
  93. memset(cmdBuf, 0, sizeof(cmdBuf));
  94. cmdIndex = 0;
  95. cmdMaxLen = 0;
  96. continue;
  97. }
  98. if (cmdIndex == 0) {
  99. //This is the length value
  100. cmdMaxLen = c + 1;
  101. }
  102. cmdBuf[cmdIndex] = c;
  103. cmdIndex++;
  104. cmdMaxLen--;
  105. if (cmdMaxLen == 0) {
  106. //End of ctrl cmd, handle it
  107. handle_ctrl_cmd();
  108. //Clear ctrl cmd buf
  109. memset(cmdBuf, 0, sizeof(cmdBuf));
  110. cmdIndex = 0;
  111. cmdMaxLen = 0;
  112. }
  113. }
  114. while (Serial0_available()) {
  115. uint8_t b = Serial0_read();
  116. if (b == 0x57) {
  117. //Start of a new cmd. Clear the buffer
  118. memset(kbCmdBuf, 0, sizeof(kbCmdBuf));
  119. kbCmdIndex = 0;
  120. kbCmdCounter = MAX_CMD_LEN;
  121. } else if (kbCmdIndex == 4) {
  122. //Data length of this cmd
  123. kbCmdCounter = b + 0x02; //Sum byte + this Byte
  124. }
  125. //Append to buffer
  126. kbCmdBuf[kbCmdIndex] = b;
  127. kbCmdIndex++;
  128. kbCmdCounter--;
  129. if (kbCmdCounter == 0) {
  130. //End of command, verify checksum
  131. uint8_t expected_sum = kbCmdBuf[kbCmdIndex - 1];
  132. for (int i = 0; i < kbCmdIndex - 1; i++) {
  133. expected_sum -= kbCmdBuf[i];
  134. }
  135. if (expected_sum == 0) {
  136. //Correct, process the command
  137. handle_cmd_processing(kbCmdBuf[3]);
  138. } else {
  139. USBSerial_println("Invalid checksum or cmd too long, skipping");
  140. }
  141. //Clear the buffer
  142. memset(kbCmdBuf, 0, sizeof(kbCmdBuf));
  143. kbCmdIndex = 0;
  144. kbCmdCounter = MAX_CMD_LEN;
  145. }
  146. }
  147. }