usbkvm_fw2.ino 5.4 KB

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