123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- /*
- keyboard_emu.ino
- Author: tobychui
- This code file handle keyboard emulation related functionality
- When opr_type is set to 0x01, the sub-handler will process the
- request here.
- -- Keyboard Opcode --
- 0x00 = Reserved
- 0x01 = keyboard write
- 0x02 = keyboard press
- 0x03 = keyboard release
- (ASCII bytes in range of 32 to 127)
- 0x04 = Modifier key combination set (bit flags in payload)
- Bit 0 (0x01) = KEY_LEFT_CTRL
- Bit 1 (0x02) = KEY_LEFT_SHIFT
- Bit 2 (0x04) = KEY_LEFT_ALT
- Bit 3 (0x08) = KEY_LEFT_GUI
- Bit 4 (0x10) = KEY_RIGHT_CTRL
- Bit 5 (0x20) = KEY_RIGHT_SHIFT
- Bit 6 (0x40) = KEY_RIGHT_ALT
- Bit 7 (0x80) = KEY_RIGHT_GUI
- 0x05 = Modifier key combination reset
- 0x07 = Function key combinartion write
- 0xC2 = KEY_F1
- 0xC3 = KEY_F2
- 0xC4 = KEY_F3
- ...
- 0xCC = KEY_F11
- 0xCD = KEY_F12
- 0xF0 = KEY_F13
- ...
- 0xFB = KEY_F24
-
- 0x08 = Other keys press
- 0x09 = Other keys release
- 0xDA = KEY_UP_ARROW
- 0xD9 = KEY_DOWN_ARROW
- 0xD8 = KEY_LEFT_ARROW
- 0xD7 = KEY_RIGHT_ARROW
- 0xB2 = KEY_BACKSPACE
- 0xB3 = KEY_TAB
- 0xB0 = KEY_RETURN
- 0xB1 = KEY_ESC
- 0xD1 = KEY_INSERT
- 0xD4 = KEY_DELETE
- 0xD3 = KEY_PAGE_UP
- 0xD6 = KEY_PAGE_DOWN
- 0xD2 = KEY_HOME
- 0xD5 = KEY_END
- 0xC1 = KEY_CAPS_LOCK
- -- Special Opcode --
- 0xFE = Ctrl + Alt + Delete
- 0xFF = Reset all keys state
- */
- #include "usbkvm_fw.h"
- //Check if the value is a supported ascii code
- bool is_ascii(uint8_t value) {
- return value >= 32 && value <= 127;
- }
- //Check if the value is a valid function key value
- bool is_funckey(uint8_t value) {
- return ((value >= 0xC2 && value <= 0xCD) || (value >= 0xF0 && value <= 0xFB));
- }
- //Check if the key is valid key that do not belongs in ASCII or function key
- bool is_validkeys(uint8_t key) {
- if (key >= 0xD7 && key <= 0xDA) {
- //Arrow keys
- return true;
- }
- if (key >= 0xB0 && key <= 0xB3) {
- //ESC, tabs and other left-most keys
- return true;
- }
- if (key >= 0xD1 && key <= 0xD6) {
- //Keys above arrow keys like pageup and down
- return true;
- }
- //CAP_LOCK
- return key == 0xC1;
- }
- //Check if the nth bit is set in the value
- bool isBitSet(uint8_t value, uint8_t n) {
- if (n > 7) return false; // Ensure n is within 0-7
- return (value & (1 << n)) != 0;
- }
- //Handle modifying key set or unset
- void keyboard_modifying_key_set(uint8_t key) {
- if (key & 0x01) { // Bit 0 = KEY_LEFT_CTRL
- Keyboard_press(KEY_LEFT_CTRL);
- } else {
- Keyboard_release(KEY_LEFT_CTRL);
- }
- if (key & 0x02) { // Bit 1 = KEY_LEFT_SHIFT
- Keyboard_press(KEY_LEFT_SHIFT);
- } else {
- Keyboard_release(KEY_LEFT_SHIFT);
- }
- if (key & 0x04) { // Bit 2 = KEY_LEFT_ALT
- Keyboard_press(KEY_LEFT_ALT);
- } else {
- Keyboard_release(KEY_LEFT_ALT);
- }
- if (key & 0x08) { // Bit 3 = KEY_LEFT_GUI
- Keyboard_press(KEY_LEFT_GUI);
- } else {
- Keyboard_release(KEY_LEFT_GUI);
- }
- if (key & 0x10) { // Bit 4 = KEY_RIGHT_CTRL
- Keyboard_press(KEY_RIGHT_CTRL);
- } else {
- Keyboard_release(KEY_RIGHT_CTRL);
- }
- if (key & 0x20) { // Bit 5 = KEY_RIGHT_SHIFT
- Keyboard_press(KEY_RIGHT_SHIFT);
- } else {
- Keyboard_release(KEY_RIGHT_SHIFT);
- }
- if (key & 0x40) { // Bit 6 = KEY_RIGHT_ALT
- Keyboard_press(KEY_RIGHT_ALT);
- } else {
- Keyboard_release(KEY_RIGHT_ALT);
- }
- if (key & 0x80) { // Bit 7 = KEY_RIGHT_GUI
- Keyboard_press(KEY_RIGHT_GUI);
- } else {
- Keyboard_release(KEY_RIGHT_GUI);
- }
- }
- //Set a specific numpad key value
- void numpad_key_set(bool isPress, uint8_t value) {
- if (isPress) {
- switch (value) {
- case PAYLOAD_NUMPAD_0:
- Keyboard_press('\352'); //0
- return;
- case PAYLOAD_NUMPAD_1:
- Keyboard_press('\341'); //1
- return;
- case PAYLOAD_NUMPAD_2:
- Keyboard_press('\342'); //2
- return;
- case PAYLOAD_NUMPAD_3:
- Keyboard_press('\343'); //3
- return;
- case PAYLOAD_NUMPAD_4:
- Keyboard_press('\344'); //4
- return;
- case PAYLOAD_NUMPAD_5:
- Keyboard_press('\345'); //5
- return;
- case PAYLOAD_NUMPAD_6:
- Keyboard_press('\346'); //6
- return;
- case PAYLOAD_NUMPAD_7:
- Keyboard_press('\347'); //7
- return;
- case PAYLOAD_NUMPAD_8:
- Keyboard_press('\350'); //8
- return;
- case PAYLOAD_NUMPAD_9:
- Keyboard_press('\351'); //9
- return;
- case PAYLOAD_NUMPAD_DOT:
- Keyboard_press('\353'); //.
- return;
- case PAYLOAD_NUMPAD_TIMES:
- Keyboard_press('\335'); //*
- return;
- case PAYLOAD_NUMPAD_DIV:
- Keyboard_press('\334'); // /
- return;
- case PAYLOAD_NUMPAD_PLUS:
- Keyboard_press('\337'); // +
- return;
- case PAYLOAD_NUMPAD_MINUS:
- Keyboard_press('\336'); // -
- return;
- case PAYLOAD_NUMPAD_ENTER:
- Keyboard_press('\340'); // Enter
- return;
- case PAYLOAD_NUMPAD_NUMLOCK:
- Keyboard_press('\333'); // NumLock
- return;
- }
- } else {
- switch (value) {
- case PAYLOAD_NUMPAD_0:
- Keyboard_release('\352'); //0
- return;
- case PAYLOAD_NUMPAD_1:
- Keyboard_release('\341'); //1
- return;
- case PAYLOAD_NUMPAD_2:
- Keyboard_release('\342'); //2
- return;
- case PAYLOAD_NUMPAD_3:
- Keyboard_release('\343'); //3
- return;
- case PAYLOAD_NUMPAD_4:
- Keyboard_release('\344'); //4
- return;
- case PAYLOAD_NUMPAD_5:
- Keyboard_release('\345'); //5
- return;
- case PAYLOAD_NUMPAD_6:
- Keyboard_release('\346'); //6
- return;
- case PAYLOAD_NUMPAD_7:
- Keyboard_release('\347'); //7
- return;
- case PAYLOAD_NUMPAD_8:
- Keyboard_release('\350'); //8
- return;
- case PAYLOAD_NUMPAD_9:
- Keyboard_release('\351'); //9
- return;
- case PAYLOAD_NUMPAD_DOT:
- Keyboard_release('\353'); //.
- return;
- case PAYLOAD_NUMPAD_TIMES:
- Keyboard_release('\335'); //*
- return;
- case PAYLOAD_NUMPAD_DIV:
- Keyboard_release('\334'); // /
- return;
- case PAYLOAD_NUMPAD_PLUS:
- Keyboard_release('\337'); // +
- return;
- case PAYLOAD_NUMPAD_MINUS:
- Keyboard_release('\336'); // -
- return;
- case PAYLOAD_NUMPAD_ENTER:
- Keyboard_release('\340'); // Enter
- return;
- case PAYLOAD_NUMPAD_NUMLOCK:
- Keyboard_release('\333'); // NumLock
- return;
- }
- }
- }
- //Entry point for keyboard emulation
- uint8_t keyboard_emulation(uint8_t subtype, uint8_t value) {
- //Check if the input is a supported ascii value
- switch (subtype) {
- case SUBTYPE_KEYBOARD_ASCII_WRITE:
- if (!is_ascii(value))
- return resp_invalid_key_value;
- Keyboard_write(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_ASCII_PRESS:
- if (!is_ascii(value))
- return resp_invalid_key_value;
- Keyboard_press(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_ASCII_RELEASE:
- if (!is_ascii(value))
- return resp_invalid_key_value;
- Keyboard_release(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_MODIFIER_SET:
- keyboard_modifying_key_set(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_MODIFIER_CLEAR:
- keyboard_modifying_key_set(0x00);
- return resp_ok;
- case SUBTYPE_KEYBOARD_FUNCTKEY_PRESS:
- if (!is_funckey(value))
- return resp_invalid_key_value;
- Keyboard_press(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_FUNCTKEY_RELEASE:
- if (!is_funckey(value))
- return resp_invalid_key_value;
- Keyboard_release(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_OTHERKEY_PRESS:
- if (!is_validkeys(value))
- return resp_invalid_key_value;
- Keyboard_press(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_OTHERKEY_RELEASE:
- if (!is_validkeys(value))
- return resp_invalid_key_value;
- Keyboard_release(value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_NUMPAD_PRESS:
- if (value > PAYLOAD_NUMPAD_NUMLOCK)
- return resp_invalid_key_value;
- numpad_key_set(true, value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_NUMPAD_RELEASE:
- if (value > PAYLOAD_NUMPAD_NUMLOCK)
- return resp_invalid_key_value;
- numpad_key_set(false, value);
- return resp_ok;
- case SUBTYPE_KEYBOARD_SPECIAL_CTRLALTDEL:
- // Press Ctrl + Alt + Del
- Keyboard_press(KEY_LEFT_CTRL);
- Keyboard_press(KEY_LEFT_ALT);
- Keyboard_press(KEY_DELETE);
- delay(100); // Give a little longer time for all keys to be registered together
- // Release Ctrl + Alt + Del in reverse order
- Keyboard_release(KEY_DELETE);
- delay(MIN_KEY_EVENTS_DELAY);
- Keyboard_release(KEY_LEFT_ALT);
- delay(MIN_KEY_EVENTS_DELAY);
- Keyboard_release(KEY_LEFT_CTRL);
- delay(MIN_KEY_EVENTS_DELAY);
- return resp_ok;
- case SUBTYPE_KEYBOARD_SPECIAL_RESET:
- //Release all pressed keys
- Keyboard_releaseAll();
- return resp_ok;
- default:
- return resp_invalid_opr_type;
- }
- }
|