source: mainline/uspace/srv/kbd/arch/arm32/src/kbd_gxemul.c@ 00acd66

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 00acd66 was 00acd66, checked in by Jakub Jermar <jakub@…>, 18 years ago

New, better-structured, directory layout for uspace.

  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 * Copyright (c) 2007 Michal Kebrt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kbdarm32gxemul GXemul
30 * @brief HelenOS arm32 GXEmul uspace keyboard handler.
31 * @ingroup kbdarm32
32 * @{
33 */
34/** @file
35 * @brief GXemul uspace keyboard handler.
36 */
37
38#include <ipc/ipc.h>
39#include <sysinfo.h>
40#include <kbd.h>
41#include <keys.h>
42#include <bool.h>
43
44
45/* GXemul key codes in no-framebuffer mode. */
46#define GXEMUL_KEY_F1 0x504f1bL
47#define GXEMUL_KEY_F2 0x514f1bL
48#define GXEMUL_KEY_F3 0x524f1bL
49#define GXEMUL_KEY_F4 0x534f1bL
50#define GXEMUL_KEY_F5 0x35315b1bL
51#define GXEMUL_KEY_F6 0x37315b1bL
52#define GXEMUL_KEY_F7 0x38315b1bL
53#define GXEMUL_KEY_F8 0x39315b1bL
54#define GXEMUL_KEY_F9 0x30325b1bL
55#define GXEMUL_KEY_F10 0x31325b1bL
56#define GXEMUL_KEY_F11 0x33325d1bL
57#define GXEMUL_KEY_F12 0x34325b1bL
58
59/** Start code of F5-F12 keys. */
60#define GXEMUL_KEY_F5_F12_START_CODE 0x7e
61
62/* GXemul key codes in framebuffer mode. */
63#define GXEMUL_FB_KEY_F1 0x504f5b1bL
64#define GXEMUL_FB_KEY_F2 0x514f5b1bL
65#define GXEMUL_FB_KEY_F3 0x524f5b1bL
66#define GXEMUL_FB_KEY_F4 0x534f5b1bL
67#define GXEMUL_FB_KEY_F5 0x35315b1bL
68#define GXEMUL_FB_KEY_F6 0x37315b1bL
69#define GXEMUL_FB_KEY_F7 0x38315b1bL
70#define GXEMUL_FB_KEY_F8 0x39315b1bL
71#define GXEMUL_FB_KEY_F9 0x38325b1bL
72#define GXEMUL_FB_KEY_F10 0x39325b1bL
73#define GXEMUL_FB_KEY_F11 0x33325b1bL
74#define GXEMUL_FB_KEY_F12 0x34325b1bL
75
76
77/** Function keys start code (F1=0x101) */
78#define FUNCTION_KEYS 0x100
79
80static irq_cmd_t gxemul_cmds[] = {
81 {
82 CMD_MEM_READ_1,
83 (void *) 0,
84 0,
85 2
86 }
87};
88
89static irq_code_t gxemul_kbd = {
90 1,
91 gxemul_cmds
92};
93
94
95/** Framebuffer switched on. */
96static bool fb;
97
98
99/*
100// Please preserve this code (it can be used to determine scancodes)
101int to_hex(int v)
102{
103 return "0123456789ABCDEF"[v];
104}
105*/
106
107
108/** Process data sent when a key is pressed (in no-framebuffer mode).
109 *
110 * @param keybuffer Buffer of pressed key.
111 * @param scan_code Scan code.
112 *
113 * @return Always 1.
114 */
115static int gxemul_kbd_process_no_fb(keybuffer_t *keybuffer, int scan_code)
116{
117 // holds at most 4 latest scan codes
118 static unsigned long buf = 0;
119
120 // number of scan codes in #buf
121 static int count = 0;
122
123 /*
124 // Preserve for detecting scan codes.
125 keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
126 keybuffer_push(keybuffer, to_hex(scan_code&0xf));
127 keybuffer_push(keybuffer, 'X');
128 keybuffer_push(keybuffer, 'Y');
129 return 1;
130 */
131
132 if (scan_code == '\r') {
133 scan_code = '\n';
134 }
135
136 if (scan_code == GXEMUL_KEY_F5_F12_START_CODE) {
137 switch (buf) {
138 case GXEMUL_KEY_F5:
139 keybuffer_push(keybuffer,FUNCTION_KEYS | 5);
140 buf = count = 0;
141 return 1;
142 case GXEMUL_KEY_F6:
143 keybuffer_push(keybuffer,FUNCTION_KEYS | 6);
144 buf = count = 0;
145 return 1;
146 case GXEMUL_KEY_F7:
147 keybuffer_push(keybuffer,FUNCTION_KEYS | 7);
148 buf = count = 0;
149 return 1;
150 case GXEMUL_KEY_F8:
151 keybuffer_push(keybuffer,FUNCTION_KEYS | 8);
152 buf = count = 0;
153 return 1;
154 case GXEMUL_KEY_F9:
155 keybuffer_push(keybuffer,FUNCTION_KEYS | 9);
156 buf = count = 0;
157 return 1;
158 case GXEMUL_KEY_F10:
159 keybuffer_push(keybuffer,FUNCTION_KEYS | 10);
160 buf = count = 0;
161 return 1;
162 case GXEMUL_KEY_F11:
163 keybuffer_push(keybuffer,FUNCTION_KEYS | 11);
164 buf = count = 0;
165 return 1;
166 case GXEMUL_KEY_F12:
167 keybuffer_push(keybuffer,FUNCTION_KEYS | 12);
168 buf = count = 0;
169 return 1;
170 default:
171 keybuffer_push(keybuffer, buf & 0xff);
172 keybuffer_push(keybuffer, (buf >> 8) & 0xff);
173 keybuffer_push(keybuffer, (buf >> 16) & 0xff);
174 keybuffer_push(keybuffer, (buf >> 24) & 0xff);
175 keybuffer_push(keybuffer, scan_code);
176 buf = count = 0;
177 return 1;
178 }
179 }
180
181 // add to buffer
182 buf |= ((unsigned long) scan_code) << (8 * (count++));
183
184 if ((buf & 0xff) != (GXEMUL_KEY_F1 & 0xff)) {
185 keybuffer_push(keybuffer, buf);
186 buf = count = 0;
187 return 1;
188 }
189
190 if (count <= 1) {
191 return 1;
192 }
193
194 if ((buf & 0xffff) != (GXEMUL_KEY_F1 & 0xffff)
195 && (buf & 0xffff) != (GXEMUL_KEY_F5 & 0xffff) ) {
196
197 keybuffer_push(keybuffer, buf & 0xff);
198 keybuffer_push(keybuffer, (buf >> 8) &0xff);
199 buf = count = 0;
200 return 1;
201 }
202
203 if (count <= 2) {
204 return 1;
205 }
206
207 switch (buf) {
208 case GXEMUL_KEY_F1:
209 keybuffer_push(keybuffer,FUNCTION_KEYS | 1);
210 buf = count = 0;
211 return 1;
212 case GXEMUL_KEY_F2:
213 keybuffer_push(keybuffer,FUNCTION_KEYS | 2);
214 buf = count = 0;
215 return 1;
216 case GXEMUL_KEY_F3:
217 keybuffer_push(keybuffer,FUNCTION_KEYS | 3);
218 buf = count = 0;
219 return 1;
220 case GXEMUL_KEY_F4:
221 keybuffer_push(keybuffer,FUNCTION_KEYS | 4);
222 buf = count = 0;
223 return 1;
224 }
225
226
227 if ((buf & 0xffffff) != (GXEMUL_KEY_F5 & 0xffffff)
228 && (buf & 0xffffff) != (GXEMUL_KEY_F9 & 0xffffff)) {
229
230 keybuffer_push(keybuffer, buf & 0xff);
231 keybuffer_push(keybuffer, (buf >> 8) & 0xff);
232 keybuffer_push(keybuffer, (buf >> 16) & 0xff);
233 buf = count = 0;
234 return 1;
235 }
236
237 if (count <= 3) {
238 return 1;
239 }
240
241 switch (buf) {
242 case GXEMUL_KEY_F5:
243 case GXEMUL_KEY_F6:
244 case GXEMUL_KEY_F7:
245 case GXEMUL_KEY_F8:
246 case GXEMUL_KEY_F9:
247 case GXEMUL_KEY_F10:
248 case GXEMUL_KEY_F11:
249 case GXEMUL_KEY_F12:
250 return 1;
251 default:
252 keybuffer_push(keybuffer, buf & 0xff);
253 keybuffer_push(keybuffer, (buf >> 8) & 0xff);
254 keybuffer_push(keybuffer, (buf >> 16) & 0xff);
255 keybuffer_push(keybuffer, (buf >> 24) & 0xff);
256 buf = count = 0;
257 return 1;
258 }
259
260 return 1;
261}
262
263
264/** Process data sent when a key is pressed (in framebuffer mode).
265 *
266 * @param keybuffer Buffer of pressed keys.
267 * @param scan_code Scan code.
268 *
269 * @return Always 1.
270 */
271static int gxemul_kbd_process_fb(keybuffer_t *keybuffer, int scan_code)
272{
273 // holds at most 4 latest scan codes
274 static unsigned long buf = 0;
275
276 // number of scan codes in #buf
277 static int count = 0;
278
279 /*
280 // Please preserve this code (it can be used to determine scancodes)
281 keybuffer_push(keybuffer, to_hex((scan_code>>4)&0xf));
282 keybuffer_push(keybuffer, to_hex(scan_code&0xf));
283 keybuffer_push(keybuffer, ' ');
284 keybuffer_push(keybuffer, ' ');
285 return 1;
286 */
287
288 if (scan_code == '\r') {
289 scan_code = '\n';
290 }
291
292 // add to buffer
293 buf |= ((unsigned long) scan_code) << (8*(count++));
294
295
296 if ((buf & 0xff) != (GXEMUL_FB_KEY_F1 & 0xff)) {
297 keybuffer_push(keybuffer, buf);
298 buf = count = 0;
299 return 1;
300 }
301
302 if (count <= 1) {
303 return 1;
304 }
305
306 if ((buf & 0xffff) != (GXEMUL_FB_KEY_F1 & 0xffff)) {
307 keybuffer_push(keybuffer, buf & 0xff);
308 keybuffer_push(keybuffer, (buf >> 8) &0xff);
309 buf = count = 0;
310 return 1;
311 }
312
313 if (count <= 2) {
314 return 1;
315 }
316
317 if ((buf & 0xffffff) != (GXEMUL_FB_KEY_F1 & 0xffffff)
318 && (buf & 0xffffff) != (GXEMUL_FB_KEY_F5 & 0xffffff)
319 && (buf & 0xffffff) != (GXEMUL_FB_KEY_F9 & 0xffffff)) {
320
321 keybuffer_push(keybuffer, buf & 0xff);
322 keybuffer_push(keybuffer, (buf >> 8) & 0xff);
323 keybuffer_push(keybuffer, (buf >> 16) & 0xff);
324 buf = count = 0;
325 return 1;
326 }
327
328 if (count <= 3) {
329 return 1;
330 }
331
332 switch (buf) {
333 case GXEMUL_FB_KEY_F1:
334 keybuffer_push(keybuffer,FUNCTION_KEYS | 1 );
335 buf = count = 0;
336 return 1;
337 case GXEMUL_FB_KEY_F2:
338 keybuffer_push(keybuffer,FUNCTION_KEYS | 2 );
339 buf = count = 0;
340 return 1;
341 case GXEMUL_FB_KEY_F3:
342 keybuffer_push(keybuffer,FUNCTION_KEYS | 3 );
343 buf = count = 0;
344 return 1;
345 case GXEMUL_FB_KEY_F4:
346 keybuffer_push(keybuffer,FUNCTION_KEYS | 4 );
347 buf = count = 0;
348 return 1;
349 case GXEMUL_FB_KEY_F5:
350 keybuffer_push(keybuffer,FUNCTION_KEYS | 5 );
351 buf = count = 0;
352 return 1;
353 case GXEMUL_FB_KEY_F6:
354 keybuffer_push(keybuffer,FUNCTION_KEYS | 6 );
355 buf = count = 0;
356 return 1;
357 case GXEMUL_FB_KEY_F7:
358 keybuffer_push(keybuffer,FUNCTION_KEYS | 7 );
359 buf = count = 0;
360 return 1;
361 case GXEMUL_FB_KEY_F8:
362 keybuffer_push(keybuffer,FUNCTION_KEYS | 8 );
363 buf = count = 0;
364 return 1;
365 case GXEMUL_FB_KEY_F9:
366 keybuffer_push(keybuffer,FUNCTION_KEYS | 9 );
367 buf = count = 0;
368 return 1;
369 case GXEMUL_FB_KEY_F10:
370 keybuffer_push(keybuffer,FUNCTION_KEYS | 10 );
371 buf = count = 0;
372 return 1;
373 case GXEMUL_FB_KEY_F11:
374 keybuffer_push(keybuffer,FUNCTION_KEYS | 11 );
375 buf = count = 0;
376 return 1;
377 case GXEMUL_FB_KEY_F12:
378 keybuffer_push(keybuffer,FUNCTION_KEYS | 12 );
379 buf = count = 0;
380 return 1;
381 default:
382 keybuffer_push(keybuffer, buf & 0xff );
383 keybuffer_push(keybuffer, (buf >> 8) & 0xff);
384 keybuffer_push(keybuffer, (buf >> 16) & 0xff);
385 keybuffer_push(keybuffer, (buf >> 24) & 0xff);
386 buf = count = 0;
387 return 1;
388 }
389
390 return 1;
391}
392
393
394/** Initializes keyboard handler. */
395int kbd_arch_init(void)
396{
397 fb = (sysinfo_value("fb.kind") == 1);
398 gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
399 ipc_register_irq(sysinfo_value("kbd.inr"), sysinfo_value("kbd.devno"), 0, &gxemul_kbd);
400 return 0;
401}
402
403
404/** Process data sent when a key is pressed.
405 *
406 * @param keybuffer Buffer of pressed keys.
407 * @param call IPC call.
408 *
409 * @return Always 1.
410 */
411int kbd_arch_process(keybuffer_t *keybuffer, ipc_call_t *call)
412{
413 int scan_code = IPC_GET_ARG2(*call);
414
415 if (fb) {
416 return gxemul_kbd_process_fb(keybuffer, scan_code);
417 } else {
418 return gxemul_kbd_process_no_fb(keybuffer, scan_code);
419 }
420
421}
422
423/** @}
424 */
Note: See TracBrowser for help on using the repository browser.