usbkvm_fw2.ino 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. //mouse_emu.ino
  32. int mouse_button_press(uint8_t opcode);
  33. int mouse_button_release(uint8_t opcode);
  34. int mouse_scroll_up(uint8_t tilt);
  35. int mouse_scroll_down(uint8_t tilt);
  36. // Set the USB descriptor exposed to the slave device
  37. void setup_keyboard_chip_cfg() {
  38. //Set manufacturer string
  39. uint8_t manufacturer_string[9] = { 0x00, 0x07, 'i', 'm', 'u', 's', 'l', 'a', 'b' };
  40. send_cmd(0x0B, manufacturer_string, 9);
  41. flush_cmd_resp();
  42. //Set product string
  43. uint8_t product_string[11] = { 0x01, 0x09, 'R', 'e', 'm', 'd', 'e', 's', 'K', 'V', 'M' };
  44. send_cmd(0x0B, product_string, 11);
  45. flush_cmd_resp();
  46. }
  47. //This function will trigger the target handler to handle the buffer data recv from CH9329
  48. void handle_cmd_processing(uint8_t cmd) {
  49. switch (cmd) {
  50. case 0x81:
  51. handle_keyboard_get_info_reply();
  52. break;
  53. default:
  54. //Unknown reply
  55. USBSerial_print("Unknown cmd recv: 0x");
  56. USBSerial_println(cmd, HEX);
  57. }
  58. }
  59. //This function will handle the incoming cmd from RemdesKVM control software
  60. //return 0x00 if success and 0x01 if error
  61. void handle_ctrl_cmd() {
  62. uint8_t cmd = cmdBuf[1]; //Type of operation
  63. uint8_t value = cmdBuf[2]; //values for 2 bytes cmd
  64. int ret = 0;
  65. switch (cmd) {
  66. case 0x01:
  67. //keyboard press
  68. ret = keyboard_press_key(value);
  69. break;
  70. case 0x02:
  71. //keyboard release
  72. ret = keyboard_release_key(value);
  73. break;
  74. case 0x03:
  75. //keyboard modifier key press
  76. ret = keyboard_press_modkey(value);
  77. break;
  78. case 0x04:
  79. //keyboard modifier key release
  80. ret = keyboard_release_modkey(value);
  81. break;
  82. case 0x05:
  83. //mouse button press
  84. ret = mouse_button_press(value);
  85. break;
  86. case 0x06:
  87. //mouse button release
  88. ret = mouse_button_release(value);
  89. break;
  90. case 0x07:
  91. //Mouse scroll up
  92. ret = mouse_scroll_up(value);
  93. break;
  94. case 0x08:
  95. //Mouse scroll down
  96. ret = mouse_scroll_down(value);
  97. break;
  98. default:
  99. //unknown operation, do nothing
  100. ret = -1;
  101. break;
  102. }
  103. if (ret < 0){
  104. //Error
  105. USBSerial_print(0x01);
  106. }else{
  107. USBSerial_print(0x00);
  108. }
  109. }
  110. void setup() {
  111. USBSerial_println("Ready");
  112. Serial0_begin(9600); // CH9329 UART default baudd
  113. delay(100);
  114. setup_keyboard_chip_cfg();
  115. }
  116. void loop() {
  117. // Read characters into buffer
  118. while (USBSerial_available()) {
  119. uint8_t c = USBSerial_read();
  120. if (c == 0xFF) {
  121. //Reset
  122. keyboard_reset();
  123. memset(cmdBuf, 0, sizeof(cmdBuf));
  124. cmdIndex = 0;
  125. cmdMaxLen = 0;
  126. continue;
  127. }
  128. if (cmdIndex == 0) {
  129. //This is the length value
  130. cmdMaxLen = c + 1;
  131. }
  132. cmdBuf[cmdIndex] = c;
  133. cmdIndex++;
  134. cmdMaxLen--;
  135. if (cmdMaxLen == 0) {
  136. //End of ctrl cmd, handle it
  137. handle_ctrl_cmd();
  138. //Clear ctrl cmd buf
  139. memset(cmdBuf, 0, sizeof(cmdBuf));
  140. cmdIndex = 0;
  141. cmdMaxLen = 0;
  142. }
  143. }
  144. while (Serial0_available()) {
  145. uint8_t b = Serial0_read();
  146. if (b == 0x57) {
  147. //Start of a new cmd. Clear the buffer
  148. memset(kbCmdBuf, 0, sizeof(kbCmdBuf));
  149. kbCmdIndex = 0;
  150. kbCmdCounter = MAX_CMD_LEN;
  151. } else if (kbCmdIndex == 4) {
  152. //Data length of this cmd
  153. kbCmdCounter = b + 0x02; //Sum byte + this Byte
  154. }
  155. //Append to buffer
  156. kbCmdBuf[kbCmdIndex] = b;
  157. kbCmdIndex++;
  158. kbCmdCounter--;
  159. if (kbCmdCounter == 0) {
  160. //End of command, verify checksum
  161. uint8_t expected_sum = kbCmdBuf[kbCmdIndex - 1];
  162. for (int i = 0; i < kbCmdIndex - 1; i++) {
  163. expected_sum -= kbCmdBuf[i];
  164. }
  165. if (expected_sum == 0) {
  166. //Correct, process the command
  167. handle_cmd_processing(kbCmdBuf[3]);
  168. } else {
  169. USBSerial_println("Invalid checksum or cmd too long, skipping");
  170. }
  171. //Clear the buffer
  172. memset(kbCmdBuf, 0, sizeof(kbCmdBuf));
  173. kbCmdIndex = 0;
  174. kbCmdCounter = MAX_CMD_LEN;
  175. }
  176. }
  177. }