]> Joshua Wise's Git repositories - netwatch.git/blob - netwatch/keyboard.c
First pass of 410watch UI code.
[netwatch.git] / netwatch / keyboard.c
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
16 static unsigned char kbd_inj_buffer[128];
17 static int kbd_inj_start = 0;
18 static int kbd_inj_end = 0;
19 int 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
40 struct keyspec {
41         char press[2];
42         char release[2];
43 };
44
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" }
141 };
142
143 static 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
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
187 };
188
189 unsigned 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
208 void 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
221 void 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
265 unsigned 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
282 int 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.036017 seconds and 4 git commands to generate.