usbkvm_fw3.ino 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. //Pins definations
  11. #define ATX_PWR_LED 15
  12. #define ATX_HDD_LED 16
  13. #define ATX_RST_BTN 33
  14. #define ATX_PWR_BTN 34
  15. #define USB_MS_SW 32
  16. //Custom header bytes for RemdesKVM
  17. #define HEADER_BYTE_0 0x58
  18. #define HEADER_BYTE_1 0xEE
  19. #define MAX_DATA_LEN 32 //Max resp data length from remdesKVM control signal
  20. //Runtime
  21. uint8_t trigger = 0; //Counter for header matching logic
  22. uint8_t c = 0x00;
  23. uint8_t data[MAX_DATA_LEN];
  24. // execute a remdeskvm only command
  25. void execute_remdeskvm_cmd(uint8_t cmd) {
  26. uint8_t res = 0, len = 0, sum = 0;
  27. memset(data, 0, sizeof(data));
  28. res = cmd | 0x80;
  29. switch (cmd) {
  30. case 0x00:
  31. //ATX Power button ON
  32. digitalWrite(ATX_PWR_BTN, HIGH);
  33. break;
  34. case 0x01:
  35. //ATX Power button OFF
  36. digitalWrite(ATX_PWR_BTN, LOW);
  37. break;
  38. case 0x02:
  39. //Reset button ON
  40. digitalWrite(ATX_RST_BTN, HIGH);
  41. break;
  42. case 0x03:
  43. //Reset button OFF
  44. digitalWrite(ATX_RST_BTN, LOW);
  45. break;
  46. case 0x04:
  47. //Get LED status
  48. data[0] = digitalRead(ATX_PWR_LED);
  49. data[1] = digitalRead(ATX_HDD_LED);
  50. len = 2;
  51. break;
  52. default:
  53. //Unknown command
  54. res = cmd | 0x0C;
  55. }
  56. //Write the result back to control software
  57. USBSerial_print(HEADER_BYTE_0); //Header byte
  58. sum += HEADER_BYTE_0;
  59. USBSerial_print(HEADER_BYTE_1); //Header byte
  60. sum += HEADER_BYTE_1;
  61. USBSerial_print(res); //Status
  62. sum += res;
  63. USBSerial_print(len); //Length
  64. sum += len;
  65. for (int i = 0; i < len; i++) {
  66. USBSerial_print(data[i]); //Data payload
  67. sum += data[i];
  68. }
  69. USBSerial_print(sum); //Checksum
  70. }
  71. // Send a CH9329 cmd via UART0
  72. void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length) {
  73. uint8_t sum = 0;
  74. Serial0_write(0x57);
  75. sum += 0x57;
  76. Serial0_write(0xAB);
  77. sum += 0xAB;
  78. Serial0_write(0x00);
  79. Serial0_write(cmd);
  80. sum += cmd;
  81. Serial0_write(length);
  82. sum += length;
  83. for (int i = 0; i < length; i++) {
  84. Serial0_write(data[i]);
  85. sum += data[i];
  86. }
  87. Serial0_write(sum);
  88. }
  89. // flush the serial RX (blocking)
  90. void flush_cmd_resp() {
  91. delay(100);
  92. while (Serial0_available()) {
  93. uint8_t b = Serial0_read();
  94. USBSerial_print("0x");
  95. if (b < 0x10) USBSerial_print("0");
  96. USBSerial_print(b, HEX);
  97. USBSerial_print(" ");
  98. }
  99. USBSerial_println("");
  100. }
  101. // Set the USB descriptor exposed to the slave device
  102. void setup_keyboard_chip_cfg() {
  103. //Set manufacturer string
  104. uint8_t manufacturer_string[9] = { 0x00, 0x07, 'i', 'm', 'u', 's', 'l', 'a', 'b' };
  105. send_cmd(0x0B, manufacturer_string, 9);
  106. flush_cmd_resp();
  107. //Set product string
  108. uint8_t product_string[11] = { 0x01, 0x09, 'R', 'e', 'm', 'd', 'e', 's', 'K', 'V', 'M' };
  109. send_cmd(0x0B, product_string, 11);
  110. flush_cmd_resp();
  111. }
  112. void setup() {
  113. //Setup ATX Pins
  114. pinMode(ATX_PWR_LED, INPUT);
  115. pinMode(ATX_HDD_LED, INPUT);
  116. pinMode(ATX_RST_BTN, OUTPUT);
  117. pinMode(ATX_PWR_BTN, OUTPUT);
  118. pinMode(USB_MS_SW, OUTPUT); //Currently not used
  119. digitalWrite(ATX_RST_BTN, LOW);
  120. digitalWrite(ATX_PWR_BTN, LOW);
  121. //Serial0_begin(9600); // CH9329 UART default baudrate (uncomment this before running -cfgchip)
  122. Serial0_begin(19200);
  123. delay(100);
  124. setup_keyboard_chip_cfg();
  125. }
  126. void loop() {
  127. // Read characters into buffer
  128. if (USBSerial_available()) {
  129. c = USBSerial_read();
  130. Serial0_write(c);
  131. if (c == HEADER_BYTE_0 && trigger == 0) {
  132. trigger++;
  133. } else if (c == HEADER_BYTE_1 && trigger == 1) {
  134. trigger++;
  135. } else if (trigger == 2) {
  136. //This is the command for remdeskvm
  137. execute_remdeskvm_cmd(c);
  138. trigger = 0;
  139. }
  140. }
  141. if (Serial0_available()) {
  142. c = Serial0_read();
  143. USBSerial_write(c);
  144. }
  145. }