123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- /*
- ketboard_emu.ino
- This file handle keyboard emulation and key writes
- */
- #define KEYBOARD_HID_KEYCODE_LENGTH 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[KEYBOARD_HID_KEYCODE_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t keyboard_pressing_key_count = 0; //No. of key currently pressing, max is 6
- uint8_t keyboard_modifiers = 0x00; //Current modifier key state
- //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
- }
- /* Send key combinations to CH9329*/
- int keyboard_send_key_combinations() {
- uint8_t packet[14] = {
- 0x57, 0xAB, 0x00, 0x02, 0x08,
- keyboard_modifiers, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00
- };
- //Populate the HID keycodes
- for (uint8_t i = 0; i < KEYBOARD_HID_KEYCODE_LENGTH; i++) {
- packet[7 + i] = keyboard_state[i];
- }
- 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
- }
- }
- //Send a keyboard press by JavaScript keycode
- int keyboard_press_key(uint8_t keycode) {
- //Convert javascript keycode to HID
- keycode = javascript_keycode_to_hid_opcode(keycode);
- if (keycode == 0x00) {
- //Not supported
- return -1;
- }
- // Already pressed? Skip
- for (int i = 0; i < 6; i++) {
- if (keyboard_state[i] == keycode) {
- return 0; // Already held
- }
- }
- //Get the empty slot in the current HID list
- for (int i = 0; i < 6; i++) {
- if (keyboard_state[i] == 0x00) {
- keyboard_state[i] = keycode;
- keyboard_pressing_key_count++;
- keyboard_send_key_combinations();
- return 0;
- }
- }
- //No space left
- return -1;
- }
- //Send a keyboard release by JavaScript keycode
- int keyboard_release_key(uint8_t keycode) {
- //Convert javascript keycode to HID
- keycode = javascript_keycode_to_hid_opcode(keycode);
- if (keycode == 0x00) {
- //Not supported
- return -1;
- }
- //Get the position where the key is pressed
- for (int i = 0; i < 6; i++) {
- if (keyboard_state[i] == keycode) {
- keyboard_state[i] = 0x00;
- if (keyboard_pressing_key_count > 0) {
- keyboard_pressing_key_count--;
- }
- keyboard_send_key_combinations();
- return 0;
- }
- }
- //That key is not pressed
- return 0;
- }
- uint8_t keyboard_get_modifier_bit_from_opcode(uint8_t opcode) {
- switch (opcode) {
- case 0x01:
- return MOD_LCTRL;
- case 0x02:
- return MOD_LSHIFT;
- case 0x03:
- return MOD_LALT;
- case 0x04:
- return MOD_LGUI;
- case 0x05:
- return MOD_RCTRL;
- case 0x06:
- return MOD_RSHIFT;
- case 0x07:
- return MOD_RALT;
- case 0x08:
- return MOD_RGUI;
- case 0x09:
- //Ctrl + Alt + Del
- return MOD_LCTRL | MOD_LALT;
- case 0x0A:
- //Win + Shift + S
- return MOD_LSHIFT | MOD_LGUI;
- break;
- //To be added
- default:
- return 0x00;
- }
- }
- //Set the modifier key bit
- int keyboard_press_modkey(uint8_t opcode) {
- if (opcode == 0x00){
- //Reset the modkeys
- keyboard_modifiers = 0;
- keyboard_send_key_combinations();
- return 0;
- }
- uint8_t mask = keyboard_get_modifier_bit_from_opcode(opcode);
- if (mask == 0x00){
- return -1;
- }
- keyboard_modifiers |= mask;
- keyboard_send_key_combinations();
- return 0;
- }
- //Unset modifier key bit
- int keyboard_release_modkey(uint8_t opcode) {
- if (opcode == 0x00){
- //Reset the modkeys
- keyboard_modifiers = 0;
- keyboard_send_key_combinations();
- return 0;
- }
- uint8_t mask = keyboard_get_modifier_bit_from_opcode(opcode);
- if (mask == 0x00){
- return -1;
- }
- keyboard_modifiers &= ~mask;
- keyboard_send_key_combinations();
- return 0;
- }
- //Reset all keypress on keyboard
- void keyboard_reset(){
- memset(keyboard_state, 0x00, sizeof(keyboard_state));
- keyboard_modifiers = 0x00;
- keyboard_send_key_combinations();
- }
|