123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /*
- ketboard_emu.ino
- This file handle keyboard emulation and key writes
- */
- #define MAX_KEYBOARD_HID_KEYCODE_NO 6
- #define ENABLE_KEYBOARD_DEBUG_PRINTOUT
- /* Modifier keycode for CH9329 */
- #define MOD_LCTRL 0x01
- #define MOD_LSHIFT 0x02
- #define MOD_LALT 0x04
- #define MOD_LGUI 0x08
- #define MOD_RCTRL 0x10
- #define MOD_RSHIFT 0x20
- #define MOD_RALT 0x40
- #define MOD_RGUI 0x80
- /* Runtime variables */
- uint8_t keyboard_state[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- //byte 0: Computer connected
- //byte 1:
- // bit 0: NUM LOCK
- // bit 1: CAPS LOCK
- // bit 2: SCROLL LOCK
- uint8_t keyboard_leds[2] = { 0x00, 0x00 };
- extern uint8_t kbCmdBuf[MAX_CMD_LEN];
- extern uint8_t kbCmdIndex;
- extern uint8_t kbCmdCounter;
- /* Function Prototypes */
- void send_cmd(uint8_t cmd, uint8_t* data, uint8_t length);
- /* Request CH9329 response with current keyboard status */
- void keyboard_get_info() {
- send_cmd(0x01, NULL, 0x00);
- }
- /* Callback handler for setting keyboard status */
- void handle_keyboard_get_info_reply() {
- keyboard_leds[0] = kbCmdBuf[6];
- keyboard_leds[1] = kbCmdBuf[7];
- #ifdef ENABLE_KEYBOARD_DEBUG_PRINTOUT
- for (int i = 0; i < kbCmdIndex; i++) {
- uint8_t b = kbCmdBuf[i];
- USBSerial_print("0x");
- if (b < 0x10) USBSerial_print("0");
- USBSerial_print(b, HEX);
- USBSerial_print(" ");
- }
- USBSerial_println(keyboard_leds[0] ? "Connected" : "Not Connected");
- USBSerial_println((keyboard_leds[1] & 0x01) ? "NUMLOCK ON" : "NUMLOCK OFF");
- USBSerial_println((keyboard_leds[1] & 0x02) ? "CAPSLOCK ON" : "CAPSLOCK OFF");
- USBSerial_println((keyboard_leds[1] & 0x04) ? "SCROLLLOCK ON" : "SCROLLLOCK OFF");
- #endif
- }
- /* helper to write an array of uint8_t to CH9329 */
- void Serial0_writeBuf(const uint8_t* data, uint8_t len) {
- for (uint8_t i = 0; i < len; i++) {
- Serial0_write(data[i]);
- }
- }
- /* Send key combinations, keycode must be an array with length 6 */
- int keyboard_send_key_combinations(uint8_t modifiers, uint8_t* keycode, uint8_t length) {
- if (length != MAX_KEYBOARD_HID_KEYCODE_NO) {
- //This function must take in an array of 6 keycodes
- return -1;
- }
- uint8_t packet[14] = {
- 0x57, 0xAB, 0x00, 0x02, 0x08,
- modifiers, 0x00,
- keycode[0], keycode[1], keycode[2], keycode[3], keycode[4], keycode[5],
- 0x00
- };
- packet[13] = calcChecksum(packet, 13);
- Serial0_writeBuf(packet, 14);
- return 0;
- }
- /* Release all keypress on the current emulated keyboard */
- void keyboard_release_all_keys() {
- uint8_t packet[] = {
- 0x57, 0xAB, 0x00, 0x02, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00 // checksum placeholder
- };
- packet[13] = calcChecksum(packet, 13);
- Serial0_writeBuf(packet, 14);
- }
- /* Convert JavaScrpt Keycode into HID keycode */
- uint8_t javascript_keycode_to_hid_opcode(uint8_t keycode) {
- // Letters A-Z
- if (keycode >= 65 && keycode <= 90) {
- return (keycode - 65) + 0x04; // 'A' is 0x04
- }
- // Numbers 1-9 (top row, not numpad)
- if (keycode >= 49 && keycode <= 57) {
- return (keycode - 48) + 0x1E; // '1' is 0x1E
- }
- //Numpad 1-9
- if (keycode >= 97 && keycode <= 105) {
- return (keycode - 97) + 0x59; // '1' (numpad) is 0x59
- }
- //F1 to F12
- if (keycode >= 112 && keycode <= 123) {
- return (keycode - 112) + 0x3A; // 'F1' is 0x3A
- }
- switch (keycode) {
- case 8:
- return 0x2A; // Backspace
- case 9:
- return 0x2B; // Tab
- case 13:
- return 0x28; // Enter
- case 16:
- return 0xE1; //Left shift
- case 17:
- return 0xE0; //Left Ctrl
- case 18:
- return 0xE6; //Left Alt
- case 20:
- return 0x39; // Caps Lock
- case 27:
- return 0x29; // Escape
- case 32:
- return 0x2C; // Spacebar
- case 33:
- return 0x4B; // Page Up
- case 34:
- return 0x4E; // Page Down
- case 35:
- return 0x4D; // End
- case 36:
- return 0x4A; // Home
- case 37:
- return 0x50; // Left Arrow
- case 38:
- return 0x52; // Up Arrow
- case 39:
- return 0x4F; // Right Arrow
- case 40:
- return 0x51; // Down Arrow
- case 44:
- return 0x46; //Print Screen or F13 (Firefox)
- case 45:
- return 0x49; // Insert
- case 46:
- return 0x4C; // Delete
- case 48:
- return 0x27; // 0 (not Numpads)
- // 49 - 57 Number row 1 - 9 handled above
- // 58 not supported
- case 59:
- return 0x33; // ';'
- // 60 not supported
- case 61:
- return 0x2E; // '='
- //62 - 90 not supported
- case 91:
- return 0xE3; // Left GUI (Windows)
- case 92:
- return 0xE7; // Right GUI
- case 93:
- return 0x65; // Menu key
- // 64 - 65 not supported
- case 96:
- return 0x62; //0 (Numpads)
- //Numpad 1 to 9 handled above
- case 106:
- return 0x55; //* (Numpads)
- case 107:
- return 0x57; //+ (Numpads)
- case 109:
- return 0x56; //- (Numpads)
- case 110:
- return 0x63; // dot (Numpads)
- case 111:
- return 0x54; // divide (Numpads)
- // 112 - 123 F1 to F12 handled above
- // 124 - 143 F13 to F32 not supported
- case 144:
- return 0x53; // Num Lock
- case 145:
- return 0x47; // Scroll Lock
- // 146 - 185 not supported or not exists
- case 186:
- return 0x33; // ;
- case 187:
- return 0x2E; // =
- case 188:
- return 0x36; // ,
- case 189:
- return 0x2D; // -
- case 190:
- return 0x37; // .
- case 191:
- return 0x38; // /
- case 192:
- return 0x35; // `
- case 219:
- return 0x2F; // [
- case 220:
- return 0x31; // backslash
- case 221:
- return 0x30; // ]
- case 222:
- return 0x34; // '
- default:
- return 0x00; // Unknown / unsupported
- }
- }
|