1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#pragma once
14
15#include <stdint.h>
16#include <stdbool.h>
17
18#define VK_MAX_ENUM 0xFF
19#define PS2_MAX_KEYCODES_BASIC 0xFF
20
21#define KEYBOARD_KEY_DEBUG false
22
23typedef struct keycode_info {
24    int16_t ch;
25    int16_t uppercase;
26    int16_t ctrlchar;
27} keycode_info_t;
28
29typedef struct keycode_state {
30    bool keystate[VK_MAX_ENUM];
31
32    bool scroll_lock;
33    bool num_lock;
34    bool caps_lock;
35    bool led_state_changed;
36
37    /* Optional callback, called when a vkey has been pressed or released. */
38    void (*handle_keyevent_callback)(int16_t vkey, bool pressed, void *cookie);
39    /* Optional callback, called when a character has been typed. */
40    void (*handle_chartyped_callback)(int c, void *cookie);
41    /* Optional callback, called when num/scroll/caps lock LED state has changed. */
42    void (*handle_led_state_changed_callback)(void *cookie);
43
44} keycode_state_t;
45
46/* ref:
47        http://nehe.gamedev.net/article/msdn_virtualkey_codes/15009/
48        http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
49*/
50enum virtual_keycode_enum {
51    VK_LBUTTON = 0x1 ,  /* Left mouse button */
52    VK_RBUTTON = 0x2 ,  /* Right mouse button */
53    VK_CANCEL = 0x3 ,  /* Control-break processing */
54    VK_MBUTTON = 0x4 ,  /* Middle mouse button (three-button mouse) */
55    VK_XBUTTON1 = 0x5 ,  /*  X1 mouse button */
56    VK_XBUTTON2 = 0x6 ,  /*  X2 mouse button */
57    VK_BACK = 0x8 ,  /* BACKSPACE key */
58    VK_TAB = 0x9 ,  /* TAB key */
59    VK_CLEAR = 0x0C,  /* CLEAR key */
60    VK_RETURN = 0x0D,  /* ENTER key */
61    VK_CONTROL = 0x11,  /* CTRL key */
62    VK_SHIFT = 0x10,  /* SHIFT key */
63    VK_MENU = 0x12,  /* ALT key */
64    VK_PAUSE = 0x13,  /* PAUSE key */
65    VK_CAPITAL = 0x14,  /* CAPS LOCK key */
66    VK_KANA = 0x15,  /* IME Kana mode */
67    VK_HANGUEL = 0x15,  /* IME Hanguel mode (maintained for compatibility; use VK_HANGUL) */
68    VK_HANGUL = 0x15,  /* IME Hangul mode */
69    VK_JUNJA = 0x17,  /* IME Junja mode */
70    VK_FINAL = 0x18,  /* IME final mode */
71    VK_HANJA = 0x19,  /* IME Hanja mode */
72    VK_KANJI = 0x19,  /* IME Kanji mode */
73    VK_ESCAPE = 0x1B,  /* ESC key */
74    VK_CONVERT = 0x1C,  /* IME convert */
75    VK_NONCONVERT = 0x1D,  /* IME nonconvert */
76    VK_ACCEPT = 0x1E,  /* IME accept */
77    VK_MODECHANGE = 0x1F,  /* IME mode change request */
78    VK_SPACE = 0x20,  /* SPACEBAR */
79    VK_PRIOR = 0x21,  /* PAGE UP key */
80    VK_NEXT = 0x22,  /* PAGE DOWN key */
81    VK_END = 0x23,  /* END key */
82    VK_HOME = 0x24,  /* HOME key */
83    VK_LEFT = 0x25,  /* LEFT ARROW key */
84    VK_UP = 0x26,  /* UP ARROW key */
85    VK_RIGHT = 0x27,  /* RIGHT ARROW key */
86    VK_DOWN = 0x28,  /* DOWN ARROW key */
87    VK_SELECT = 0x29,  /* SELECT key */
88    VK_PRINT = 0x2A,  /* PRINT key */
89    VK_EXECUTE = 0x2B,  /* EXECUTE key */
90    VK_SNAPSHOT = 0x2C,  /* PRINT SCREEN key */
91    VK_INSERT = 0x2D,  /* INS key */
92    VK_DELETE = 0x2E,  /* DEL key */
93    VK_HELP = 0x2F,  /* HELP key */
94    VK_0 = 0x30,  /* 0 key */
95    VK_1 = 0x31,  /* 1 key */
96    VK_2 = 0x32,  /* 2 key */
97    VK_3 = 0x33,  /* 3 key */
98    VK_4 = 0x34,  /* 4 key */
99    VK_5 = 0x35,  /* 5 key */
100    VK_6 = 0x36,  /* 6 key */
101    VK_7 = 0x37,  /* 7 key */
102    VK_8 = 0x38,  /* 8 key */
103    VK_9 = 0x39,  /* 9 key */
104    VK_A = 0x41,  /* A key */
105    VK_B = 0x42,  /* B key */
106    VK_C = 0x43,  /* C key */
107    VK_D = 0x44,  /* D key */
108    VK_E = 0x45,  /* E key */
109    VK_F = 0x46,  /* F key */
110    VK_G = 0x47,  /* G key */
111    VK_H = 0x48,  /* H key */
112    VK_I = 0x49,  /* I key */
113    VK_J = 0x4A,  /* J key */
114    VK_K = 0x4B,  /* K key */
115    VK_L = 0x4C,  /* L key */
116    VK_M = 0x4D,  /* M key */
117    VK_N = 0x4E,  /* N key */
118    VK_O = 0x4F,  /* O key */
119    VK_P = 0x50,  /* P key */
120    VK_Q = 0x51,  /* Q key */
121    VK_R = 0x52,  /* R key */
122    VK_S = 0x53,  /* S key */
123    VK_T = 0x54,  /* T key */
124    VK_U = 0x55,  /* U key */
125    VK_V = 0x56,  /* V key */
126    VK_W = 0x57,  /* W key */
127    VK_X = 0x58,  /* X key */
128    VK_Y = 0x59,  /* Y key */
129    VK_Z = 0x5A,  /* Z key */
130    VK_LWIN = 0x5B,  /* Left Windows key (Microsoft Natural Keyboard) */
131    VK_RWIN = 0x5C,  /* Right Windows key (Microsoft Natural Keyboard) */
132    VK_APPS = 0x5D,  /* Applications key (Microsoft Natural Keyboard) */
133    VK_SLEEP = 0x5F,  /* Computer Sleep key */
134    VK_NUMPAD0 = 0x60,  /* Numeric keypad 0 key */
135    VK_NUMPAD1 = 0x61,  /* Numeric keypad 1 key */
136    VK_NUMPAD2 = 0x62,  /* Numeric keypad 2 key */
137    VK_NUMPAD3 = 0x63,  /* Numeric keypad 3 key */
138    VK_NUMPAD4 = 0x64,  /* Numeric keypad 4 key */
139    VK_NUMPAD5 = 0x65,  /* Numeric keypad 5 key */
140    VK_NUMPAD6 = 0x66,  /* Numeric keypad 6 key */
141    VK_NUMPAD7 = 0x67,  /* Numeric keypad 7 key */
142    VK_NUMPAD8 = 0x68,  /* Numeric keypad 8 key */
143    VK_NUMPAD9 = 0x69,  /* Numeric keypad 9 key */
144    VK_MULTIPLY = 0x6A,  /* Multiply key */
145    VK_ADD = 0x6B,  /* Add key */
146    VK_SEPARATOR = 0x6C,  /* Separator key */
147    VK_SUBTRACT = 0x6D,  /* Subtract key */
148    VK_DECIMAL = 0x6E,  /* Decimal key */
149    VK_DIVIDE = 0x6F,  /* Divide key */
150    VK_F1 = 0x70,  /* F1 key */
151    VK_F2 = 0x71,  /* F2 key */
152    VK_F3 = 0x72,  /* F3 key */
153    VK_F4 = 0x73,  /* F4 key */
154    VK_F5 = 0x74,  /* F5 key */
155    VK_F6 = 0x75,  /* F6 key */
156    VK_F7 = 0x76,  /* F7 key */
157    VK_F8 = 0x77,  /* F8 key */
158    VK_F9 = 0x78,  /* F9 key */
159    VK_F10 = 0x79,  /* F10 key */
160    VK_F11 = 0x7A,  /* F11 key */
161    VK_F12 = 0x7B,  /* F12 key */
162    VK_F13 = 0x7C,  /* F13 key */
163    VK_F14 = 0x7D,  /* F14 key */
164    VK_F15 = 0x7E,  /* F15 key */
165    VK_F16 = 0x7F,  /* F16 key */
166    VK_F17 = 0x80,  /* F17 key */
167    VK_F18 = 0x81,  /* F18 key */
168    VK_F19 = 0x82,  /* F19 key */
169    VK_F20 = 0x83,  /* F20 key */
170    VK_F21 = 0x84,  /* F21 key */
171    VK_F22 = 0x85,  /* F22 key */
172    VK_F23 = 0x86,  /* F23 key */
173    VK_F24 = 0x87,  /* F24 key */
174    VK_NUMLOCK = 0x90,  /* NUM LOCK key */
175    VK_SCROLL = 0x91,  /* SCROLL LOCK key */
176    VK_LSHIFT = 0xA0,  /* Left SHIFT key */
177    VK_RSHIFT = 0xA1,  /* Right SHIFT key */
178    VK_LCONTROL = 0xA2,  /* Left CONTROL key */
179    VK_RCONTROL = 0xA3,  /* Right CONTROL key */
180    VK_LMENU = 0xA4,  /* Left MENU key */
181    VK_RMENU = 0xA5,  /* Right MENU key */
182    VK_BROWSER_BACK = 0xA6,  /*  Browser Back key */
183    VK_BROWSER_FORWARD = 0xA7,  /*  Browser Forward key */
184    VK_BROWSER_REFRESH = 0xA8,  /*  Browser Refresh key */
185    VK_BROWSER_STOP = 0xA9,  /*  Browser Stop key */
186    VK_BROWSER_SEARCH = 0xAA,  /*  Browser Search key */
187    VK_BROWSER_FAVORITES = 0xAB,  /*  Browser Favorites key */
188    VK_BROWSER_HOME = 0xAC,  /*  Browser Launch and Home key */
189    VK_VOLUME_MUTE = 0xAD,  /*  Volume Mute key */
190    VK_VOLUME_DOWN = 0xAE,  /*  Volume Down key */
191    VK_VOLUME_UP = 0xAF,  /*  Volume Up key */
192    VK_MEDIA_NEXT_TRACK = 0xB0,  /*  Next Track key */
193    VK_MEDIA_PREV_TRACK = 0xB1,  /*  Previous Track key */
194    VK_MEDIA_STOP = 0xB2,  /*  Stop Media key */
195    VK_MEDIA_PLAY_PAUSE = 0xB3,  /*  Play/Pause Media key */
196    VK_LAUNCH_MAIL = 0xB4,  /*  Launch Mail key */
197    VK_LAUNCH_MEDIA_SELECT = 0xB5,  /*  Select Media key */
198    VK_LAUNCH_APP1 = 0xB6,  /*  Launch Application 1 key */
199    VK_LAUNCH_APP2 = 0xB7,  /*  Launch Application 2 key */
200    VK_OEM_1 = 0xBA,  /*  For the US standard keyboard, the ';:' key */
201    VK_OEM_PLUS = 0xBB,  /*  For any country/region, the '+' key */
202    VK_OEM_COMMA = 0xBC,  /*  For any country/region, the ',' key */
203    VK_OEM_MINUS = 0xBD,  /*  For any country/region, the '-' key */
204    VK_OEM_PERIOD = 0xBE,  /*  For any country/region, the '.' key */
205    VK_OEM_2 = 0xBF,  /*  For the US standard keyboard, the '/?' key */
206    VK_OEM_3 = 0xC0,  /*  For the US standard keyboard, the '`~' key */
207    VK_OEM_4 = 0xDB,  /*  For the US standard keyboard, the '[{' key */
208    VK_OEM_5 = 0xDC,  /*  For the US standard keyboard, the '\|' key */
209    VK_OEM_6 = 0xDD,  /*  For the US standard keyboard, the ']}' key */
210    VK_OEM_7 = 0xDE,  /*  For the US standard keyboard, the 'single-quote/double-quote' key */
211    VK_OEM_8 = 0xDF,  /* �� */
212    VK_OEM_102 = 0xE2,  /*  either the '<>' key or the '\|' key on the RT 102-key keyboard */
213    VK_PROCESSKEY = 0xE5,  /* Windows 95, Windows NT 4.0, and  IME PROCESS key */
214    VK_PACKET = 0xE7,  /*  Used to pass Unicode characters as if they were keystrokes. */
215    VK_ATTN = 0xF6,  /* Attn key */
216    VK_CRSEL = 0xF7,  /* CrSel key */
217    VK_EXSEL = 0xF8,  /* ExSel key */
218    VK_EREOF = 0xF9,  /* Erase EOF key */
219    VK_PLAY = 0xFA,  /* Play key */
220    VK_ZOOM = 0xFB,  /* Zoom key */
221    VK_NONAME = 0xFC,  /* Reserved for future use */
222    VK_PA1 = 0xFD,  /* PA1 key */
223    VK_OEM_CLEAR = 0xFE  /* Clear key */
224};
225
226/* ref: http://techdocs.altium.com/display/FPGA/PS2+Keyboard+Scan+Codes */
227enum ps2_keycode_scanmode2_enum {
228    PS2_KEY_ESC = 0x76,
229    PS2_KEY_F1 = 0x05,
230    PS2_KEY_F2 = 0x06,
231    PS2_KEY_F3 = 0x04,
232    PS2_KEY_F4 = 0x0C,
233    PS2_KEY_F5 = 0x03,
234    PS2_KEY_F6 = 0x0B,
235    PS2_KEY_F7 = 0x83,
236    PS2_KEY_F8 = 0x0A,
237    PS2_KEY_F9 = 0x01,
238    PS2_KEY_F10 = 0x09,
239    PS2_KEY_F11 = 0x78,
240    PS2_KEY_F12 = 0x07,
241    PS2_KEY_SCROLL_LOCK = 0x7E,
242    PS2_KEY_TILDE = 0x0E,
243    PS2_KEY_1 = 0x16,
244    PS2_KEY_2 = 0x1E,
245    PS2_KEY_3 = 0x26,
246    PS2_KEY_4 = 0x25,
247    PS2_KEY_5 = 0x2E,
248    PS2_KEY_6 = 0x36,
249    PS2_KEY_7 = 0x3D,
250    PS2_KEY_8 = 0x3E,
251    PS2_KEY_9 = 0x46,
252    PS2_KEY_0 = 0x45,
253    PS2_KEY_SUBTRACT = 0x4E,
254    PS2_KEY_EQUALS = 0x55,
255    PS2_KEY_BACKSPACE = 0x66,
256    PS2_KEY_TAB = 0x0D,
257    PS2_KEY_Q = 0x15,
258    PS2_KEY_W = 0x1D,
259    PS2_KEY_E = 0x24,
260    PS2_KEY_R = 0x2D,
261    PS2_KEY_T = 0x2C,
262    PS2_KEY_Y = 0x35,
263    PS2_KEY_U = 0x3C,
264    PS2_KEY_I = 0x43,
265    PS2_KEY_O = 0x44,
266    PS2_KEY_P = 0x4D,
267    PS2_KEY_LBRACKET = 0x54,
268    PS2_KEY_RBRACKET = 0x5B,
269    PS2_KEY_BACKSLASH = 0x5D,
270    PS2_KEY_CAPS_LOCK = 0x58,
271    PS2_KEY_A = 0x1C,
272    PS2_KEY_S = 0x1B,
273    PS2_KEY_D = 0x23,
274    PS2_KEY_F = 0x2B,
275    PS2_KEY_G = 0x34,
276    PS2_KEY_H = 0x33,
277    PS2_KEY_J = 0x3B,
278    PS2_KEY_K = 0x42,
279    PS2_KEY_L = 0x4B,
280    PS2_KEY_COLON = 0x4C,
281    PS2_KEY_TICK = 0x52,
282    PS2_KEY_ENTER = 0x5A,
283    PS2_KEY_SHIFT_LEFT = 0x12,
284    PS2_KEY_Z = 0x1A,
285    PS2_KEY_X = 0x22,
286    PS2_KEY_C = 0x21,
287    PS2_KEY_V = 0x2A,
288    PS2_KEY_B = 0x32,
289    PS2_KEY_N = 0x31,
290    PS2_KEY_M = 0x3A,
291    PS2_KEY_COMMA = 0x41,
292    PS2_KEY_DOT = 0x49,
293    PS2_KEY_SLASH = 0x4A,
294    PS2_KEY_SHIFT_RIGHT = 0x59,
295    PS2_KEY_CTRL_LEFT = 0x14,
296    PS2_KEY_ALT_LEFT = 0x11,
297    PS2_KEY_SPACEBAR = 0x29,
298    PS2_KEY_NUM_LOCK = 0x77,
299    PS2_KEY_NUM_MULTIPLY = 0x7C,
300    PS2_KEY_NUM_MINUS = 0x7B,
301    PS2_KEY_NUM_7 = 0x6C,
302    PS2_KEY_NUM_8 = 0x75,
303    PS2_KEY_NUM_9 = 0x7D,
304    PS2_KEY_NUM_PLUS = 0x79,
305    PS2_KEY_NUM_4 = 0x6B,
306    PS2_KEY_NUM_5 = 0x73,
307    PS2_KEY_NUM_6 = 0x74,
308    PS2_KEY_NUM_1 = 0x69,
309    PS2_KEY_NUM_2 = 0x72,
310    PS2_KEY_NUM_3 = 0x7A,
311    PS2_KEY_NUM_0 = 0x70,
312    PS2_KEY_NUM_DOT = 0x71,
313
314    PS2_KEY_PRTSCR = 0xE012, /* 0xE012E07C */
315    PS2_KEY_PAUSE = 0xE114, /* 0xE11477E1F014E077 */
316    PS2_KEY_WINDOWS_LEFT = 0xE01F,
317    PS2_KEY_ALT_RIGHT = 0xE011,
318    PS2_KEY_WINDOWS_RIGHT = 0xE027,
319    PS2_KEY_MENUS = 0xE02F,
320    PS2_KEY_CTRL_RIGHT = 0xE014,
321    PS2_KEY_INSERT = 0xE070,
322    PS2_KEY_HOME = 0xE06C,
323    PS2_KEY_PAGE_UP = 0xE07D,
324    PS2_KEY_DELETE = 0xE071,
325    PS2_KEY_END = 0xE069,
326    PS2_KEY_PAGE_DOWN = 0xE07A,
327    PS2_KEY_UP_ARROW = 0xE075,
328    PS2_KEY_LEFT_ARROW = 0xE06B,
329    PS2_KEY_DOWN_ARROW = 0xE072,
330    PS2_KEY_RIGHT_ARROW = 0xE074,
331    PS2_KEY_NUM_DIVIDE = 0xE04A,
332    PS2_KEY_NUM_ENTER = 0xE05A
333};
334
335/* All callbacks are optional, set to NULL if don't care. */
336void keycode_init(
337    keycode_state_t *s,
338    void (*handle_keyevent_callback)(int16_t vkey, bool pressed, void *cookie),
339    void (*handle_chartyped_callback)(int c, void *cookie),
340    void (*handle_led_state_changed_callback)(void *cookie)
341);
342
343#if KEYBOARD_KEY_DEBUG
344const char* keycode_vkey_desc(uint16_t vk);
345#endif
346
347int16_t keycode_info_char_modifier(keycode_info_t *info, bool ctrl, bool shift);
348
349int16_t keycode_info_char(keycode_state_t *s, keycode_info_t *info);
350
351int16_t keycode_ps2_to_vkey(int32_t ps2_keycode);
352
353keycode_info_t *keycode_process_vkey_event(keycode_state_t *s, int32_t vkey, bool pressed,
354                                           void* cookie);
355
356int16_t keycode_process_vkey_event_to_char(keycode_state_t *s, int32_t vkey, bool pressed,
357                                           void* cookie);
358
359bool keycode_get_async_vkey_state(keycode_state_t *s, int32_t vkey);
360
361