Mercurial > sdl-ios-xcode
annotate src/video/fbcon/SDL_fbevents.c @ 4:4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
From: Alexander Pipelka <pipelka@bms-austria.com>
Subject: SDL ELO driver bugfix
Hi Sam!
We noticed that the ELO serial touchscreen controller is quite sensitive
in terms of correct protocol handling.
The current implementation cause some controllers to hangup after some
time (> 24h).
I think the attached patch should fix this (I ran my device more than 3
days without any hangups).
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:54:56 +0000 |
parents | 74212992fb08 |
children | b685c94f8db7 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@devolution.com | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Handle the event stream, converting console events into SDL events */ | |
29 | |
30 #include <sys/types.h> | |
31 #include <sys/time.h> | |
32 #include <sys/ioctl.h> | |
33 #include <stdlib.h> | |
34 #include <stdio.h> | |
35 #include <unistd.h> | |
36 #include <fcntl.h> | |
37 #include <string.h> | |
38 #include <errno.h> | |
39 #include <limits.h> | |
40 | |
41 /* For parsing /proc */ | |
42 #include <dirent.h> | |
43 #include <ctype.h> | |
44 | |
45 #include <linux/vt.h> | |
46 #include <linux/kd.h> | |
47 #include <linux/keyboard.h> | |
48 | |
49 #include "SDL.h" | |
50 #include "SDL_mutex.h" | |
51 #include "SDL_sysevents.h" | |
52 #include "SDL_sysvideo.h" | |
53 #include "SDL_events_c.h" | |
54 #include "SDL_fbvideo.h" | |
55 #include "SDL_fbevents_c.h" | |
56 #include "SDL_fbkeys.h" | |
57 | |
58 #include "SDL_fbelo.h" | |
59 | |
60 #ifndef GPM_NODE_FIFO | |
61 #define GPM_NODE_FIFO "/dev/gpmdata" | |
62 #endif | |
63 | |
64 | |
65 /* The translation tables from a console scancode to a SDL keysym */ | |
66 #define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) | |
67 static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; | |
68 static SDLKey keymap[128]; | |
69 static Uint16 keymap_temp[128]; /* only used at startup */ | |
70 static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); | |
71 | |
72 /* Ugh, we have to duplicate the kernel's keysym mapping code... | |
73 Oh, it's not so bad. :-) | |
74 | |
75 FIXME: Add keyboard LED handling code | |
76 */ | |
77 static void FB_vgainitkeymaps(int fd) | |
78 { | |
79 struct kbentry entry; | |
80 int map, i; | |
81 | |
82 /* Don't do anything if we are passed a closed keyboard */ | |
83 if ( fd < 0 ) { | |
84 return; | |
85 } | |
86 | |
87 /* Load all the keysym mappings */ | |
88 for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { | |
89 memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); | |
90 for ( i=0; i<NR_KEYS; ++i ) { | |
91 entry.kb_table = map; | |
92 entry.kb_index = i; | |
93 if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { | |
94 /* fill keytemp. This replaces SDL_fbkeys.h */ | |
95 if ( (map == 0) && (i<128) ) { | |
96 keymap_temp[i] = entry.kb_value; | |
97 } | |
98 /* The "Enter" key is a special case */ | |
99 if ( entry.kb_value == K_ENTER ) { | |
100 entry.kb_value = K(KT_ASCII,13); | |
101 } | |
102 /* Handle numpad specially as well */ | |
103 if ( KTYP(entry.kb_value) == KT_PAD ) { | |
104 switch ( entry.kb_value ) { | |
105 case K_P0: | |
106 case K_P1: | |
107 case K_P2: | |
108 case K_P3: | |
109 case K_P4: | |
110 case K_P5: | |
111 case K_P6: | |
112 case K_P7: | |
113 case K_P8: | |
114 case K_P9: | |
115 vga_keymap[map][i]=entry.kb_value; | |
116 vga_keymap[map][i]+= '0'; | |
117 break; | |
118 case K_PPLUS: | |
119 vga_keymap[map][i]=K(KT_ASCII,'+'); | |
120 break; | |
121 case K_PMINUS: | |
122 vga_keymap[map][i]=K(KT_ASCII,'-'); | |
123 break; | |
124 case K_PSTAR: | |
125 vga_keymap[map][i]=K(KT_ASCII,'*'); | |
126 break; | |
127 case K_PSLASH: | |
128 vga_keymap[map][i]=K(KT_ASCII,'/'); | |
129 break; | |
130 case K_PENTER: | |
131 vga_keymap[map][i]=K(KT_ASCII,'\r'); | |
132 break; | |
133 case K_PCOMMA: | |
134 vga_keymap[map][i]=K(KT_ASCII,','); | |
135 break; | |
136 case K_PDOT: | |
137 vga_keymap[map][i]=K(KT_ASCII,'.'); | |
138 break; | |
139 default: | |
140 break; | |
141 } | |
142 } | |
143 /* Do the normal key translation */ | |
144 if ( (KTYP(entry.kb_value) == KT_LATIN) || | |
145 (KTYP(entry.kb_value) == KT_ASCII) || | |
146 (KTYP(entry.kb_value) == KT_LETTER) ) { | |
147 vga_keymap[map][i] = entry.kb_value; | |
148 } | |
149 } | |
150 } | |
151 } | |
152 } | |
153 | |
154 int FB_InGraphicsMode(_THIS) | |
155 { | |
156 return((keyboard_fd >= 0) && (saved_kbd_mode >= 0)); | |
157 } | |
158 | |
159 int FB_EnterGraphicsMode(_THIS) | |
160 { | |
161 struct termios keyboard_termios; | |
162 | |
163 /* Set medium-raw keyboard mode */ | |
164 if ( (keyboard_fd >= 0) && !FB_InGraphicsMode(this) ) { | |
165 | |
166 /* Switch to the correct virtual terminal */ | |
167 if ( current_vt > 0 ) { | |
168 struct vt_stat vtstate; | |
169 | |
170 if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { | |
171 saved_vt = vtstate.v_active; | |
172 } | |
173 if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) { | |
174 ioctl(keyboard_fd, VT_WAITACTIVE, current_vt); | |
175 } | |
176 } | |
177 | |
178 /* Set the terminal input mode */ | |
179 if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) { | |
180 SDL_SetError("Unable to get terminal attributes"); | |
181 if ( keyboard_fd > 0 ) { | |
182 close(keyboard_fd); | |
183 } | |
184 keyboard_fd = -1; | |
185 return(-1); | |
186 } | |
187 if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) { | |
188 SDL_SetError("Unable to get current keyboard mode"); | |
189 if ( keyboard_fd > 0 ) { | |
190 close(keyboard_fd); | |
191 } | |
192 keyboard_fd = -1; | |
193 return(-1); | |
194 } | |
195 keyboard_termios = saved_kbd_termios; | |
196 keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG); | |
197 keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); | |
198 keyboard_termios.c_cc[VMIN] = 0; | |
199 keyboard_termios.c_cc[VTIME] = 0; | |
200 if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) { | |
201 FB_CloseKeyboard(this); | |
202 SDL_SetError("Unable to set terminal attributes"); | |
203 return(-1); | |
204 } | |
205 /* This will fail if we aren't root or this isn't our tty */ | |
206 if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) { | |
207 FB_CloseKeyboard(this); | |
208 SDL_SetError("Unable to set keyboard in raw mode"); | |
209 return(-1); | |
210 } | |
211 if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { | |
212 FB_CloseKeyboard(this); | |
213 SDL_SetError("Unable to set keyboard in graphics mode"); | |
214 return(-1); | |
215 } | |
216 } | |
217 return(keyboard_fd); | |
218 } | |
219 | |
220 void FB_LeaveGraphicsMode(_THIS) | |
221 { | |
222 if ( FB_InGraphicsMode(this) ) { | |
223 ioctl(keyboard_fd, KDSETMODE, KD_TEXT); | |
224 ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); | |
225 tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); | |
226 saved_kbd_mode = -1; | |
227 | |
228 /* Head back over to the original virtual terminal */ | |
229 if ( saved_vt > 0 ) { | |
230 ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); | |
231 } | |
232 } | |
233 } | |
234 | |
235 void FB_CloseKeyboard(_THIS) | |
236 { | |
237 if ( keyboard_fd >= 0 ) { | |
238 FB_LeaveGraphicsMode(this); | |
239 if ( keyboard_fd > 0 ) { | |
240 close(keyboard_fd); | |
241 } | |
242 } | |
243 keyboard_fd = -1; | |
244 } | |
245 | |
246 int FB_OpenKeyboard(_THIS) | |
247 { | |
248 /* Open only if not already opened */ | |
249 if ( keyboard_fd < 0 ) { | |
250 char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; | |
251 char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; | |
252 int i, tty0_fd; | |
253 | |
254 /* Try to query for a free virtual terminal */ | |
255 tty0_fd = -1; | |
256 for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { | |
257 tty0_fd = open(tty0[i], O_WRONLY, 0); | |
258 } | |
259 if ( tty0_fd < 0 ) { | |
260 tty0_fd = dup(0); /* Maybe stdin is a VT? */ | |
261 } | |
262 ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); | |
263 close(tty0_fd); | |
264 if ( (geteuid() == 0) && (current_vt > 0) ) { | |
265 for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { | |
266 char vtpath[12]; | |
267 | |
268 sprintf(vtpath, vcs[i], current_vt); | |
269 keyboard_fd = open(vtpath, O_RDWR, 0); | |
270 #ifdef DEBUG_KEYBOARD | |
271 fprintf(stderr, "vtpath = %s, fd = %d\n", | |
272 vtpath, keyboard_fd); | |
273 #endif /* DEBUG_KEYBOARD */ | |
274 | |
275 /* This needs to be our controlling tty | |
276 so that the kernel ioctl() calls work | |
277 */ | |
278 if ( keyboard_fd >= 0 ) { | |
279 tty0_fd = open("/dev/tty", O_RDWR, 0); | |
280 if ( tty0_fd >= 0 ) { | |
281 ioctl(tty0_fd, TIOCNOTTY, 0); | |
282 close(tty0_fd); | |
283 } | |
284 } | |
285 } | |
286 } | |
287 if ( keyboard_fd < 0 ) { | |
288 /* Last resort, maybe our tty is a usable VT */ | |
289 current_vt = 0; | |
290 keyboard_fd = open("/dev/tty", O_RDWR); | |
291 } | |
292 #ifdef DEBUG_KEYBOARD | |
293 fprintf(stderr, "Current VT: %d\n", current_vt); | |
294 #endif | |
295 saved_kbd_mode = -1; | |
296 | |
297 /* Make sure that our input is a console terminal */ | |
298 { int dummy; | |
299 if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { | |
300 close(keyboard_fd); | |
301 keyboard_fd = -1; | |
302 SDL_SetError("Unable to open a console terminal"); | |
303 } | |
304 } | |
305 | |
306 /* Set up keymap */ | |
307 FB_vgainitkeymaps(keyboard_fd); | |
308 } | |
309 return(keyboard_fd); | |
310 } | |
311 | |
312 static enum { | |
313 MOUSE_NONE = -1, | |
314 MOUSE_GPM, /* Note: GPM uses the MSC protocol */ | |
315 MOUSE_PS2, | |
316 MOUSE_IMPS2, | |
317 MOUSE_MS, | |
318 MOUSE_BM, | |
319 MOUSE_ELO, | |
320 NUM_MOUSE_DRVS | |
321 } mouse_drv = MOUSE_NONE; | |
322 | |
323 void FB_CloseMouse(_THIS) | |
324 { | |
325 if ( mouse_fd > 0 ) { | |
326 close(mouse_fd); | |
327 } | |
328 mouse_fd = -1; | |
329 } | |
330 | |
331 /* Returns processes listed in /proc with the desired name */ | |
332 static int find_pid(DIR *proc, const char *wanted_name) | |
333 { | |
334 struct dirent *entry; | |
335 int pid; | |
336 | |
337 /* First scan proc for the gpm process */ | |
338 pid = 0; | |
339 while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) { | |
340 if ( isdigit(entry->d_name[0]) ) { | |
341 FILE *status; | |
342 char path[PATH_MAX]; | |
343 char name[PATH_MAX]; | |
344 | |
345 sprintf(path, "/proc/%s/status", entry->d_name); | |
346 status=fopen(path, "r"); | |
347 if ( status ) { | |
348 name[0] = '\0'; | |
349 fscanf(status, "Name: %s", name); | |
350 if ( strcmp(name, wanted_name) == 0 ) { | |
351 pid = atoi(entry->d_name); | |
352 } | |
353 fclose(status); | |
354 } | |
355 } | |
356 } | |
357 return pid; | |
358 } | |
359 | |
360 /* Returns true if /dev/gpmdata is being written to by gpm */ | |
361 static int gpm_available(void) | |
362 { | |
363 int available; | |
364 DIR *proc; | |
365 int pid; | |
366 int cmdline, len, arglen; | |
367 char path[PATH_MAX]; | |
368 char args[PATH_MAX], *arg; | |
369 | |
370 /* Don't bother looking if the fifo isn't there */ | |
371 if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { | |
372 return(0); | |
373 } | |
374 | |
375 available = 0; | |
376 proc = opendir("/proc"); | |
377 if ( proc ) { | |
378 while ( (pid=find_pid(proc, "gpm")) > 0 ) { | |
379 sprintf(path, "/proc/%d/cmdline", pid); | |
380 cmdline = open(path, O_RDONLY, 0); | |
381 if ( cmdline >= 0 ) { | |
382 len = read(cmdline, args, sizeof(args)); | |
383 arg = args; | |
384 while ( len > 0 ) { | |
385 if ( strcmp(arg, "-R") == 0 ) { | |
386 available = 1; | |
387 } | |
388 arglen = strlen(arg)+1; | |
389 len -= arglen; | |
390 arg += arglen; | |
391 } | |
392 close(cmdline); | |
393 } | |
394 } | |
395 closedir(proc); | |
396 } | |
397 return available; | |
398 } | |
399 | |
400 /* Returns true if the mouse uses the IMPS/2 protocol */ | |
401 static int detect_imps2(int fd) | |
402 { | |
403 int imps2; | |
404 | |
405 imps2 = 0; | |
406 if ( getenv("SDL_MOUSEDEV_IMPS2") ) { | |
407 imps2 = 1; | |
408 } | |
409 if ( ! imps2 ) { | |
410 unsigned char query_ps2 = 0xF2; | |
411 fd_set fdset; | |
412 struct timeval tv; | |
413 | |
414 | |
415 /* Get rid of any mouse motion noise */ | |
416 FD_ZERO(&fdset); | |
417 FD_SET(fd, &fdset); | |
418 tv.tv_sec = 0; | |
419 tv.tv_usec = 0; | |
420 while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { | |
421 char temp[32]; | |
422 read(fd, temp, sizeof(temp)); | |
423 } | |
424 | |
425 /* Query for the type of mouse protocol */ | |
426 if ( write(fd, &query_ps2, 1) == 1 ) { | |
427 unsigned char ch = 0; | |
428 | |
429 /* If you wanted to control the mouse mode: | |
430 Set IMPS/2 protocol: | |
431 {0xf3,200,0xf3,100,0xf3,80} | |
432 Reset mouse device: | |
433 {0xFF} | |
434 */ | |
435 /* Get the mouse protocol response */ | |
436 do { | |
437 FD_ZERO(&fdset); | |
438 FD_SET(fd, &fdset); | |
439 tv.tv_sec = 1; | |
440 tv.tv_usec = 0; | |
441 if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) { | |
442 break; | |
443 } | |
444 } while ( (read(fd, &ch, 1) == 1) && | |
445 ((ch == 0xFA) || (ch == 0xAA)) ); | |
446 | |
447 /* Experimental values (Logitech wheelmouse) */ | |
448 #ifdef DEBUG_MOUSE | |
449 fprintf(stderr, "Last mouse mode: 0x%x\n", ch); | |
450 #endif | |
451 if ( ch == 3 ) { | |
452 imps2 = 1; | |
453 } | |
454 } | |
455 } | |
456 return imps2; | |
457 } | |
458 | |
459 int FB_OpenMouse(_THIS) | |
460 { | |
461 const char *mousedev; | |
462 const char *mousedrv; | |
463 | |
464 mousedrv = getenv("SDL_MOUSEDRV"); | |
465 mousedev = getenv("SDL_MOUSEDEV"); | |
466 mouse_fd = -1; | |
467 | |
468 /* ELO TOUCHSCREEN SUPPORT */ | |
469 | |
470 if( (mousedrv != NULL) && (strcmp(mousedrv, "ELO") == 0) ) { | |
471 mouse_fd = open(mousedev, O_RDWR); | |
472 if ( mouse_fd >= 0 ) { | |
473 if(eloInitController(mouse_fd)) { | |
474 #ifdef DEBUG_MOUSE | |
475 fprintf(stderr, "Using ELO touchscreen\n"); | |
476 #endif | |
477 mouse_drv = MOUSE_ELO; | |
478 } | |
479 | |
480 } | |
481 else if ( mouse_fd < 0 ) { | |
482 mouse_drv = MOUSE_NONE; | |
483 } | |
484 | |
485 return(mouse_fd); | |
486 } | |
487 | |
488 /* STD MICE */ | |
489 | |
490 if ( mousedev == NULL ) { | |
491 /* First try to use GPM in repeater mode */ | |
492 if ( mouse_fd < 0 ) { | |
493 if ( gpm_available() ) { | |
494 mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); | |
495 if ( mouse_fd >= 0 ) { | |
496 #ifdef DEBUG_MOUSE | |
497 fprintf(stderr, "Using GPM mouse\n"); | |
498 #endif | |
499 mouse_drv = MOUSE_GPM; | |
500 } | |
501 } | |
502 } | |
503 /* Now try to use the new HID unified mouse device */ | |
504 if ( mouse_fd < 0 ) { | |
505 mouse_fd = open("/dev/input/mice", O_RDONLY, 0); | |
506 if ( mouse_fd >= 0 ) { | |
507 mouse_drv = MOUSE_IMPS2; | |
508 } | |
509 } | |
510 /* Now try to use a modern PS/2 port mouse */ | |
511 if ( mouse_fd < 0 ) { | |
512 mouse_fd = open("/dev/psaux", O_RDWR, 0); | |
513 if ( mouse_fd < 0 ) { | |
514 mouse_fd = open("/dev/psaux", O_RDONLY, 0); | |
515 } | |
516 if ( mouse_fd >= 0 ) { | |
517 if ( detect_imps2(mouse_fd) ) { | |
518 #ifdef DEBUG_MOUSE | |
519 fprintf(stderr, "Using IMPS/2 mouse\n"); | |
520 #endif | |
521 mouse_drv = MOUSE_IMPS2; | |
522 } else { | |
523 #ifdef DEBUG_MOUSE | |
524 fprintf(stderr, "Using PS/2 mouse\n"); | |
525 #endif | |
526 mouse_drv = MOUSE_PS2; | |
527 } | |
528 } | |
529 } | |
530 /* Next try to use a PPC ADB port mouse */ | |
531 if ( mouse_fd < 0 ) { | |
532 mouse_fd = open("/dev/adbmouse", O_RDONLY, 0); | |
533 if ( mouse_fd >= 0 ) { | |
534 #ifdef DEBUG_MOUSE | |
535 fprintf(stderr, "Using ADB mouse\n"); | |
536 #endif | |
537 mouse_drv = MOUSE_BM; | |
538 } | |
539 } | |
540 } | |
541 /* Default to a serial Microsoft mouse */ | |
542 if ( mouse_fd < 0 ) { | |
543 if ( mousedev == NULL ) { | |
544 mousedev = "/dev/mouse"; | |
545 } | |
546 mouse_fd = open(mousedev, O_RDONLY, 0); | |
547 if ( mouse_fd >= 0 ) { | |
548 struct termios mouse_termios; | |
549 | |
550 /* Set the sampling speed to 1200 baud */ | |
551 tcgetattr(mouse_fd, &mouse_termios); | |
552 mouse_termios.c_iflag = IGNBRK | IGNPAR; | |
553 mouse_termios.c_oflag = 0; | |
554 mouse_termios.c_lflag = 0; | |
555 mouse_termios.c_line = 0; | |
556 mouse_termios.c_cc[VTIME] = 0; | |
557 mouse_termios.c_cc[VMIN] = 1; | |
558 mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL; | |
559 mouse_termios.c_cflag |= CS8; | |
560 mouse_termios.c_cflag |= B1200; | |
561 tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios); | |
562 #ifdef DEBUG_MOUSE | |
563 fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev); | |
564 #endif | |
565 mouse_drv = MOUSE_MS; | |
566 } | |
567 } | |
568 if ( mouse_fd < 0 ) { | |
569 mouse_drv = MOUSE_NONE; | |
570 } | |
571 return(mouse_fd); | |
572 } | |
573 | |
574 static int posted = 0; | |
575 | |
576 void FB_vgamousecallback(int button, int relative, int dx, int dy) | |
577 { | |
578 int button_1, button_3; | |
579 int button_state; | |
580 int state_changed; | |
581 int i; | |
582 Uint8 state; | |
583 | |
584 if ( dx || dy ) { | |
585 posted += SDL_PrivateMouseMotion(0, relative, dx, dy); | |
586 } | |
587 | |
588 /* Swap button 1 and 3 */ | |
589 button_1 = (button & 0x04) >> 2; | |
590 button_3 = (button & 0x01) << 2; | |
591 button &= ~0x05; | |
592 button |= (button_1|button_3); | |
593 | |
594 /* See what changed */ | |
595 button_state = SDL_GetMouseState(NULL, NULL); | |
596 state_changed = button_state ^ button; | |
597 for ( i=0; i<8; ++i ) { | |
598 if ( state_changed & (1<<i) ) { | |
599 if ( button & (1<<i) ) { | |
600 state = SDL_PRESSED; | |
601 } else { | |
602 state = SDL_RELEASED; | |
603 } | |
604 posted += SDL_PrivateMouseButton(state, i+1, 0, 0); | |
605 } | |
606 } | |
607 } | |
608 | |
609 /* For now, use GPM, PS/2, and MS protocols | |
610 Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.) | |
611 */ | |
612 static void handle_mouse(_THIS) | |
613 { | |
614 static int start = 0; | |
615 static unsigned char mousebuf[BUFSIZ]; | |
616 static int relative = 1; | |
617 | |
618 int i, nread; | |
619 int button = 0; | |
620 int dx = 0, dy = 0; | |
621 int packetsize = 0; | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
622 int realx, realy; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
623 |
0 | 624 /* Figure out the mouse packet size */ |
625 switch (mouse_drv) { | |
626 case MOUSE_NONE: | |
627 /* Ack! */ | |
628 read(mouse_fd, mousebuf, BUFSIZ); | |
629 return; | |
630 case MOUSE_GPM: | |
631 packetsize = 5; | |
632 break; | |
633 case MOUSE_IMPS2: | |
634 packetsize = 4; | |
635 break; | |
636 case MOUSE_PS2: | |
637 case MOUSE_MS: | |
638 case MOUSE_BM: | |
639 packetsize = 3; | |
640 break; | |
641 case MOUSE_ELO: | |
642 packetsize = ELO_PACKET_SIZE; | |
643 relative = 0; | |
644 break; | |
645 case NUM_MOUSE_DRVS: | |
646 /* Uh oh.. */ | |
647 packetsize = 0; | |
648 break; | |
649 } | |
650 | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
651 /* Special handling for the quite sensitive ELO controller */ |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
652 if (mouse_drv == MOUSE_ELO) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
653 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
654 /* try to read the next packet */ |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
655 if(eloReadPosition(this, mouse_fd, &dx, &dy, &button, &realx, &realy)) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
656 button = (button & 0x01) << 2; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
657 FB_vgamousecallback(button, relative, dx, dy); |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
658 } |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
659 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
660 return; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
661 } |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
662 |
0 | 663 /* Read as many packets as possible */ |
664 nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start); | |
665 if ( nread < 0 ) { | |
666 return; | |
667 } | |
668 nread += start; | |
669 #ifdef DEBUG_MOUSE | |
670 fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start); | |
671 #endif | |
672 for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) { | |
673 switch (mouse_drv) { | |
674 case MOUSE_NONE: | |
675 break; | |
676 case MOUSE_GPM: | |
677 /* GPM protocol has 0x80 in high byte */ | |
678 if ( (mousebuf[i] & 0xF8) != 0x80 ) { | |
679 /* Go to next byte */ | |
680 i -= (packetsize-1); | |
681 continue; | |
682 } | |
683 /* Get current mouse state */ | |
684 button = (~mousebuf[i]) & 0x07; | |
685 dx = (signed char)(mousebuf[i+1]) + | |
686 (signed char)(mousebuf[i+3]); | |
687 dy = -((signed char)(mousebuf[i+2]) + | |
688 (signed char)(mousebuf[i+4])); | |
689 break; | |
690 case MOUSE_PS2: | |
691 /* PS/2 protocol has nothing in high byte */ | |
692 if ( (mousebuf[i] & 0xC0) != 0 ) { | |
693 /* Go to next byte */ | |
694 i -= (packetsize-1); | |
695 continue; | |
696 } | |
697 /* Get current mouse state */ | |
698 button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ | |
699 (mousebuf[i] & 0x02) >> 1 | /*Right*/ | |
700 (mousebuf[i] & 0x01) << 2; /*Left*/ | |
701 dx = (mousebuf[i] & 0x10) ? | |
702 mousebuf[i+1] - 256 : mousebuf[i+1]; | |
703 dy = (mousebuf[i] & 0x20) ? | |
704 -(mousebuf[i+2] - 256) : -mousebuf[i+2]; | |
705 break; | |
706 case MOUSE_IMPS2: | |
707 /* Get current mouse state */ | |
708 button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ | |
709 (mousebuf[i] & 0x02) >> 1 | /*Right*/ | |
710 (mousebuf[i] & 0x01) << 2 | /*Left*/ | |
711 (mousebuf[i] & 0x40) >> 3 | /* 4 */ | |
712 (mousebuf[i] & 0x80) >> 3; /* 5 */ | |
713 dx = (mousebuf[i] & 0x10) ? | |
714 mousebuf[i+1] - 256 : mousebuf[i+1]; | |
715 dy = (mousebuf[i] & 0x20) ? | |
716 -(mousebuf[i+2] - 256) : -mousebuf[i+2]; | |
717 switch (mousebuf[i+3]&0x0F) { | |
718 case 0x0E: /* DX = +1 */ | |
719 case 0x02: /* DX = -1 */ | |
720 break; | |
721 case 0x0F: /* DY = +1 (map button 4) */ | |
722 button |= (1<<3); | |
723 break; | |
724 case 0x01: /* DY = -1 (map button 5) */ | |
725 button |= (1<<4); | |
726 break; | |
727 } | |
728 break; | |
729 case MOUSE_MS: | |
730 /* Microsoft protocol has 0x40 in high byte */ | |
731 if ( (mousebuf[i] & 0x40) != 0x40 ) { | |
732 /* Go to next byte */ | |
733 i -= (packetsize-1); | |
734 continue; | |
735 } | |
736 /* Get current mouse state */ | |
737 button = ((mousebuf[i] & 0x20) >> 3) | | |
738 ((mousebuf[i] & 0x10) >> 4); | |
739 dx = (signed char)(((mousebuf[i] & 0x03) << 6) | | |
740 (mousebuf[i + 1] & 0x3F)); | |
741 dy = (signed char)(((mousebuf[i] & 0x0C) << 4) | | |
742 (mousebuf[i + 2] & 0x3F)); | |
743 break; | |
744 case MOUSE_BM: | |
745 /* BusMouse protocol has 0xF8 in high byte */ | |
746 if ( (mousebuf[i] & 0xF8) != 0x80 ) { | |
747 /* Go to next byte */ | |
748 i -= (packetsize-1); | |
749 continue; | |
750 } | |
751 /* Get current mouse state */ | |
752 button = (~mousebuf[i]) & 0x07; | |
753 dx = (signed char)mousebuf[i+1]; | |
754 dy = -(signed char)mousebuf[i+2]; | |
755 break; | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
756 /* |
0 | 757 case MOUSE_ELO: |
758 if ( mousebuf[i] != ELO_START_BYTE ) { | |
759 i -= (packetsize-1); | |
760 continue; | |
761 } | |
762 | |
763 if(!eloParsePacket(&(mousebuf[i]), &dx, &dy, &button)) { | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
764 i -= (packetsize-1); |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
765 continue; |
0 | 766 } |
767 | |
768 button = (button & 0x01) << 2; | |
769 | |
770 eloConvertXY(this, &dx, &dy); | |
771 break; | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
772 */ |
0 | 773 |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
774 case MOUSE_ELO: |
0 | 775 case NUM_MOUSE_DRVS: |
776 /* Uh oh.. */ | |
777 dx = 0; | |
778 dy = 0; | |
779 break; | |
780 } | |
781 FB_vgamousecallback(button, relative, dx, dy); | |
782 } | |
783 if ( i < nread ) { | |
784 memcpy(mousebuf, &mousebuf[i], (nread-i)); | |
785 start = (nread-i); | |
786 } else { | |
787 start = 0; | |
788 } | |
789 return; | |
790 } | |
791 | |
792 /* Handle switching to another VC, returns when our VC is back */ | |
793 static void switch_vt(_THIS, unsigned short which) | |
794 { | |
795 struct vt_stat vtstate; | |
796 unsigned short current; | |
797 SDL_Surface *screen; | |
798 __u16 saved_pal[3*256]; | |
799 Uint32 screen_arealen; | |
800 Uint8 *screen_contents; | |
801 | |
802 /* Figure out whether or not we're switching to a new console */ | |
803 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || | |
804 (which == vtstate.v_active) ) { | |
805 return; | |
806 } | |
807 current = vtstate.v_active; | |
808 | |
809 /* Save the contents of the screen, and go to text mode */ | |
810 SDL_mutexP(hw_lock); | |
811 screen = SDL_VideoSurface; | |
812 screen_arealen = (screen->h*screen->pitch); | |
813 screen_contents = (Uint8 *)malloc(screen_arealen); | |
814 if ( screen_contents ) { | |
815 memcpy(screen_contents, screen->pixels, screen_arealen); | |
816 } | |
817 FB_SavePaletteTo(this, 256, saved_pal); | |
818 ioctl(keyboard_fd, KDSETMODE, KD_TEXT); | |
819 | |
820 /* New console, switch to it */ | |
821 if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { | |
822 /* Wait for our console to be activated again */ | |
823 ioctl(keyboard_fd, VT_WAITACTIVE, which); | |
824 while ( ioctl(keyboard_fd, VT_WAITACTIVE, current) < 0 ) { | |
825 if ( (errno != EINTR) && (errno != EAGAIN) ) { | |
826 /* Unknown VT error - cancel this */ | |
827 break; | |
828 } | |
829 SDL_Delay(500); | |
830 } | |
831 } | |
832 | |
833 /* Restore graphics mode and the contents of the screen */ | |
834 ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS); | |
835 FB_RestorePaletteFrom(this, 256, saved_pal); | |
836 if ( screen_contents ) { | |
837 memcpy(screen->pixels, screen_contents, screen_arealen); | |
838 free(screen_contents); | |
839 } | |
840 SDL_mutexV(hw_lock); | |
841 } | |
842 | |
843 static void handle_keyboard(_THIS) | |
844 { | |
845 unsigned char keybuf[BUFSIZ]; | |
846 int i, nread; | |
847 int pressed; | |
848 int scancode; | |
849 SDL_keysym keysym; | |
850 | |
851 nread = read(keyboard_fd, keybuf, BUFSIZ); | |
852 for ( i=0; i<nread; ++i ) { | |
853 scancode = keybuf[i] & 0x7F; | |
854 if ( keybuf[i] & 0x80 ) { | |
855 pressed = SDL_RELEASED; | |
856 } else { | |
857 pressed = SDL_PRESSED; | |
858 } | |
859 TranslateKey(scancode, &keysym); | |
860 /* Handle Alt-FN for vt switch */ | |
861 switch (keysym.sym) { | |
862 case SDLK_F1: | |
863 case SDLK_F2: | |
864 case SDLK_F3: | |
865 case SDLK_F4: | |
866 case SDLK_F5: | |
867 case SDLK_F6: | |
868 case SDLK_F7: | |
869 case SDLK_F8: | |
870 case SDLK_F9: | |
871 case SDLK_F10: | |
872 case SDLK_F11: | |
873 case SDLK_F12: | |
874 if ( SDL_GetModState() & KMOD_ALT ) { | |
875 switch_vt(this, (keysym.sym-SDLK_F1)+1); | |
876 break; | |
877 } | |
878 /* Fall through to normal processing */ | |
879 default: | |
880 posted += SDL_PrivateKeyboard(pressed, &keysym); | |
881 break; | |
882 } | |
883 } | |
884 } | |
885 | |
886 void FB_PumpEvents(_THIS) | |
887 { | |
888 fd_set fdset; | |
889 int max_fd; | |
890 static struct timeval zero; | |
891 | |
892 do { | |
893 posted = 0; | |
894 | |
895 FD_ZERO(&fdset); | |
896 max_fd = 0; | |
897 if ( keyboard_fd >= 0 ) { | |
898 FD_SET(keyboard_fd, &fdset); | |
899 if ( max_fd < keyboard_fd ) { | |
900 max_fd = keyboard_fd; | |
901 } | |
902 } | |
903 if ( mouse_fd >= 0 ) { | |
904 FD_SET(mouse_fd, &fdset); | |
905 if ( max_fd < mouse_fd ) { | |
906 max_fd = mouse_fd; | |
907 } | |
908 } | |
909 if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) { | |
910 if ( keyboard_fd >= 0 ) { | |
911 if ( FD_ISSET(keyboard_fd, &fdset) ) { | |
912 handle_keyboard(this); | |
913 } | |
914 } | |
915 if ( mouse_fd >= 0 ) { | |
916 if ( FD_ISSET(mouse_fd, &fdset) ) { | |
917 handle_mouse(this); | |
918 } | |
919 } | |
920 } | |
921 } while ( posted ); | |
922 } | |
923 | |
924 void FB_InitOSKeymap(_THIS) | |
925 { | |
926 int i; | |
927 | |
928 /* Initialize the Linux key translation table */ | |
929 | |
930 /* First get the ascii keys and others not well handled */ | |
931 for (i=0; i<SDL_TABLESIZE(keymap); ++i) { | |
932 switch(i) { | |
933 /* These aren't handled by the x86 kernel keymapping (?) */ | |
934 case SCANCODE_PRINTSCREEN: | |
935 keymap[i] = SDLK_PRINT; | |
936 break; | |
937 case SCANCODE_BREAK: | |
938 keymap[i] = SDLK_BREAK; | |
939 break; | |
940 case SCANCODE_BREAK_ALTERNATIVE: | |
941 keymap[i] = SDLK_PAUSE; | |
942 break; | |
943 case SCANCODE_LEFTSHIFT: | |
944 keymap[i] = SDLK_LSHIFT; | |
945 break; | |
946 case SCANCODE_RIGHTSHIFT: | |
947 keymap[i] = SDLK_RSHIFT; | |
948 break; | |
949 case SCANCODE_LEFTCONTROL: | |
950 keymap[i] = SDLK_LCTRL; | |
951 break; | |
952 case SCANCODE_RIGHTCONTROL: | |
953 keymap[i] = SDLK_RCTRL; | |
954 break; | |
955 case SCANCODE_RIGHTWIN: | |
956 keymap[i] = SDLK_RSUPER; | |
957 break; | |
958 case SCANCODE_LEFTWIN: | |
959 keymap[i] = SDLK_LSUPER; | |
960 break; | |
961 case 127: | |
962 keymap[i] = SDLK_MENU; | |
963 break; | |
964 /* this should take care of all standard ascii keys */ | |
965 default: | |
966 keymap[i] = KVAL(vga_keymap[0][i]); | |
967 break; | |
968 } | |
969 } | |
970 for (i=0; i<SDL_TABLESIZE(keymap); ++i) { | |
971 switch(keymap_temp[i]) { | |
972 case K_F1: keymap[i] = SDLK_F1; break; | |
973 case K_F2: keymap[i] = SDLK_F2; break; | |
974 case K_F3: keymap[i] = SDLK_F3; break; | |
975 case K_F4: keymap[i] = SDLK_F4; break; | |
976 case K_F5: keymap[i] = SDLK_F5; break; | |
977 case K_F6: keymap[i] = SDLK_F6; break; | |
978 case K_F7: keymap[i] = SDLK_F7; break; | |
979 case K_F8: keymap[i] = SDLK_F8; break; | |
980 case K_F9: keymap[i] = SDLK_F9; break; | |
981 case K_F10: keymap[i] = SDLK_F10; break; | |
982 case K_F11: keymap[i] = SDLK_F11; break; | |
983 case K_F12: keymap[i] = SDLK_F12; break; | |
984 | |
985 case K_DOWN: keymap[i] = SDLK_DOWN; break; | |
986 case K_LEFT: keymap[i] = SDLK_LEFT; break; | |
987 case K_RIGHT: keymap[i] = SDLK_RIGHT; break; | |
988 case K_UP: keymap[i] = SDLK_UP; break; | |
989 | |
990 case K_P0: keymap[i] = SDLK_KP0; break; | |
991 case K_P1: keymap[i] = SDLK_KP1; break; | |
992 case K_P2: keymap[i] = SDLK_KP2; break; | |
993 case K_P3: keymap[i] = SDLK_KP3; break; | |
994 case K_P4: keymap[i] = SDLK_KP4; break; | |
995 case K_P5: keymap[i] = SDLK_KP5; break; | |
996 case K_P6: keymap[i] = SDLK_KP6; break; | |
997 case K_P7: keymap[i] = SDLK_KP7; break; | |
998 case K_P8: keymap[i] = SDLK_KP8; break; | |
999 case K_P9: keymap[i] = SDLK_KP9; break; | |
1000 case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break; | |
1001 case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break; | |
1002 case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break; | |
1003 case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break; | |
1004 case K_PENTER: keymap[i] = SDLK_KP_ENTER; break; | |
1005 case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break; | |
1006 | |
1007 case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT ) | |
1008 keymap[i] = SDLK_LSHIFT; | |
1009 break; | |
1010 case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break; | |
1011 case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break; | |
1012 case K_CTRL: if ( keymap[i] != SDLK_RCTRL ) | |
1013 keymap[i] = SDLK_LCTRL; | |
1014 break; | |
1015 case K_CTRLL: keymap[i] = SDLK_LCTRL; break; | |
1016 case K_CTRLR: keymap[i] = SDLK_RCTRL; break; | |
1017 case K_ALT: keymap[i] = SDLK_LALT; break; | |
1018 case K_ALTGR: keymap[i] = SDLK_RALT; break; | |
1019 | |
1020 case K_INSERT: keymap[i] = SDLK_INSERT; break; | |
1021 case K_REMOVE: keymap[i] = SDLK_DELETE; break; | |
1022 case K_PGUP: keymap[i] = SDLK_PAGEUP; break; | |
1023 case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break; | |
1024 case K_FIND: keymap[i] = SDLK_HOME; break; | |
1025 case K_SELECT: keymap[i] = SDLK_END; break; | |
1026 | |
1027 case K_NUM: keymap[i] = SDLK_NUMLOCK; break; | |
1028 case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break; | |
1029 | |
1030 case K_F13: keymap[i] = SDLK_PRINT; break; | |
1031 case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break; | |
1032 case K_PAUSE: keymap[i] = SDLK_PAUSE; break; | |
1033 | |
1034 case 127: keymap[i] = SDLK_BACKSPACE; break; | |
1035 | |
1036 default: break; | |
1037 } | |
1038 } | |
1039 } | |
1040 | |
1041 static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) | |
1042 { | |
1043 /* Set the keysym information */ | |
1044 keysym->scancode = scancode; | |
1045 keysym->sym = keymap[scancode]; | |
1046 keysym->mod = KMOD_NONE; | |
1047 | |
1048 /* If UNICODE is on, get the UNICODE value for the key */ | |
1049 keysym->unicode = 0; | |
1050 if ( SDL_TranslateUNICODE ) { | |
1051 int map; | |
1052 SDLMod modstate; | |
1053 | |
1054 modstate = SDL_GetModState(); | |
1055 map = 0; | |
1056 if ( modstate & KMOD_SHIFT ) { | |
1057 map |= (1<<KG_SHIFT); | |
1058 } | |
1059 if ( modstate & KMOD_CTRL ) { | |
1060 map |= (1<<KG_CTRL); | |
1061 } | |
1062 if ( modstate & KMOD_ALT ) { | |
1063 map |= (1<<KG_ALT); | |
1064 } | |
1065 if ( modstate & KMOD_MODE ) { | |
1066 map |= (1<<KG_ALTGR); | |
1067 } | |
1068 if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { | |
1069 if ( modstate & KMOD_CAPS ) { | |
1070 map ^= (1<<KG_SHIFT); | |
1071 } | |
1072 } | |
1073 if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { | |
1074 if ( modstate & KMOD_NUM ) { | |
1075 keysym->unicode=KVAL(vga_keymap[map][scancode]); | |
1076 } | |
1077 } else { | |
1078 keysym->unicode = KVAL(vga_keymap[map][scancode]); | |
1079 } | |
1080 } | |
1081 return(keysym); | |
1082 } |