| /* |
| * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) |
| * |
| * SPDX-License-Identifier: BSD-2-Clause |
| */ |
| |
| #include "keyboard_vkey.h" |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <assert.h> |
| |
| /* This requires ISO-C99 gcc standard. */ |
| /* ref: http://www.unix-manuals.com/refs/misc/ascii-table.html */ |
| keycode_info_t keycodes[VK_MAX_ENUM] = { |
| [0 ... (VK_MAX_ENUM - 1)] = { -1, -1, -1}, |
| |
| [VK_ESCAPE] = {VK_ESCAPE, VK_ESCAPE, -1}, |
| [VK_OEM_3] = {'`', '~', -1}, |
| [VK_1] = {'1', '!', -1}, |
| [VK_2] = {'2', '@', -1}, |
| [VK_3] = {'3', '#', -1}, |
| [VK_4] = {'4', '$', -1}, |
| [VK_5] = {'5', '%', -1}, |
| [VK_6] = {'6', '^', -1}, |
| [VK_7] = {'7', '&', -1}, |
| [VK_8] = {'8', '*', -1}, |
| [VK_9] = {'9', '(', -1}, |
| [VK_0] = {'0', ')', -1}, |
| [VK_OEM_MINUS] = {'-', '_', -1}, |
| [VK_OEM_PLUS] = {'=', '+', -1}, |
| [VK_BACK] = {VK_BACK, VK_BACK, -1}, |
| [VK_TAB] = {VK_TAB, VK_TAB, -1}, |
| [VK_Q] = {'q', 'Q', 0x11}, |
| [VK_W] = {'w', 'W', 0x17}, |
| [VK_E] = {'e', 'E', 0x5}, |
| [VK_R] = {'r', 'R', 0x12}, |
| [VK_T] = {'t', 'T', 0x14}, |
| [VK_Y] = {'y', 'Y', 0x19}, |
| [VK_U] = {'u', 'U', 0x15}, |
| [VK_I] = {'i', 'I', 0x9}, |
| [VK_O] = {'o', 'O', 0x0F}, |
| [VK_P] = {'p', 'P', 0x10}, |
| [VK_OEM_4] = {'[', '{', VK_ESCAPE}, |
| [VK_OEM_6] = {']', '}', 0x29}, |
| [VK_OEM_5] = {'\\', '|', 0x28}, |
| [VK_A] = {'a', 'A', 0x1}, |
| [VK_S] = {'s', 'S', 0x13}, |
| [VK_D] = {'d', 'D', 0x4}, |
| [VK_F] = {'f', 'F', 0x6}, |
| [VK_G] = {'g', 'G', 0x7}, |
| [VK_H] = {'h', 'H', 0x8}, |
| [VK_J] = {'j', 'J', 0x0A}, |
| [VK_K] = {'k', 'K', 0x0B}, |
| [VK_L] = {'l', 'L', 0x0C}, |
| [VK_OEM_1] = {';', ':', -1}, |
| [VK_OEM_7] = {'\'', '"', -1}, |
| [VK_RETURN] = {VK_RETURN, VK_RETURN, -1}, |
| [VK_Z] = {'z', 'Z', 0x1A}, |
| [VK_X] = {'x', 'X', 0x18}, |
| [VK_C] = {'c', 'C', 0x3}, |
| [VK_V] = {'v', 'V', 0x16}, |
| [VK_B] = {'b', 'B', 0x2}, |
| [VK_N] = {'n', 'N', 0x0E}, |
| [VK_M] = {'m', 'M', 0x0D}, |
| [VK_OEM_COMMA] = {',', ',', -1}, |
| [VK_OEM_PERIOD] = {'.', '>', -1}, |
| [VK_OEM_2] = {'/', '?', -1}, |
| [VK_SPACE] = {VK_SPACE, VK_SPACE, -1}, |
| [VK_DELETE] = {0x7F, 0x7F, -1}, |
| [VK_DIVIDE] = {'/', '/', -1}, |
| [VK_MULTIPLY] = {'*', '*', -1}, |
| [VK_SUBTRACT] = {'-', '-', -1}, |
| [VK_ADD] = {'+', '+', -1}, |
| [VK_NUMPAD0] = {'0', '0', -1}, |
| [VK_NUMPAD1] = {'1', '1', -1}, |
| [VK_NUMPAD2] = {'2', '2', -1}, |
| [VK_NUMPAD3] = {'3', '3', -1}, |
| [VK_NUMPAD4] = {'4', '4', -1}, |
| [VK_NUMPAD5] = {'5', '5', -1}, |
| [VK_NUMPAD6] = {'6', '6', -1}, |
| [VK_NUMPAD7] = {'7', '7', -1}, |
| [VK_NUMPAD8] = {'8', '8', -1}, |
| [VK_NUMPAD9] = {'9', '9', -1} |
| }; |
| |
| /* ref: http://techdocs.altium.com/display/FPGA/PS2+Keyboard+Scan+Codes |
| NOTE: This table does not contain the extended char codes, they are handled as special cases |
| by the keycode_ps2_to_vkey() helper function. This is done to reduce the memory footprint |
| of this lookup table from 65535 to 256 bytes. |
| */ |
| int16_t ps2_to_vkey[PS2_MAX_KEYCODES_BASIC] = { |
| [0 ... (PS2_MAX_KEYCODES_BASIC - 1)] = -1, |
| |
| [PS2_KEY_ESC] = VK_ESCAPE, |
| [PS2_KEY_F1] = VK_F1, |
| [PS2_KEY_F2] = VK_F2, |
| [PS2_KEY_F3] = VK_F3, |
| [PS2_KEY_F4] = VK_F4, |
| [PS2_KEY_F5] = VK_F5, |
| [PS2_KEY_F6] = VK_F6, |
| [PS2_KEY_F7] = VK_F7, |
| [PS2_KEY_F8] = VK_F8, |
| [PS2_KEY_F9] = VK_F9, |
| [PS2_KEY_F10] = VK_F10, |
| [PS2_KEY_F11] = VK_F11, |
| [PS2_KEY_F12] = VK_F12, |
| [PS2_KEY_SCROLL_LOCK] = VK_SCROLL, |
| [PS2_KEY_TILDE] = VK_OEM_3, |
| [PS2_KEY_1] = VK_1, |
| [PS2_KEY_2] = VK_2, |
| [PS2_KEY_3] = VK_3, |
| [PS2_KEY_4] = VK_4, |
| [PS2_KEY_5] = VK_5, |
| [PS2_KEY_6] = VK_6, |
| [PS2_KEY_7] = VK_7, |
| [PS2_KEY_8] = VK_8, |
| [PS2_KEY_9] = VK_9, |
| [PS2_KEY_0] = VK_0, |
| [PS2_KEY_SUBTRACT] = VK_OEM_MINUS, |
| [PS2_KEY_EQUALS] = VK_OEM_PLUS, |
| [PS2_KEY_BACKSPACE] = VK_BACK, |
| [PS2_KEY_TAB] = VK_TAB, |
| [PS2_KEY_Q] = VK_Q, |
| [PS2_KEY_W] = VK_W, |
| [PS2_KEY_E] = VK_E, |
| [PS2_KEY_R] = VK_R, |
| [PS2_KEY_T] = VK_T, |
| [PS2_KEY_Y] = VK_Y, |
| [PS2_KEY_U] = VK_U, |
| [PS2_KEY_I] = VK_I, |
| [PS2_KEY_O] = VK_O, |
| [PS2_KEY_P] = VK_P, |
| [PS2_KEY_LBRACKET] = VK_OEM_4, |
| [PS2_KEY_RBRACKET] = VK_OEM_6, |
| [PS2_KEY_BACKSLASH] = VK_OEM_5, |
| [PS2_KEY_CAPS_LOCK] = VK_CAPITAL, |
| [PS2_KEY_A] = VK_A, |
| [PS2_KEY_S] = VK_S, |
| [PS2_KEY_D] = VK_D, |
| [PS2_KEY_F] = VK_F, |
| [PS2_KEY_G] = VK_G, |
| [PS2_KEY_H] = VK_H, |
| [PS2_KEY_J] = VK_J, |
| [PS2_KEY_K] = VK_K, |
| [PS2_KEY_L] = VK_L, |
| [PS2_KEY_COLON] = VK_OEM_1, |
| [PS2_KEY_TICK] = VK_OEM_7, |
| [PS2_KEY_ENTER] = VK_RETURN, |
| [PS2_KEY_SHIFT_LEFT] = VK_LSHIFT, |
| [PS2_KEY_Z] = VK_Z, |
| [PS2_KEY_X] = VK_X, |
| [PS2_KEY_C] = VK_C, |
| [PS2_KEY_V] = VK_V, |
| [PS2_KEY_B] = VK_B, |
| [PS2_KEY_N] = VK_N, |
| [PS2_KEY_M] = VK_M, |
| [PS2_KEY_COMMA] = VK_OEM_COMMA, |
| [PS2_KEY_DOT] = VK_OEM_PERIOD, |
| [PS2_KEY_SLASH] = VK_OEM_2, |
| [PS2_KEY_SHIFT_RIGHT] = VK_RSHIFT, |
| [PS2_KEY_CTRL_LEFT] = VK_LCONTROL, |
| [PS2_KEY_ALT_LEFT] = VK_MENU, |
| [PS2_KEY_SPACEBAR] = VK_SPACE, |
| [PS2_KEY_NUM_LOCK] = VK_NUMLOCK, |
| [PS2_KEY_NUM_MULTIPLY] = VK_MULTIPLY, |
| [PS2_KEY_NUM_MINUS] = VK_SUBTRACT, |
| [PS2_KEY_NUM_7] = VK_NUMPAD7, |
| [PS2_KEY_NUM_8] = VK_NUMPAD8, |
| [PS2_KEY_NUM_9] = VK_NUMPAD9, |
| [PS2_KEY_NUM_PLUS] = VK_ADD, |
| [PS2_KEY_NUM_4] = VK_NUMPAD4, |
| [PS2_KEY_NUM_5] = VK_NUMPAD5, |
| [PS2_KEY_NUM_6] = VK_NUMPAD6, |
| [PS2_KEY_NUM_1] = VK_NUMPAD1, |
| [PS2_KEY_NUM_2] = VK_NUMPAD2, |
| [PS2_KEY_NUM_3] = VK_NUMPAD3, |
| [PS2_KEY_NUM_0] = VK_NUMPAD0, |
| [PS2_KEY_NUM_DOT] = VK_DECIMAL |
| }; |
| |
| void |
| keycode_init(keycode_state_t *s, |
| void (*handle_keyevent_callback)(int16_t vkey, bool pressed, void *cookie), |
| void (*handle_chartyped_callback)(int c, void *cookie), |
| void (*handle_led_state_changed_callback)(void *cookie)) |
| { |
| memset(s, 0, sizeof(keycode_state_t)); |
| |
| s->num_lock = true; |
| s->handle_keyevent_callback = handle_keyevent_callback; |
| s->handle_chartyped_callback = handle_chartyped_callback; |
| s->handle_led_state_changed_callback = handle_led_state_changed_callback; |
| } |
| |
| #if KEYBOARD_KEY_DEBUG |
| const char* |
| keycode_vkey_desc(uint16_t vk) |
| { |
| switch (vk) { |
| case VK_LBUTTON: |
| return "VK_LBUTTON"; |
| case VK_RBUTTON: |
| return "VK_RBUTTON"; |
| case VK_CANCEL: |
| return "VK_CANCEL"; |
| case VK_MBUTTON: |
| return "VK_MBUTTON"; |
| case VK_XBUTTON1: |
| return "VK_XBUTTON1"; |
| case VK_XBUTTON2: |
| return "VK_XBUTTON2"; |
| case VK_BACK: |
| return "VK_BACK"; |
| case VK_TAB: |
| return "VK_TAB"; |
| case VK_CLEAR: |
| return "VK_CLEAR"; |
| case VK_RETURN: |
| return "VK_RETURN"; |
| case VK_CONTROL: |
| return "VK_CONTROL"; |
| case VK_SHIFT: |
| return "VK_SHIFT"; |
| case VK_MENU: |
| return "VK_MENU"; |
| case VK_PAUSE: |
| return "VK_PAUSE"; |
| case VK_CAPITAL: |
| return "VK_CAPITAL"; |
| case VK_KANA: |
| return "VK_KANA"; |
| case VK_JUNJA: |
| return "VK_JUNJA"; |
| case VK_FINAL: |
| return "VK_FINAL"; |
| case VK_HANJA: |
| return "VK_HANJA"; |
| case VK_ESCAPE: |
| return "VK_ESCAPE"; |
| case VK_NONCONVERT: |
| return "VK_NONCONVERT"; |
| case VK_ACCEPT: |
| return "VK_ACCEPT"; |
| case VK_MODECHANGE: |
| return "VK_MODECHANGE"; |
| case VK_SPACE: |
| return "VK_SPACE"; |
| case VK_PRIOR: |
| return "VK_PRIOR"; |
| case VK_NEXT: |
| return "VK_NEXT"; |
| case VK_END: |
| return "VK_END"; |
| case VK_HOME: |
| return "VK_HOME"; |
| case VK_LEFT: |
| return "VK_LEFT"; |
| case VK_UP: |
| return "VK_UP"; |
| case VK_RIGHT: |
| return "VK_RIGHT"; |
| case VK_DOWN: |
| return "VK_DOWN"; |
| case VK_SELECT: |
| return "VK_SELECT"; |
| case VK_PRINT: |
| return "VK_PRINT"; |
| case VK_EXECUTE: |
| return "VK_EXECUTE"; |
| case VK_SNAPSHOT: |
| return "VK_SNAPSHOT"; |
| case VK_INSERT: |
| return "VK_INSERT"; |
| case VK_DELETE: |
| return "VK_DELETE"; |
| case VK_HELP: |
| return "VK_HELP"; |
| case VK_0: |
| return "VK_0"; |
| case VK_1: |
| return "VK_1"; |
| case VK_2: |
| return "VK_2"; |
| case VK_3: |
| return "VK_3"; |
| case VK_4: |
| return "VK_4"; |
| case VK_5: |
| return "VK_5"; |
| case VK_6: |
| return "VK_6"; |
| case VK_7: |
| return "VK_7"; |
| case VK_8: |
| return "VK_8"; |
| case VK_9: |
| return "VK_9"; |
| case VK_A: |
| return "VK_A"; |
| case VK_B: |
| return "VK_B"; |
| case VK_C: |
| return "VK_C"; |
| case VK_D: |
| return "VK_D"; |
| case VK_E: |
| return "VK_E"; |
| case VK_F: |
| return "VK_F"; |
| case VK_G: |
| return "VK_G"; |
| case VK_H: |
| return "VK_H"; |
| case VK_I: |
| return "VK_I"; |
| case VK_J: |
| return "VK_J"; |
| case VK_K: |
| return "VK_K"; |
| case VK_L: |
| return "VK_L"; |
| case VK_M: |
| return "VK_M"; |
| case VK_N: |
| return "VK_N"; |
| case VK_O: |
| return "VK_O"; |
| case VK_P: |
| return "VK_P"; |
| case VK_Q: |
| return "VK_Q"; |
| case VK_R: |
| return "VK_R"; |
| case VK_S: |
| return "VK_S"; |
| case VK_T: |
| return "VK_T"; |
| case VK_U: |
| return "VK_U"; |
| case VK_V: |
| return "VK_V"; |
| case VK_W: |
| return "VK_W"; |
| case VK_X: |
| return "VK_X"; |
| case VK_Y: |
| return "VK_Y"; |
| case VK_Z: |
| return "VK_Z"; |
| case VK_LWIN: |
| return "VK_LWIN"; |
| case VK_RWIN: |
| return "VK_RWIN"; |
| case VK_APPS: |
| return "VK_APPS"; |
| case VK_SLEEP: |
| return "VK_SLEEP"; |
| case VK_NUMPAD0: |
| return "VK_NUMPAD0"; |
| case VK_NUMPAD1: |
| return "VK_NUMPAD1"; |
| case VK_NUMPAD2: |
| return "VK_NUMPAD2"; |
| case VK_NUMPAD3: |
| return "VK_NUMPAD3"; |
| case VK_NUMPAD4: |
| return "VK_NUMPAD4"; |
| case VK_NUMPAD5: |
| return "VK_NUMPAD5"; |
| case VK_NUMPAD6: |
| return "VK_NUMPAD6"; |
| case VK_NUMPAD7: |
| return "VK_NUMPAD7"; |
| case VK_NUMPAD8: |
| return "VK_NUMPAD8"; |
| case VK_NUMPAD9: |
| return "VK_NUMPAD9"; |
| case VK_MULTIPLY: |
| return "VK_MULTIPLY"; |
| case VK_ADD: |
| return "VK_ADD"; |
| case VK_SEPARATOR: |
| return "VK_SEPARATOR"; |
| case VK_SUBTRACT: |
| return "VK_SUBTRACT"; |
| case VK_DECIMAL: |
| return "VK_DECIMAL"; |
| case VK_DIVIDE: |
| return "VK_DIVIDE"; |
| case VK_F1: |
| return "VK_F1"; |
| case VK_F2: |
| return "VK_F2"; |
| case VK_F3: |
| return "VK_F3"; |
| case VK_F4: |
| return "VK_F4"; |
| case VK_F5: |
| return "VK_F5"; |
| case VK_F6: |
| return "VK_F6"; |
| case VK_F7: |
| return "VK_F7"; |
| case VK_F8: |
| return "VK_F8"; |
| case VK_F9: |
| return "VK_F9"; |
| case VK_F10: |
| return "VK_F10"; |
| case VK_F11: |
| return "VK_F11"; |
| case VK_F12: |
| return "VK_F12"; |
| case VK_F13: |
| return "VK_F13"; |
| case VK_F14: |
| return "VK_F14"; |
| case VK_F15: |
| return "VK_F15"; |
| case VK_F16: |
| return "VK_F16"; |
| case VK_F17: |
| return "VK_F17"; |
| case VK_F18: |
| return "VK_F18"; |
| case VK_F19: |
| return "VK_F19"; |
| case VK_F20: |
| return "VK_F20"; |
| case VK_F21: |
| return "VK_F21"; |
| case VK_F22: |
| return "VK_F22"; |
| case VK_F23: |
| return "VK_F23"; |
| case VK_F24: |
| return "VK_F24"; |
| case VK_NUMLOCK: |
| return "VK_NUMLOCK"; |
| case VK_SCROLL: |
| return "VK_SCROLL"; |
| case VK_LSHIFT: |
| return "VK_LSHIFT"; |
| case VK_RSHIFT: |
| return "VK_RSHIFT"; |
| case VK_LCONTROL: |
| return "VK_LCONTROL"; |
| case VK_RCONTROL: |
| return "VK_RCONTROL"; |
| case VK_LMENU: |
| return "VK_LMENU"; |
| case VK_RMENU: |
| return "VK_RMENU"; |
| case VK_BROWSER_BACK: |
| return "VK_BROWSER_BACK"; |
| case VK_BROWSER_FORWARD: |
| return "VK_BROWSER_FORWARD"; |
| case VK_BROWSER_REFRESH: |
| return "VK_BROWSER_REFRESH"; |
| case VK_BROWSER_STOP: |
| return "VK_BROWSER_STOP"; |
| case VK_BROWSER_SEARCH: |
| return "VK_BROWSER_SEARCH"; |
| case VK_BROWSER_FAVORITES: |
| return "VK_BROWSER_FAVORITES"; |
| case VK_BROWSER_HOME: |
| return "VK_BROWSER_HOME"; |
| case VK_VOLUME_MUTE: |
| return "VK_VOLUME_MUTE"; |
| case VK_VOLUME_DOWN: |
| return "VK_VOLUME_DOWN"; |
| case VK_VOLUME_UP: |
| return "VK_VOLUME_UP"; |
| case VK_MEDIA_NEXT_TRACK: |
| return "VK_MEDIA_NEXT_TRACK"; |
| case VK_MEDIA_PREV_TRACK: |
| return "VK_MEDIA_PREV_TRACK"; |
| case VK_MEDIA_STOP: |
| return "VK_MEDIA_STOP"; |
| case VK_MEDIA_PLAY_PAUSE: |
| return "VK_MEDIA_PLAY_PAUSE"; |
| case VK_LAUNCH_MAIL: |
| return "VK_LAUNCH_MAIL"; |
| case VK_LAUNCH_MEDIA_SELECT: |
| return "VK_LAUNCH_MEDIA_SELECT"; |
| case VK_LAUNCH_APP1: |
| return "VK_LAUNCH_APP1"; |
| case VK_LAUNCH_APP2: |
| return "VK_LAUNCH_APP2"; |
| case VK_OEM_1: |
| return "VK_OEM_1"; |
| case VK_OEM_PLUS: |
| return "VK_OEM_PLUS"; |
| case VK_OEM_COMMA: |
| return "VK_OEM_COMMA"; |
| case VK_OEM_MINUS: |
| return "VK_OEM_MINUS"; |
| case VK_OEM_PERIOD: |
| return "VK_OEM_PERIOD"; |
| case VK_OEM_2: |
| return "VK_OEM_2"; |
| case VK_OEM_3: |
| return "VK_OEM_3"; |
| case VK_OEM_4: |
| return "VK_OEM_4"; |
| case VK_OEM_5: |
| return "VK_OEM_5"; |
| case VK_OEM_6: |
| return "VK_OEM_6"; |
| case VK_OEM_7: |
| return "VK_OEM_7"; |
| case VK_OEM_8: |
| return "VK_OEM_8"; |
| case VK_OEM_102: |
| return "VK_OEM_102"; |
| case VK_PROCESSKEY: |
| return "VK_PROCESSKEY"; |
| case VK_PACKET: |
| return "VK_PACKET"; |
| case VK_ATTN: |
| return "VK_ATTN"; |
| case VK_CRSEL: |
| return "VK_CRSEL"; |
| case VK_EXSEL: |
| return "VK_EXSEL"; |
| case VK_EREOF: |
| return "VK_EREOF"; |
| case VK_PLAY: |
| return "VK_PLAY"; |
| case VK_ZOOM: |
| return "VK_ZOOM"; |
| case VK_NONAME: |
| return "VK_NONAME"; |
| case VK_PA1: |
| return "VK_PA1"; |
| case VK_OEM_CLEAR: |
| return "VK_OEM_CLEAR"; |
| } |
| return "VK_UNKNOWN"; |
| } |
| #endif /* KEYBOARD_KEY_DEBUG */ |
| |
| int16_t |
| keycode_info_char_modifier(keycode_info_t *info, bool ctrl, bool shift) |
| { |
| if (ctrl && !shift && info->ctrlchar != -1) { |
| return info->ctrlchar; |
| } |
| return shift ? info->uppercase : info->ch; |
| } |
| |
| int16_t |
| keycode_info_char(keycode_state_t *s, keycode_info_t *info) |
| { |
| return keycode_info_char_modifier(info, s->keystate[VK_CONTROL], |
| s->keystate[VK_SHIFT] ^ s->caps_lock); |
| } |
| |
| int16_t |
| keycode_ps2_to_vkey(int32_t ps2_keycode) |
| { |
| if (ps2_keycode >= 0 && ps2_keycode < PS2_MAX_KEYCODES_BASIC) { |
| return ps2_to_vkey[ps2_keycode]; |
| } |
| /* Special case extended characters to avoid a large lookup table. */ |
| switch (ps2_keycode) { |
| case PS2_KEY_PRTSCR: |
| return VK_SNAPSHOT; |
| case PS2_KEY_PAUSE: |
| return VK_PAUSE; |
| case PS2_KEY_WINDOWS_LEFT: |
| return VK_LEFT; |
| case PS2_KEY_ALT_RIGHT: |
| return VK_MENU; |
| case PS2_KEY_WINDOWS_RIGHT: |
| return VK_RIGHT; |
| case PS2_KEY_MENUS: |
| return VK_MENU; |
| case PS2_KEY_INSERT: |
| return VK_INSERT; |
| case PS2_KEY_HOME: |
| return VK_HOME; |
| case PS2_KEY_PAGE_UP: |
| return VK_PRIOR; |
| case PS2_KEY_DELETE: |
| return VK_DELETE; |
| case PS2_KEY_END: |
| return VK_END; |
| case PS2_KEY_PAGE_DOWN: |
| return VK_NEXT; |
| case PS2_KEY_UP_ARROW: |
| return VK_UP; |
| case PS2_KEY_LEFT_ARROW: |
| return VK_LEFT; |
| case PS2_KEY_DOWN_ARROW: |
| return VK_DOWN; |
| case PS2_KEY_RIGHT_ARROW: |
| return VK_RIGHT; |
| case PS2_KEY_NUM_DIVIDE: |
| return VK_DIVIDE; |
| case PS2_KEY_NUM_ENTER: |
| return VK_RETURN; |
| } |
| return -1; |
| } |
| |
| static void |
| keycode_update_combined_vkeys(keycode_state_t *s) |
| { |
| s->keystate[VK_CONTROL] = s->keystate[VK_LCONTROL] || s->keystate[VK_RCONTROL]; |
| s->keystate[VK_SHIFT] = s->keystate[VK_LSHIFT] || s->keystate[VK_RSHIFT]; |
| } |
| |
| keycode_info_t * |
| keycode_process_vkey_event(keycode_state_t *s, int32_t vkey, bool pressed, void* cookie) |
| { |
| assert(s); |
| |
| if (vkey < 0) { |
| return NULL; |
| } |
| |
| s->keystate[VK_PAUSE] = false; |
| s->keystate[vkey] = pressed; |
| |
| keycode_update_combined_vkeys(s); |
| if (s->handle_keyevent_callback) { |
| s->handle_keyevent_callback(vkey, pressed, cookie); |
| } |
| |
| if (pressed) { |
| if (vkey == VK_CAPITAL) { |
| s->caps_lock = !s->caps_lock; |
| s->led_state_changed = true; |
| } |
| if (vkey == VK_SCROLL) { |
| s->scroll_lock = !s->scroll_lock; |
| s->led_state_changed = true; |
| } |
| if (vkey == VK_NUMLOCK) { |
| s->num_lock = !s->num_lock; |
| s->led_state_changed = true; |
| } |
| if (s->led_state_changed && s->handle_led_state_changed_callback) { |
| s->handle_led_state_changed_callback(cookie); |
| } |
| |
| int16_t typedc = keycode_info_char(s, &keycodes[vkey]); |
| if (typedc != -1 && s->handle_chartyped_callback) { |
| s->handle_chartyped_callback((int) typedc, cookie); |
| } |
| |
| return &keycodes[vkey]; |
| } |
| |
| return NULL; |
| } |
| |
| int16_t |
| keycode_process_vkey_event_to_char(keycode_state_t *s, int32_t vkey, bool pressed, void* cookie) |
| { |
| keycode_info_t *info = keycode_process_vkey_event(s, vkey, pressed, cookie); |
| return info ? keycode_info_char(s, info) : -1; |
| } |
| |
| bool |
| keycode_get_async_vkey_state(keycode_state_t *s, int32_t vkey) |
| { |
| assert(vkey >= 0 && vkey < VK_MAX_ENUM); |
| return s->keystate[vkey]; |
| } |