]> Joshua Wise's Git repositories - netwatch.git/blame - netwatch/keyboard.c
First pass of 410watch UI code.
[netwatch.git] / netwatch / keyboard.c
CommitLineData
3c4e084d
JP
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
e7804391 11#include "keyboard.h"
91cc1340
JP
12#include <stdint.h>
13#include <minilib.h>
e7804391
JW
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
db9fad13
JAW
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];
91cc1340
JP
43};
44
db9fad13
JAW
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};
91cc1340 142
db9fad13
JAW
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, { "", "" } }
e7804391
JW
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{
db9fad13
JAW
210 if (kbd_mode == 1) {
211 sc = sc_convert_1(sc);
212 if (!sc) return;
213 }
214
e7804391
JW
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
91cc1340 221void kbd_inject_keysym(uint32_t k, int downflag)
e7804391 222{
db9fad13
JAW
223 const struct keyspec * ks = 0;
224 const char * c = 0;
225 int i;
e7804391 226
db9fad13 227 if ((k & 0xFFFFFF00) == 0 && (k & 0xFF) > SC2_OFFSET)
91cc1340 228 {
db9fad13 229 ks = &scancodes2[SC2(k & 0xFF)];
91cc1340 230 } else if ((k & 0xFFFFFF00) == 0xFF00) {
db9fad13
JAW
231 for (i = 0; scancodes2high[i].index; i++) {
232 if ((k & 0xff) == scancodes2high[i].index) {
233 ks = &scancodes2high[i].data;
234 break;
235 }
236 }
91cc1340
JP
237 } else {
238 return;
239 }
240
db9fad13 241 if (!ks) return;
91cc1340 242
db9fad13
JAW
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');
e7804391
JW
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.04948 seconds and 4 git commands to generate.