]> Joshua Wise's Git repositories - netwatch.git/blame_incremental - netwatch/keyboard.c
First pass of 410watch UI code.
[netwatch.git] / netwatch / keyboard.c
... / ...
CommitLineData
1/* keyboard.c
2 * Keyboard scan code conversion and injection.
3 * NetWatch system management mode administration console
4 *
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.
8 *
9 */
10
11#include "keyboard.h"
12#include <stdint.h>
13#include <minilib.h>
14#include <output.h>
15
16static unsigned char kbd_inj_buffer[128];
17static int kbd_inj_start = 0;
18static int kbd_inj_end = 0;
19int kbd_mode = 1;
20
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. */
24
25#define SC2_OFFSET 32
26#define SC2(x) ((x)-SC2_OFFSET)
27
28/* Keys are stored in somewhat compressed form, to save on data space.
29 *
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.
33 *
34 * Rules:
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.
38 */
39
40struct keyspec {
41 char press[2];
42 char release[2];
43};
44
45static 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" }
141};
142
143static const struct {
144 char index;
145 struct keyspec data;
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" } },
167 { 0x00, { "", "" } }
168};
169
170const 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
187};
188
189unsigned char sc_convert_1(unsigned char in)
190{
191 static int shifted = 0;
192
193 if (shifted)
194 {
195 shifted = 0;
196 return convert_table[in] | 0x80;
197 }
198
199 if (in == 0xF0)
200 {
201 shifted = 1;
202 return 0;
203 } else {
204 return convert_table[in];
205 }
206}
207
208void kbd_inject_scancode (unsigned char sc)
209{
210 if (kbd_mode == 1) {
211 sc = sc_convert_1(sc);
212 if (!sc) return;
213 }
214
215 outputf("Buffering %02x", sc);
216 kbd_inj_buffer[kbd_inj_end] = sc;
217 kbd_inj_end += 1;
218 kbd_inj_end %= sizeof(kbd_inj_buffer);
219}
220
221void kbd_inject_keysym(uint32_t k, int downflag)
222{
223 const struct keyspec * ks = 0;
224 const char * c = 0;
225 int i;
226
227 if ((k & 0xFFFFFF00) == 0 && (k & 0xFF) > SC2_OFFSET)
228 {
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;
234 break;
235 }
236 }
237 } else {
238 return;
239 }
240
241 if (!ks) return;
242
243 if (downflag)
244 c = ks->press;
245 else
246 c = ks->release;
247
248 i = 0;
249
250 if (ks->press[0] == '\xe0' && !downflag)
251 kbd_inject_scancode('\xe0');
252
253 while (*c && i < 2) {
254 kbd_inject_scancode(*c);
255 c++;
256 i++;
257 }
258
259 if (ks->press[0] == '\x12' && !downflag) {
260 kbd_inject_scancode('\xf0');
261 kbd_inject_scancode('\x12');
262 }
263}
264
265unsigned char kbd_get_injected_scancode()
266{
267 unsigned char b;
268
269 if (kbd_inj_end != kbd_inj_start)
270 {
271 b = kbd_inj_buffer[kbd_inj_start];
272 kbd_inj_start += 1;
273 kbd_inj_start %= sizeof(kbd_inj_buffer);
274 outputf("Injecting %02x", b);
275 return b;
276 } else {
277 outputf("Not injecting");
278 return 0;
279 }
280}
281
282int kbd_has_injected_scancode()
283{
284 if (kbd_inj_end != kbd_inj_start)
285 {
286 return 1;
287 } else {
288 return 0;
289 }
290}
This page took 0.029402 seconds and 4 git commands to generate.