2 * Keyboard scan code conversion and injection.
3 * NetWatch system management mode administration console
5 * Copyright (c) 2008 Jacob Potter and Joshua Wise. All rights reserved.
6 * This program is free software; you can redistribute and/or modify it under
7 * the terms found in the file LICENSE in the root of this source tree.
16 static unsigned char kbd_inj_buffer[128];
17 static int kbd_inj_start = 0;
18 static int kbd_inj_end = 0;
21 /* To save space, we don't store the first 32 characters in scancodes2, since
22 * they're control characters. Thus, the offset is the amount to subtract
23 * from a character before looking it up. */
26 #define SC2(x) ((x)-SC2_OFFSET)
28 /* Keys are stored in somewhat compressed form, to save on data space.
30 * The "press" and "release" strings contain scancodes to be injected
31 * into the buffer. However, they are modified beforehand, since two
32 * bytes isn't enough for all keys.
35 * - If press starts with \x12 (shift down), then \xf0\x12 (shift up)
36 * will be appended to release.
37 * - If press starts with \xe0, then \xe0 is *pre*pended to release.
45 static const struct keyspec scancodes2[] = {
46 [SC2('a')] = { "\x1c", "\xf0\x1c" },
47 [SC2('b')] = { "\x32", "\xf0\x32" },
48 [SC2('c')] = { "\x21", "\xf0\x21" },
49 [SC2('d')] = { "\x23", "\xf0\x23" },
50 [SC2('e')] = { "\x24", "\xf0\x24" },
51 [SC2('f')] = { "\x2b", "\xf0\x2b" },
52 [SC2('g')] = { "\x34", "\xf0\x34" },
53 [SC2('h')] = { "\x33", "\xf0\x33" },
54 [SC2('i')] = { "\x43", "\xf0\x43" },
55 [SC2('j')] = { "\x3b", "\xf0\x3b" },
56 [SC2('k')] = { "\x42", "\xf0\x42" },
57 [SC2('l')] = { "\x4b", "\xf0\x4b" },
58 [SC2('m')] = { "\x3a", "\xf0\x3a" },
59 [SC2('n')] = { "\x31", "\xf0\x31" },
60 [SC2('o')] = { "\x44", "\xf0\x44" },
61 [SC2('p')] = { "\x4d", "\xf0\x4d" },
62 [SC2('q')] = { "\x15", "\xf0\x15" },
63 [SC2('r')] = { "\x2d", "\xf0\x2d" },
64 [SC2('s')] = { "\x1b", "\xf0\x1b" },
65 [SC2('t')] = { "\x2c", "\xf0\x2c" },
66 [SC2('u')] = { "\x3c", "\xf0\x3c" },
67 [SC2('v')] = { "\x2a", "\xf0\x2a" },
68 [SC2('w')] = { "\x1d", "\xf0\x1d" },
69 [SC2('x')] = { "\x22", "\xf0\x22" },
70 [SC2('y')] = { "\x35", "\xf0\x35" },
71 [SC2('z')] = { "\x1a", "\xf0\x1a" },
72 [SC2('A')] = { "\x12\x1c", "\xf0\x1c" },
73 [SC2('B')] = { "\x12\x32", "\xf0\x32" },
74 [SC2('C')] = { "\x12\x21", "\xf0\x21" },
75 [SC2('D')] = { "\x12\x23", "\xf0\x23" },
76 [SC2('E')] = { "\x12\x24", "\xf0\x24" },
77 [SC2('F')] = { "\x12\x2b", "\xf0\x2b" },
78 [SC2('G')] = { "\x12\x34", "\xf0\x34" },
79 [SC2('H')] = { "\x12\x33", "\xf0\x33" },
80 [SC2('I')] = { "\x12\x43", "\xf0\x43" },
81 [SC2('J')] = { "\x12\x3b", "\xf0\x3b" },
82 [SC2('K')] = { "\x12\x42", "\xf0\x42" },
83 [SC2('L')] = { "\x12\x4b", "\xf0\x4b" },
84 [SC2('M')] = { "\x12\x3a", "\xf0\x3a" },
85 [SC2('N')] = { "\x12\x31", "\xf0\x31" },
86 [SC2('O')] = { "\x12\x44", "\xf0\x44" },
87 [SC2('P')] = { "\x12\x4d", "\xf0\x4d" },
88 [SC2('Q')] = { "\x12\x15", "\xf0\x15" },
89 [SC2('R')] = { "\x12\x2d", "\xf0\x2d" },
90 [SC2('S')] = { "\x12\x1b", "\xf0\x1b" },
91 [SC2('T')] = { "\x12\x2c", "\xf0\x2c" },
92 [SC2('U')] = { "\x12\x3c", "\xf0\x3c" },
93 [SC2('V')] = { "\x12\x2a", "\xf0\x2a" },
94 [SC2('W')] = { "\x12\x1d", "\xf0\x1d" },
95 [SC2('X')] = { "\x12\x22", "\xf0\x22" },
96 [SC2('Y')] = { "\x12\x35", "\xf0\x35" },
97 [SC2('Z')] = { "\x12\x1a", "\xf0\x1a" },
98 [SC2('`')] = { "\x0e", "\xf0\x0e" },
99 [SC2('~')] = { "\x12\x0e", "\xf0\x0e" },
100 [SC2('1')] = { "\x16", "\xf0\x16" },
101 [SC2('!')] = { "\x12\x16", "\xf0\x16" },
102 [SC2('2')] = { "\x1e", "\xf0\x1e" },
103 [SC2('@')] = { "\x12\x1e", "\xf0\x1e" },
104 [SC2('3')] = { "\x26", "\xf0\x26" },
105 [SC2('#')] = { "\x12\x26", "\xf0\x26" },
106 [SC2('4')] = { "\x25", "\xf0\x25" },
107 [SC2('$')] = { "\x12\x25", "\xf0\x25" },
108 [SC2('5')] = { "\x2e", "\xf0\x2e" },
109 [SC2('%')] = { "\x12\x2e", "\xf0\x2e" },
110 [SC2('6')] = { "\x36", "\xf0\x36" },
111 [SC2('^')] = { "\x12\x36", "\xf0\x36" },
112 [SC2('7')] = { "\x3d", "\xf0\x3d" },
113 [SC2('&')] = { "\x12\x3d", "\xf0\x3d" },
114 [SC2('8')] = { "\x3e", "\xf0\x3e" },
115 [SC2('*')] = { "\x12\x3e", "\xf0\x3e" },
116 [SC2('9')] = { "\x46", "\xf0\x46" },
117 [SC2('(')] = { "\x12\x46", "\xf0\x46" },
118 [SC2('0')] = { "\x45", "\xf0\x45" },
119 [SC2(')')] = { "\x12\x45", "\xf0\x45" },
120 [SC2('-')] = { "\x4e", "\xf0\x4e" },
121 [SC2('_')] = { "\x12\x4e", "\xf0\x4e" },
122 [SC2('=')] = { "\x55", "\xf0\x55" },
123 [SC2('+')] = { "\x12\x55", "\xf0\x55" },
124 [SC2('[')] = { "\x54", "\xf0\x54" },
125 [SC2('{')] = { "\x12\x54", "\xf0\x54" },
126 [SC2(']')] = { "\x5b", "\xf0\x5b" },
127 [SC2('}')] = { "\x12\x5b", "\xf0\x5b" },
128 [SC2('\\')] = { "\x5d", "\xf0\x5d" },
129 [SC2('|')] = { "\x12\x5d", "\xf0\x5d" },
130 [SC2(';')] = { "\x4c", "\xf0\x4c" },
131 [SC2(':')] = { "\x12\x4c", "\xf0\x4c" },
132 [SC2('\'')] = { "\x52", "\xf0\x52" },
133 [SC2('"')] = { "\x12\x52", "\xf0\x52" },
134 [SC2(',')] = { "\x41", "\xf0\x41" },
135 [SC2('<')] = { "\x12\x41", "\xf0\x41" },
136 [SC2('.')] = { "\x49", "\xf0\x49" },
137 [SC2('>')] = { "\x12\x49", "\xf0\x49" },
138 [SC2('/')] = { "\x4a", "\xf0\x4a" },
139 [SC2(' ')] = { "\x29", "\xf0\x29" },
140 [SC2('?')] = { "\x12\x4a", "\xf0\x4a" }
143 static const struct {
146 } scancodes2high[] = {
147 { 0x08, { "\x66", "\xf0\x66" } },
148 { 0x09, { "\x0d", "\xf0\x0d" } },
149 { 0x0d, { "\x5a", "\xf0\x5a" } },
150 { 0x1b, { "\x76", "\xf0\x76" } },
151 { 0x63, { "\xe0\x70", "\xF0\x70" } },
152 { 0xff, { "\xe0\x71", "\xF0\x71" } },
153 { 0x50, { "\xe0\x6C", "\xF0\x6C" } },
154 { 0x57, { "\xe0\x69", "\xF0\x69" } },
155 { 0x55, { "\xe0\x75", "\xF0\x75" } },
156 { 0x56, { "\xe0\x7A", "\xF0\x7A" } },
157 { 0x51, { "\xe0\x74", "\xF0\x74" } },
158 { 0x52, { "\xe0\x75", "\xF0\x75" } },
159 { 0x53, { "\xe0\x6B", "\xF0\x6B" } },
160 { 0x54, { "\xe0\x72", "\xF0\x72" } },
161 { 0xe1, { "\x12", "" } },
162 { 0xe2, { "\x59", "\xf0\x59" } },
163 { 0xe3, { "\x14", "\xf0\x14" } },
164 { 0xe4, { "\xe0\x14", "\xF0\x14" } },
165 { 0xe9, { "\x11", "\xf0\x11" } },
166 { 0xea, { "\xe0\x11", "\xF0\x11" } },
170 const unsigned char convert_table[] = {
171 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
172 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
173 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
174 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
175 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
176 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
177 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
178 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
179 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
180 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
181 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
182 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
183 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
184 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
185 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
186 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
189 unsigned char sc_convert_1(unsigned char in)
191 static int shifted = 0;
196 return convert_table[in] | 0x80;
204 return convert_table[in];
208 void kbd_inject_scancode (unsigned char sc)
211 sc = sc_convert_1(sc);
215 outputf("Buffering %02x", sc);
216 kbd_inj_buffer[kbd_inj_end] = sc;
218 kbd_inj_end %= sizeof(kbd_inj_buffer);
221 void kbd_inject_keysym(uint32_t k, int downflag)
223 const struct keyspec * ks = 0;
227 if ((k & 0xFFFFFF00) == 0 && (k & 0xFF) > SC2_OFFSET)
229 ks = &scancodes2[SC2(k & 0xFF)];
230 } else if ((k & 0xFFFFFF00) == 0xFF00) {
231 for (i = 0; scancodes2high[i].index; i++) {
232 if ((k & 0xff) == scancodes2high[i].index) {
233 ks = &scancodes2high[i].data;
250 if (ks->press[0] == '\xe0' && !downflag)
251 kbd_inject_scancode('\xe0');
253 while (*c && i < 2) {
254 kbd_inject_scancode(*c);
259 if (ks->press[0] == '\x12' && !downflag) {
260 kbd_inject_scancode('\xf0');
261 kbd_inject_scancode('\x12');
265 unsigned char kbd_get_injected_scancode()
269 if (kbd_inj_end != kbd_inj_start)
271 b = kbd_inj_buffer[kbd_inj_start];
273 kbd_inj_start %= sizeof(kbd_inj_buffer);
274 outputf("Injecting %02x", b);
277 outputf("Not injecting");
282 int kbd_has_injected_scancode()
284 if (kbd_inj_end != kbd_inj_start)