keyboard_emu.ino 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. ketboard_emu.ino
  3. This file handle keyboard emulation and key writes
  4. */
  5. #define MAX_KEYBOARD_HID_KEYCODE_NO 6
  6. #define ENABLE_KEYBOARD_DEBUG_PRINTOUT
  7. /* Modifier keycode for CH9329 */
  8. #define MOD_LCTRL 0x01
  9. #define MOD_LSHIFT 0x02
  10. #define MOD_LALT 0x04
  11. #define MOD_LGUI 0x08
  12. #define MOD_RCTRL 0x10
  13. #define MOD_RSHIFT 0x20
  14. #define MOD_RALT 0x40
  15. #define MOD_RGUI 0x80
  16. /* Runtime variables */
  17. uint8_t keyboard_state[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  18. //byte 0: Computer connected
  19. //byte 1:
  20. // bit 0: NUM LOCK
  21. // bit 1: CAPS LOCK
  22. // bit 2: SCROLL LOCK
  23. uint8_t keyboard_leds[2] = { 0x00, 0x00 };
  24. extern uint8_t kbCmdBuf[MAX_CMD_LEN];
  25. extern uint8_t kbCmdIndex;
  26. extern uint8_t kbCmdCounter;
  27. /* Function Prototypes */
  28. void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length);
  29. /* Request CH9329 response with current keyboard status */
  30. void keyboard_get_info() {
  31. send_cmd(0x01, NULL, 0x00);
  32. }
  33. /* Callback handler for setting keyboard status */
  34. void handle_keyboard_get_info_reply() {
  35. keyboard_leds[0] = kbCmdBuf[6];
  36. keyboard_leds[1] = kbCmdBuf[7];
  37. #ifdef ENABLE_KEYBOARD_DEBUG_PRINTOUT
  38. for (int i = 0; i < kbCmdIndex; i++) {
  39. uint8_t b = kbCmdBuf[i];
  40. USBSerial_print("0x");
  41. if (b < 0x10) USBSerial_print("0");
  42. USBSerial_print(b, HEX);
  43. USBSerial_print(" ");
  44. }
  45. USBSerial_println(keyboard_leds[0] ? "Connected" : "Not Connected");
  46. USBSerial_println((keyboard_leds[1] & 0x01) ? "NUMLOCK ON" : "NUMLOCK OFF");
  47. USBSerial_println((keyboard_leds[1] & 0x02) ? "CAPSLOCK ON" : "CAPSLOCK OFF");
  48. USBSerial_println((keyboard_leds[1] & 0x04) ? "SCROLLLOCK ON" : "SCROLLLOCK OFF");
  49. #endif
  50. }
  51. /* helper to write an array of uint8_t to CH9329 */
  52. void Serial0_writeBuf(const uint8_t* data, uint8_t len) {
  53. for (uint8_t i = 0; i < len; i++) {
  54. Serial0_write(data[i]);
  55. }
  56. }
  57. /* Send key combinations, keycode must be an array with length 6 */
  58. int keyboard_send_key_combinations(uint8_t modifiers, uint8_t* keycode, uint8_t length) {
  59. if (length != MAX_KEYBOARD_HID_KEYCODE_NO) {
  60. //This function must take in an array of 6 keycodes
  61. return -1;
  62. }
  63. uint8_t packet[14] = {
  64. 0x57, 0xAB, 0x00, 0x02, 0x08,
  65. modifiers, 0x00,
  66. keycode[0], keycode[1], keycode[2], keycode[3], keycode[4], keycode[5],
  67. 0x00
  68. };
  69. packet[13] = calcChecksum(packet, 13);
  70. Serial0_writeBuf(packet, 14);
  71. return 0;
  72. }
  73. /* Release all keypress on the current emulated keyboard */
  74. void keyboard_release_all_keys() {
  75. uint8_t packet[] = {
  76. 0x57, 0xAB, 0x00, 0x02, 0x08,
  77. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  78. 0x00 // checksum placeholder
  79. };
  80. packet[13] = calcChecksum(packet, 13);
  81. Serial0_writeBuf(packet, 14);
  82. }
  83. /* Convert JavaScrpt Keycode into HID keycode */
  84. uint8_t javascript_keycode_to_hid_opcode(uint8_t keycode) {
  85. // Letters A-Z
  86. if (keycode >= 65 && keycode <= 90) {
  87. return (keycode - 65) + 0x04; // 'A' is 0x04
  88. }
  89. // Numbers 1-9 (top row, not numpad)
  90. if (keycode >= 49 && keycode <= 57) {
  91. return (keycode - 48) + 0x1E; // '1' is 0x1E
  92. }
  93. //Numpad 1-9
  94. if (keycode >= 97 && keycode <= 105) {
  95. return (keycode - 97) + 0x59; // '1' (numpad) is 0x59
  96. }
  97. //F1 to F12
  98. if (keycode >= 112 && keycode <= 123) {
  99. return (keycode - 112) + 0x3A; // 'F1' is 0x3A
  100. }
  101. switch (keycode) {
  102. case 8:
  103. return 0x2A; // Backspace
  104. case 9:
  105. return 0x2B; // Tab
  106. case 13:
  107. return 0x28; // Enter
  108. case 16:
  109. return 0xE1; //Left shift
  110. case 17:
  111. return 0xE0; //Left Ctrl
  112. case 18:
  113. return 0xE6; //Left Alt
  114. case 20:
  115. return 0x39; // Caps Lock
  116. case 27:
  117. return 0x29; // Escape
  118. case 32:
  119. return 0x2C; // Spacebar
  120. case 33:
  121. return 0x4B; // Page Up
  122. case 34:
  123. return 0x4E; // Page Down
  124. case 35:
  125. return 0x4D; // End
  126. case 36:
  127. return 0x4A; // Home
  128. case 37:
  129. return 0x50; // Left Arrow
  130. case 38:
  131. return 0x52; // Up Arrow
  132. case 39:
  133. return 0x4F; // Right Arrow
  134. case 40:
  135. return 0x51; // Down Arrow
  136. case 44:
  137. return 0x46; //Print Screen or F13 (Firefox)
  138. case 45:
  139. return 0x49; // Insert
  140. case 46:
  141. return 0x4C; // Delete
  142. case 48:
  143. return 0x27; // 0 (not Numpads)
  144. // 49 - 57 Number row 1 - 9 handled above
  145. // 58 not supported
  146. case 59:
  147. return 0x33; // ';'
  148. // 60 not supported
  149. case 61:
  150. return 0x2E; // '='
  151. //62 - 90 not supported
  152. case 91:
  153. return 0xE3; // Left GUI (Windows)
  154. case 92:
  155. return 0xE7; // Right GUI
  156. case 93:
  157. return 0x65; // Menu key
  158. // 64 - 65 not supported
  159. case 96:
  160. return 0x62; //0 (Numpads)
  161. //Numpad 1 to 9 handled above
  162. case 106:
  163. return 0x55; //* (Numpads)
  164. case 107:
  165. return 0x57; //+ (Numpads)
  166. case 109:
  167. return 0x56; //- (Numpads)
  168. case 110:
  169. return 0x63; // dot (Numpads)
  170. case 111:
  171. return 0x54; // divide (Numpads)
  172. // 112 - 123 F1 to F12 handled above
  173. // 124 - 143 F13 to F32 not supported
  174. case 144:
  175. return 0x53; // Num Lock
  176. case 145:
  177. return 0x47; // Scroll Lock
  178. // 146 - 185 not supported or not exists
  179. case 186:
  180. return 0x33; // ;
  181. case 187:
  182. return 0x2E; // =
  183. case 188:
  184. return 0x36; // ,
  185. case 189:
  186. return 0x2D; // -
  187. case 190:
  188. return 0x37; // .
  189. case 191:
  190. return 0x38; // /
  191. case 192:
  192. return 0x35; // `
  193. case 219:
  194. return 0x2F; // [
  195. case 220:
  196. return 0x31; // backslash
  197. case 221:
  198. return 0x30; // ]
  199. case 222:
  200. return 0x34; // '
  201. default:
  202. return 0x00; // Unknown / unsupported
  203. }
  204. }