usbkvm_fw.ino 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. RemdesKVM USB-KVM Firmware
  3. Author: tobychui
  4. This is the USB KVM part of RemdesKVM.
  5. It can be used seperately as a dedicated USB-KVM
  6. module as well as connected to a Linux SBC running
  7. remdeskvmd via a USB 2.0 connection.
  8. Upload Settings
  9. CH552G
  10. 24Mhz (Internal)
  11. USB CODE /w 148B USB RAM
  12. */
  13. #ifndef USER_USB_RAM
  14. #error "This firmware needs to be compiled with a USER USB setting"
  15. #endif
  16. //#define ENABLE_DEBUG_PRINT
  17. #include "usbkvm_fw.h"
  18. #include "src/remdesHid/USBHIDKeyboardMouse.h"
  19. /*
  20. instr_count store the current read index
  21. index of current instruction, all instructions have 3 bytes
  22. byte orders as follows
  23. byte 0 = opr_type
  24. byte 1 = opr_subtype
  25. byte 2 = data
  26. */
  27. uint8_t instr_count = 0;
  28. /*
  29. opr_type defines the type of the incoming data
  30. for the next byte. See usbkvm_fw.h for details.
  31. */
  32. uint8_t opr_type = 0x00;
  33. /*
  34. opr_subtype defines the sub-type of the operation
  35. Based on opr_type, there will be different catergory
  36. of operations. However, 0x00 is always reserved
  37. */
  38. uint8_t opr_subtype = 0x00;
  39. uint8_t opr_payload = 0x00;
  40. /*
  41. cursor_direction_data handles special subtype data
  42. that requires to move the cursor position
  43. */
  44. uint8_t cursor_direction_data[2] = { 0x00, 0x00 };
  45. uint8_t serial_data = 0x00;
  46. /* Function Prototypes */
  47. uint8_t keyboard_emulation(uint8_t, uint8_t);
  48. uint8_t mouse_emulation(uint8_t, uint8_t);
  49. uint8_t mouse_move(uint8_t, uint8_t, uint8_t, uint8_t);
  50. uint8_t mouse_wheel(uint8_t, uint8_t);
  51. uint8_t usb_switch_emulation(uint8_t, uint8_t);
  52. /* KVM Operation Execution Catergory*/
  53. uint8_t kvm_execute_opr() {
  54. switch (opr_type) {
  55. case OPR_TYPE_RESERVED:
  56. //Ping test
  57. return resp_ok;
  58. case OPR_TYPE_KEYBOARD_WRITE:
  59. //keyboard operations
  60. return keyboard_emulation(opr_subtype, opr_payload);
  61. case OPR_TYPE_MOUSE_WRITE:
  62. //mouse operations
  63. return mouse_emulation(opr_subtype, opr_payload);
  64. case OPR_TYPE_MOUSE_SCROLL:
  65. //mouse scroll
  66. //for larger scroll tilt value, use the multipler
  67. return mouse_wheel(opr_subtype, opr_payload);
  68. case OPR_TYPE_SWITCH_SET:
  69. //set USB signal bus switch state
  70. return usb_switch_emulation(opr_subtype, opr_payload);
  71. default:
  72. return resp_unknown_opr;
  73. }
  74. }
  75. void setup() {
  76. // Start CH340 UART COM
  77. Serial0_begin(115200);
  78. // Set both USB switch to LOW
  79. pinMode(USB_SW_SEL, OUTPUT);
  80. pinMode(HID_SW_SEL, OUTPUT);
  81. digitalWrite(HID_SW_SEL, LOW);
  82. digitalWrite(USB_SW_SEL, LOW);
  83. delay(100);
  84. // Start USB HID emulation
  85. USBInit();
  86. }
  87. void loop() {
  88. if (Serial0_available()) {
  89. serial_data = 0x00;
  90. serial_data = Serial0_read();
  91. //Debug print the Serial input message
  92. #ifdef ENABLE_DEBUG_PRINT
  93. Serial0_write(resp_start_of_info_msg);
  94. Serial0_write(serial_data);
  95. Serial0_write(resp_end_of_msg);
  96. #endif
  97. if (serial_data == OPR_TYPE_DATA_RESET) {
  98. //Reset opr data
  99. opr_type = OPR_TYPE_RESERVED;
  100. opr_subtype = SUBTYPE_RESERVED;
  101. opr_payload = 0x00;
  102. instr_count = 0;
  103. Serial0_write(resp_ok);
  104. } else if (instr_count == 0) {
  105. //Set opr type
  106. opr_type = serial_data;
  107. instr_count++;
  108. Serial0_write(resp_ok);
  109. } else if (instr_count == 1) {
  110. //Set opr subtype
  111. opr_subtype = serial_data;
  112. instr_count++;
  113. Serial0_write(resp_ok);
  114. } else if (opr_type == OPR_TYPE_MOUSE_MOVE) {
  115. //Special case where mouse move requires 4 opcodes
  116. if (instr_count == 2) {
  117. opr_payload = serial_data; //y-steps, reusing payload for lower memory consumption
  118. instr_count++;
  119. } else if (instr_count == 3) {
  120. cursor_direction_data[0] = serial_data; //x-direction
  121. instr_count++;
  122. } else if (instr_count == 4) {
  123. cursor_direction_data[1] = serial_data; //y-direction
  124. opr_type = OPR_TYPE_RESERVED;
  125. instr_count = 0;
  126. mouse_move(opr_subtype, opr_payload, cursor_direction_data[0], cursor_direction_data[1]);
  127. cursor_direction_data[0] = 0x00;
  128. cursor_direction_data[1] = 0x00;
  129. opr_subtype = 0x00;
  130. }
  131. Serial0_write(resp_ok);
  132. } else {
  133. opr_payload = serial_data;
  134. //Execute the kvm operation
  135. uint8_t err = kvm_execute_opr();
  136. Serial0_write(err);
  137. //Reset the instruction counter and ready for the next instruction
  138. instr_count = 0;
  139. }
  140. }
  141. delay(1);
  142. }