keyboard_emu.ino 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. keyboard_emu.ino
  3. Author: tobychui
  4. This code file handle keyboard emulation related functionality
  5. When opr_type is set to 0x01, the sub-handler will process the
  6. request here.
  7. -- Keyboard Opcode --
  8. 0x00 = Reserved
  9. 0x01 = keyboard write
  10. 0x02 = keyboard press
  11. 0x03 = keyboard release
  12. (ASCII bytes in range of 32 to 127)
  13. 0x04 = Modifier key combination set (bit flags in payload)
  14. Bit 0 (0x01) = KEY_LEFT_CTRL
  15. Bit 1 (0x02) = KEY_LEFT_SHIFT
  16. Bit 2 (0x04) = KEY_LEFT_ALT
  17. Bit 3 (0x08) = KEY_LEFT_GUI
  18. Bit 4 (0x10) = KEY_RIGHT_CTRL
  19. Bit 5 (0x20) = KEY_RIGHT_SHIFT
  20. Bit 6 (0x40) = KEY_RIGHT_ALT
  21. Bit 7 (0x80) = KEY_RIGHT_GUI
  22. 0x05 = Modifier key combination reset
  23. 0x07 = Function key combinartion write
  24. 0xC2 = KEY_F1
  25. 0xC3 = KEY_F2
  26. 0xC4 = KEY_F3
  27. ...
  28. 0xCC = KEY_F11
  29. 0xCD = KEY_F12
  30. 0xF0 = KEY_F13
  31. ...
  32. 0xFB = KEY_F24
  33. 0x08 = Other keys press
  34. 0x09 = Other keys release
  35. 0xDA = KEY_UP_ARROW
  36. 0xD9 = KEY_DOWN_ARROW
  37. 0xD8 = KEY_LEFT_ARROW
  38. 0xD7 = KEY_RIGHT_ARROW
  39. 0xB2 = KEY_BACKSPACE
  40. 0xB3 = KEY_TAB
  41. 0xB0 = KEY_RETURN
  42. 0xB1 = KEY_ESC
  43. 0xD1 = KEY_INSERT
  44. 0xD4 = KEY_DELETE
  45. 0xD3 = KEY_PAGE_UP
  46. 0xD6 = KEY_PAGE_DOWN
  47. 0xD2 = KEY_HOME
  48. 0xD5 = KEY_END
  49. 0xC1 = KEY_CAPS_LOCK
  50. -- Special Opcode --
  51. 0xFE = Ctrl + Alt + Delete
  52. 0xFF = Reset all keys state
  53. */
  54. #include "usbkvm_fw.h"
  55. //Check if the value is a supported ascii code
  56. bool is_ascii(uint8_t value) {
  57. return value >= 32 && value <= 127;
  58. }
  59. //Check if the value is a valid function key value
  60. bool is_funckey(uint8_t value) {
  61. return ((value >= 0xC2 && value <= 0xCD) || (value >= 0xF0 && value <= 0xFB));
  62. }
  63. //Check if the key is valid key that do not belongs in ASCII or function key
  64. bool is_validkeys(uint8_t key) {
  65. if (key >= 0xD7 && key <= 0xDA) {
  66. //Arrow keys
  67. return true;
  68. }
  69. if (key >= 0xB0 && key <= 0xB3) {
  70. //ESC, tabs and other left-most keys
  71. return true;
  72. }
  73. if (key >= 0xD1 && key <= 0xD6) {
  74. //Keys above arrow keys like pageup and down
  75. return true;
  76. }
  77. //CAP_LOCK
  78. return key == 0xC1;
  79. }
  80. //Check if the nth bit is set in the value
  81. bool isBitSet(uint8_t value, uint8_t n) {
  82. if (n > 7) return false; // Ensure n is within 0-7
  83. return (value & (1 << n)) != 0;
  84. }
  85. //Handle modifying key set or unset
  86. void keyboard_modifying_key_set(uint8_t key) {
  87. if (key & 0x01) { // Bit 0 = KEY_LEFT_CTRL
  88. Keyboard_press(KEY_LEFT_CTRL);
  89. } else {
  90. Keyboard_release(KEY_LEFT_CTRL);
  91. }
  92. if (key & 0x02) { // Bit 1 = KEY_LEFT_SHIFT
  93. Keyboard_press(KEY_LEFT_SHIFT);
  94. } else {
  95. Keyboard_release(KEY_LEFT_SHIFT);
  96. }
  97. if (key & 0x04) { // Bit 2 = KEY_LEFT_ALT
  98. Keyboard_press(KEY_LEFT_ALT);
  99. } else {
  100. Keyboard_release(KEY_LEFT_ALT);
  101. }
  102. if (key & 0x08) { // Bit 3 = KEY_LEFT_GUI
  103. Keyboard_press(KEY_LEFT_GUI);
  104. } else {
  105. Keyboard_release(KEY_LEFT_GUI);
  106. }
  107. if (key & 0x10) { // Bit 4 = KEY_RIGHT_CTRL
  108. Keyboard_press(KEY_RIGHT_CTRL);
  109. } else {
  110. Keyboard_release(KEY_RIGHT_CTRL);
  111. }
  112. if (key & 0x20) { // Bit 5 = KEY_RIGHT_SHIFT
  113. Keyboard_press(KEY_RIGHT_SHIFT);
  114. } else {
  115. Keyboard_release(KEY_RIGHT_SHIFT);
  116. }
  117. if (key & 0x40) { // Bit 6 = KEY_RIGHT_ALT
  118. Keyboard_press(KEY_RIGHT_ALT);
  119. } else {
  120. Keyboard_release(KEY_RIGHT_ALT);
  121. }
  122. if (key & 0x80) { // Bit 7 = KEY_RIGHT_GUI
  123. Keyboard_press(KEY_RIGHT_GUI);
  124. } else {
  125. Keyboard_release(KEY_RIGHT_GUI);
  126. }
  127. }
  128. //Entry point for keyboard emulation
  129. uint8_t keyboard_emulation(uint8_t subtype, uint8_t value) {
  130. //Check if the input is a supported ascii value
  131. switch (subtype) {
  132. case SUBTYPE_KEYBOARD_ASCII_WRITE:
  133. if (!is_ascii(value))
  134. return resp_invalid_key_value;
  135. Keyboard_write(value);
  136. return resp_ok;
  137. case SUBTYPE_KEYBOARD_ASCII_PRESS:
  138. if (!is_ascii(value))
  139. return resp_invalid_key_value;
  140. Keyboard_press(value);
  141. return resp_ok;
  142. case SUBTYPE_KEYBOARD_ASCII_RELEASE:
  143. if (!is_ascii(value))
  144. return resp_invalid_key_value;
  145. Keyboard_release(value);
  146. return resp_ok;
  147. case SUBTYPE_KEYBOARD_MODIFIER_SET:
  148. keyboard_modifying_key_set(value);
  149. return resp_ok;
  150. case SUBTYPE_KEYBOARD_MODIFIER_CLEAR:
  151. keyboard_modifying_key_set(0x00);
  152. return resp_ok;
  153. case SUBTYPE_KEYBOARD_FUNCTKEY_WRITE:
  154. if (!is_funckey(value))
  155. return resp_invalid_key_value;
  156. Keyboard_press(value);
  157. delay(100);
  158. Keyboard_release(value);
  159. return resp_ok;
  160. case SUBTYPE_KEYBOARD_OTHERKEY_PRESS:
  161. if (!is_validkeys(value))
  162. return resp_invalid_key_value;
  163. Keyboard_press(value);
  164. return resp_ok;
  165. case SUBTYPE_KEYBOARD_OTHERKEY_RELEASE:
  166. if (!is_validkeys(value))
  167. return resp_invalid_key_value;
  168. Keyboard_release(value);
  169. return resp_ok;
  170. case SUBTYPE_KEYBOARD_SPECIAL_CTRLALTDEL:
  171. // Press Ctrl + Alt + Del
  172. Keyboard_press(KEY_LEFT_CTRL);
  173. Keyboard_press(KEY_LEFT_ALT);
  174. Keyboard_press(KEY_DELETE);
  175. delay(100); // Give a little longer time for all keys to be registered together
  176. // Release Ctrl + Alt + Del in reverse order
  177. Keyboard_release(KEY_DELETE);
  178. delay(20);
  179. Keyboard_release(KEY_LEFT_ALT);
  180. delay(20);
  181. Keyboard_release(KEY_LEFT_CTRL);
  182. delay(20);
  183. return resp_ok;
  184. case SUBTYPE_KEYBOARD_SPECIAL_RESET:
  185. Keyboard_releaseAll();
  186. return resp_ok;
  187. default:
  188. return resp_invalid_opr_type;
  189. }
  190. }