comparison src/video/ps2gs/SDL_gsevents.c @ 70:f590dd383b5d

Added Linux PlayStation 2 Graphics Synthesizer support
author Sam Lantinga <slouken@lokigames.com>
date Sat, 16 Jun 2001 03:17:45 +0000
parents
children 2604a7be65af
comparison
equal deleted inserted replaced
69:280ff3af2ecc 70:f590dd383b5d
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_gsvideo.h"
55 #include "SDL_gsevents_c.h"
56 #include "SDL_gskeys.h"
57
58 #ifndef GPM_NODE_FIFO
59 #define GPM_NODE_FIFO "/dev/gpmdata"
60 #endif
61
62 /* The translation tables from a console scancode to a SDL keysym */
63 #define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT)
64 static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
65 static SDLKey keymap[128];
66 static Uint16 keymap_temp[128]; /* only used at startup */
67 static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);
68
69 /* Ugh, we have to duplicate the kernel's keysym mapping code...
70 Oh, it's not so bad. :-)
71
72 FIXME: Add keyboard LED handling code
73 */
74 static void GS_vgainitkeymaps(int fd)
75 {
76 struct kbentry entry;
77 int map, i;
78
79 /* Don't do anything if we are passed a closed keyboard */
80 if ( fd < 0 ) {
81 return;
82 }
83
84 /* Load all the keysym mappings */
85 for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
86 memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
87 for ( i=0; i<NR_KEYS; ++i ) {
88 entry.kb_table = map;
89 entry.kb_index = i;
90 if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
91 /* fill keytemp. This replaces SDL_fbkeys.h */
92 if ( (map == 0) && (i<128) ) {
93 keymap_temp[i] = entry.kb_value;
94 }
95 /* The "Enter" key is a special case */
96 if ( entry.kb_value == K_ENTER ) {
97 entry.kb_value = K(KT_ASCII,13);
98 }
99 /* Handle numpad specially as well */
100 if ( KTYP(entry.kb_value) == KT_PAD ) {
101 switch ( entry.kb_value ) {
102 case K_P0:
103 case K_P1:
104 case K_P2:
105 case K_P3:
106 case K_P4:
107 case K_P5:
108 case K_P6:
109 case K_P7:
110 case K_P8:
111 case K_P9:
112 vga_keymap[map][i]=entry.kb_value;
113 vga_keymap[map][i]+= '0';
114 break;
115 case K_PPLUS:
116 vga_keymap[map][i]=K(KT_ASCII,'+');
117 break;
118 case K_PMINUS:
119 vga_keymap[map][i]=K(KT_ASCII,'-');
120 break;
121 case K_PSTAR:
122 vga_keymap[map][i]=K(KT_ASCII,'*');
123 break;
124 case K_PSLASH:
125 vga_keymap[map][i]=K(KT_ASCII,'/');
126 break;
127 case K_PENTER:
128 vga_keymap[map][i]=K(KT_ASCII,'\r');
129 break;
130 case K_PCOMMA:
131 vga_keymap[map][i]=K(KT_ASCII,',');
132 break;
133 case K_PDOT:
134 vga_keymap[map][i]=K(KT_ASCII,'.');
135 break;
136 default:
137 break;
138 }
139 }
140 /* Do the normal key translation */
141 if ( (KTYP(entry.kb_value) == KT_LATIN) ||
142 (KTYP(entry.kb_value) == KT_ASCII) ||
143 (KTYP(entry.kb_value) == KT_LETTER) ) {
144 vga_keymap[map][i] = entry.kb_value;
145 }
146 }
147 }
148 }
149 }
150
151 int GS_InGraphicsMode(_THIS)
152 {
153 return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
154 }
155
156 int GS_EnterGraphicsMode(_THIS)
157 {
158 struct termios keyboard_termios;
159
160 /* Set medium-raw keyboard mode */
161 if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) {
162
163 /* Switch to the correct virtual terminal */
164 if ( current_vt > 0 ) {
165 struct vt_stat vtstate;
166
167 if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {
168 saved_vt = vtstate.v_active;
169 }
170 if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {
171 ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
172 }
173 }
174
175 /* Set the terminal input mode */
176 if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
177 SDL_SetError("Unable to get terminal attributes");
178 if ( keyboard_fd > 0 ) {
179 close(keyboard_fd);
180 }
181 keyboard_fd = -1;
182 return(-1);
183 }
184 if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
185 SDL_SetError("Unable to get current keyboard mode");
186 if ( keyboard_fd > 0 ) {
187 close(keyboard_fd);
188 }
189 keyboard_fd = -1;
190 return(-1);
191 }
192 keyboard_termios = saved_kbd_termios;
193 keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
194 keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
195 keyboard_termios.c_cc[VMIN] = 0;
196 keyboard_termios.c_cc[VTIME] = 0;
197 if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
198 GS_CloseKeyboard(this);
199 SDL_SetError("Unable to set terminal attributes");
200 return(-1);
201 }
202 /* This will fail if we aren't root or this isn't our tty */
203 if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
204 GS_CloseKeyboard(this);
205 SDL_SetError("Unable to set keyboard in raw mode");
206 return(-1);
207 }
208 if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
209 GS_CloseKeyboard(this);
210 SDL_SetError("Unable to set keyboard in graphics mode");
211 return(-1);
212 }
213 }
214 return(keyboard_fd);
215 }
216
217 void GS_LeaveGraphicsMode(_THIS)
218 {
219 if ( GS_InGraphicsMode(this) ) {
220 ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
221 ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
222 tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
223 saved_kbd_mode = -1;
224
225 /* Head back over to the original virtual terminal */
226 if ( saved_vt > 0 ) {
227 ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
228 }
229 }
230 }
231
232 void GS_CloseKeyboard(_THIS)
233 {
234 if ( keyboard_fd >= 0 ) {
235 GS_LeaveGraphicsMode(this);
236 if ( keyboard_fd > 0 ) {
237 close(keyboard_fd);
238 }
239 }
240 keyboard_fd = -1;
241 }
242
243 int GS_OpenKeyboard(_THIS)
244 {
245 /* Open only if not already opened */
246 if ( keyboard_fd < 0 ) {
247 char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
248 char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
249 int i, tty0_fd;
250
251 /* Try to query for a free virtual terminal */
252 tty0_fd = -1;
253 for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
254 tty0_fd = open(tty0[i], O_WRONLY, 0);
255 }
256 if ( tty0_fd < 0 ) {
257 tty0_fd = dup(0); /* Maybe stdin is a VT? */
258 }
259 ioctl(tty0_fd, VT_OPENQRY, &current_vt);
260 close(tty0_fd);
261 if ( (geteuid() == 0) && (current_vt > 0) ) {
262 for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {
263 char vtpath[12];
264
265 sprintf(vtpath, vcs[i], current_vt);
266 keyboard_fd = open(vtpath, O_RDWR, 0);
267 #ifdef DEBUG_KEYBOARD
268 fprintf(stderr, "vtpath = %s, fd = %d\n",
269 vtpath, keyboard_fd);
270 #endif /* DEBUG_KEYBOARD */
271
272 /* This needs to be our controlling tty
273 so that the kernel ioctl() calls work
274 */
275 if ( keyboard_fd >= 0 ) {
276 tty0_fd = open("/dev/tty", O_RDWR, 0);
277 if ( tty0_fd >= 0 ) {
278 ioctl(tty0_fd, TIOCNOTTY, 0);
279 close(tty0_fd);
280 }
281 }
282 }
283 }
284 if ( keyboard_fd < 0 ) {
285 /* Last resort, maybe our tty is a usable VT */
286 current_vt = 0;
287 keyboard_fd = open("/dev/tty", O_RDWR);
288 }
289 #ifdef DEBUG_KEYBOARD
290 fprintf(stderr, "Current VT: %d\n", current_vt);
291 #endif
292 saved_kbd_mode = -1;
293
294 /* Make sure that our input is a console terminal */
295 { int dummy;
296 if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
297 close(keyboard_fd);
298 keyboard_fd = -1;
299 SDL_SetError("Unable to open a console terminal");
300 }
301 }
302
303 /* Set up keymap */
304 GS_vgainitkeymaps(keyboard_fd);
305 }
306 return(keyboard_fd);
307 }
308
309 static enum {
310 MOUSE_NONE = -1,
311 MOUSE_GPM, /* Note: GPM uses the MSC protocol */
312 MOUSE_PS2,
313 MOUSE_IMPS2,
314 MOUSE_MS,
315 MOUSE_BM,
316 NUM_MOUSE_DRVS
317 } mouse_drv = MOUSE_NONE;
318
319 void GS_CloseMouse(_THIS)
320 {
321 if ( mouse_fd > 0 ) {
322 close(mouse_fd);
323 }
324 mouse_fd = -1;
325 }
326
327 /* Returns processes listed in /proc with the desired name */
328 static int find_pid(DIR *proc, const char *wanted_name)
329 {
330 struct dirent *entry;
331 int pid;
332
333 /* First scan proc for the gpm process */
334 pid = 0;
335 while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
336 if ( isdigit(entry->d_name[0]) ) {
337 FILE *status;
338 char path[PATH_MAX];
339 char name[PATH_MAX];
340
341 sprintf(path, "/proc/%s/status", entry->d_name);
342 status=fopen(path, "r");
343 if ( status ) {
344 name[0] = '\0';
345 fscanf(status, "Name: %s", name);
346 if ( strcmp(name, wanted_name) == 0 ) {
347 pid = atoi(entry->d_name);
348 }
349 fclose(status);
350 }
351 }
352 }
353 return pid;
354 }
355
356 /* Returns true if /dev/gpmdata is being written to by gpm */
357 static int gpm_available(void)
358 {
359 int available;
360 DIR *proc;
361 int pid;
362 int cmdline, len, arglen;
363 char path[PATH_MAX];
364 char args[PATH_MAX], *arg;
365
366 /* Don't bother looking if the fifo isn't there */
367 if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
368 return(0);
369 }
370
371 available = 0;
372 proc = opendir("/proc");
373 if ( proc ) {
374 while ( (pid=find_pid(proc, "gpm")) > 0 ) {
375 sprintf(path, "/proc/%d/cmdline", pid);
376 cmdline = open(path, O_RDONLY, 0);
377 if ( cmdline >= 0 ) {
378 len = read(cmdline, args, sizeof(args));
379 arg = args;
380 while ( len > 0 ) {
381 if ( strcmp(arg, "-R") == 0 ) {
382 available = 1;
383 }
384 arglen = strlen(arg)+1;
385 len -= arglen;
386 arg += arglen;
387 }
388 close(cmdline);
389 }
390 }
391 closedir(proc);
392 }
393 return available;
394 }
395
396
397 /* rcg06112001 Set up IMPS/2 mode, if possible. This gives
398 * us access to the mousewheel, etc. Returns zero if
399 * writes to device failed, but you still need to query the
400 * device to see which mode it's actually in.
401 */
402 static int set_imps2_mode(int fd)
403 {
404 /* If you wanted to control the mouse mode (and we do :) ) ...
405 Set IMPS/2 protocol:
406 {0xf3,200,0xf3,100,0xf3,80}
407 Reset mouse device:
408 {0xFF}
409 */
410 Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
411 Uint8 reset = 0xff;
412 fd_set fdset;
413 struct timeval tv;
414 int retval = 0;
415
416 if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
417 if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
418 retval = 1;
419 }
420 }
421
422 /* Get rid of any chatter from the above */
423 FD_ZERO(&fdset);
424 FD_SET(fd, &fdset);
425 tv.tv_sec = 0;
426 tv.tv_usec = 0;
427 while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
428 char temp[32];
429 read(fd, temp, sizeof(temp));
430 }
431
432 return retval;
433 }
434
435
436 /* Returns true if the mouse uses the IMPS/2 protocol */
437 static int detect_imps2(int fd)
438 {
439 int imps2;
440
441 imps2 = 0;
442
443 if ( getenv("SDL_MOUSEDEV_IMPS2") ) {
444 imps2 = 1;
445 }
446 if ( ! imps2 ) {
447 Uint8 query_ps2 = 0xF2;
448 fd_set fdset;
449 struct timeval tv;
450
451 /* Get rid of any mouse motion noise */
452 FD_ZERO(&fdset);
453 FD_SET(fd, &fdset);
454 tv.tv_sec = 0;
455 tv.tv_usec = 0;
456 while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
457 char temp[32];
458 read(fd, temp, sizeof(temp));
459 }
460
461 /* Query for the type of mouse protocol */
462 if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
463 Uint8 ch = 0;
464
465 /* Get the mouse protocol response */
466 do {
467 FD_ZERO(&fdset);
468 FD_SET(fd, &fdset);
469 tv.tv_sec = 1;
470 tv.tv_usec = 0;
471 if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {
472 break;
473 }
474 } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
475 ((ch == 0xFA) || (ch == 0xAA)) );
476
477 /* Experimental values (Logitech wheelmouse) */
478 #ifdef DEBUG_MOUSE
479 fprintf(stderr, "Last mouse mode: 0x%x\n", ch);
480 #endif
481 if ( ch == 3 ) {
482 imps2 = 1;
483 }
484 }
485 }
486 return imps2;
487 }
488
489 int GS_OpenMouse(_THIS)
490 {
491 int i;
492 const char *mousedev;
493 const char *mousedrv;
494
495 mousedrv = getenv("SDL_MOUSEDRV");
496 mousedev = getenv("SDL_MOUSEDEV");
497 mouse_fd = -1;
498
499 /* STD MICE */
500
501 if ( mousedev == NULL ) {
502 /* FIXME someday... allow multiple mice in this driver */
503 char *ps2mice[] = {
504 "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
505 };
506 /* First try to use GPM in repeater mode */
507 if ( mouse_fd < 0 ) {
508 if ( gpm_available() ) {
509 mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
510 if ( mouse_fd >= 0 ) {
511 #ifdef DEBUG_MOUSE
512 fprintf(stderr, "Using GPM mouse\n");
513 #endif
514 mouse_drv = MOUSE_GPM;
515 }
516 }
517 }
518 /* Now try to use a modern PS/2 mouse */
519 for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) {
520 mouse_fd = open(ps2mice[i], O_RDWR, 0);
521 if (mouse_fd < 0) {
522 mouse_fd = open(ps2mice[i], O_RDONLY, 0);
523 }
524 if (mouse_fd >= 0) {
525 /* rcg06112001 Attempt to set IMPS/2 mode */
526 if ( i == 0 ) {
527 set_imps2_mode(mouse_fd);
528 }
529 if (detect_imps2(mouse_fd)) {
530 #ifdef DEBUG_MOUSE
531 fprintf(stderr, "Using IMPS2 mouse\n");
532 #endif
533 mouse_drv = MOUSE_IMPS2;
534 } else {
535 mouse_drv = MOUSE_PS2;
536 #ifdef DEBUG_MOUSE
537 fprintf(stderr, "Using PS2 mouse\n");
538 #endif
539 }
540 }
541 }
542 /* Next try to use a PPC ADB port mouse */
543 if ( mouse_fd < 0 ) {
544 mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
545 if ( mouse_fd >= 0 ) {
546 #ifdef DEBUG_MOUSE
547 fprintf(stderr, "Using ADB mouse\n");
548 #endif
549 mouse_drv = MOUSE_BM;
550 }
551 }
552 }
553 /* Default to a serial Microsoft mouse */
554 if ( mouse_fd < 0 ) {
555 if ( mousedev == NULL ) {
556 mousedev = "/dev/mouse";
557 }
558 mouse_fd = open(mousedev, O_RDONLY, 0);
559 if ( mouse_fd >= 0 ) {
560 struct termios mouse_termios;
561
562 /* Set the sampling speed to 1200 baud */
563 tcgetattr(mouse_fd, &mouse_termios);
564 mouse_termios.c_iflag = IGNBRK | IGNPAR;
565 mouse_termios.c_oflag = 0;
566 mouse_termios.c_lflag = 0;
567 mouse_termios.c_line = 0;
568 mouse_termios.c_cc[VTIME] = 0;
569 mouse_termios.c_cc[VMIN] = 1;
570 mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
571 mouse_termios.c_cflag |= CS8;
572 mouse_termios.c_cflag |= B1200;
573 tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
574 #ifdef DEBUG_MOUSE
575 fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev);
576 #endif
577 mouse_drv = MOUSE_MS;
578 }
579 }
580 if ( mouse_fd < 0 ) {
581 mouse_drv = MOUSE_NONE;
582 }
583 return(mouse_fd);
584 }
585
586 static int posted = 0;
587
588 void GS_vgamousecallback(int button, int dx, int dy)
589 {
590 int button_1, button_3;
591 int button_state;
592 int state_changed;
593 int i;
594 Uint8 state;
595
596 if ( dx || dy ) {
597 posted += SDL_PrivateMouseMotion(0, 1, dx, dy);
598 }
599
600 /* Swap button 1 and 3 */
601 button_1 = (button & 0x04) >> 2;
602 button_3 = (button & 0x01) << 2;
603 button &= ~0x05;
604 button |= (button_1|button_3);
605
606 /* See what changed */
607 button_state = SDL_GetMouseState(NULL, NULL);
608 state_changed = button_state ^ button;
609 for ( i=0; i<8; ++i ) {
610 if ( state_changed & (1<<i) ) {
611 if ( button & (1<<i) ) {
612 state = SDL_PRESSED;
613 } else {
614 state = SDL_RELEASED;
615 }
616 posted += SDL_PrivateMouseButton(state, i+1, 0, 0);
617 }
618 }
619 }
620
621 /* For now, use GPM, PS/2, and MS protocols
622 Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
623 */
624 static void handle_mouse(_THIS)
625 {
626 static int start = 0;
627 static unsigned char mousebuf[BUFSIZ];
628 int i, nread;
629 int button = 0;
630 int dx = 0, dy = 0;
631 int packetsize = 0;
632
633 /* Figure out the mouse packet size */
634 switch (mouse_drv) {
635 case MOUSE_NONE:
636 /* Ack! */
637 read(mouse_fd, mousebuf, BUFSIZ);
638 return;
639 case MOUSE_GPM:
640 packetsize = 5;
641 break;
642 case MOUSE_IMPS2:
643 packetsize = 4;
644 break;
645 case MOUSE_PS2:
646 case MOUSE_MS:
647 case MOUSE_BM:
648 packetsize = 3;
649 break;
650 case NUM_MOUSE_DRVS:
651 /* Uh oh.. */
652 packetsize = 0;
653 break;
654 }
655
656 /* Read as many packets as possible */
657 nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
658 if ( nread < 0 ) {
659 return;
660 }
661 nread += start;
662 #ifdef DEBUG_MOUSE
663 fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
664 #endif
665 for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
666 switch (mouse_drv) {
667 case MOUSE_NONE:
668 break;
669 case MOUSE_GPM:
670 /* GPM protocol has 0x80 in high byte */
671 if ( (mousebuf[i] & 0xF8) != 0x80 ) {
672 /* Go to next byte */
673 i -= (packetsize-1);
674 continue;
675 }
676 /* Get current mouse state */
677 button = (~mousebuf[i]) & 0x07;
678 dx = (signed char)(mousebuf[i+1]) +
679 (signed char)(mousebuf[i+3]);
680 dy = -((signed char)(mousebuf[i+2]) +
681 (signed char)(mousebuf[i+4]));
682 break;
683 case MOUSE_PS2:
684 /* PS/2 protocol has nothing in high byte */
685 if ( (mousebuf[i] & 0xC0) != 0 ) {
686 /* Go to next byte */
687 i -= (packetsize-1);
688 continue;
689 }
690 /* Get current mouse state */
691 button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
692 (mousebuf[i] & 0x02) >> 1 | /*Right*/
693 (mousebuf[i] & 0x01) << 2; /*Left*/
694 dx = (mousebuf[i] & 0x10) ?
695 mousebuf[i+1] - 256 : mousebuf[i+1];
696 dy = (mousebuf[i] & 0x20) ?
697 -(mousebuf[i+2] - 256) : -mousebuf[i+2];
698 break;
699 case MOUSE_IMPS2:
700 /* Get current mouse state */
701 button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
702 (mousebuf[i] & 0x02) >> 1 | /*Right*/
703 (mousebuf[i] & 0x01) << 2 | /*Left*/
704 (mousebuf[i] & 0x40) >> 3 | /* 4 */
705 (mousebuf[i] & 0x80) >> 3; /* 5 */
706 dx = (mousebuf[i] & 0x10) ?
707 mousebuf[i+1] - 256 : mousebuf[i+1];
708 dy = (mousebuf[i] & 0x20) ?
709 -(mousebuf[i+2] - 256) : -mousebuf[i+2];
710 switch (mousebuf[i+3]&0x0F) {
711 case 0x0E: /* DX = +1 */
712 case 0x02: /* DX = -1 */
713 break;
714 case 0x0F: /* DY = +1 (map button 4) */
715 button |= (1<<3);
716 break;
717 case 0x01: /* DY = -1 (map button 5) */
718 button |= (1<<4);
719 break;
720 }
721 break;
722 case MOUSE_MS:
723 /* Microsoft protocol has 0x40 in high byte */
724 if ( (mousebuf[i] & 0x40) != 0x40 ) {
725 /* Go to next byte */
726 i -= (packetsize-1);
727 continue;
728 }
729 /* Get current mouse state */
730 button = ((mousebuf[i] & 0x20) >> 3) |
731 ((mousebuf[i] & 0x10) >> 4);
732 dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
733 (mousebuf[i + 1] & 0x3F));
734 dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
735 (mousebuf[i + 2] & 0x3F));
736 break;
737 case MOUSE_BM:
738 /* BusMouse protocol has 0xF8 in high byte */
739 if ( (mousebuf[i] & 0xF8) != 0x80 ) {
740 /* Go to next byte */
741 i -= (packetsize-1);
742 continue;
743 }
744 /* Get current mouse state */
745 button = (~mousebuf[i]) & 0x07;
746 dx = (signed char)mousebuf[i+1];
747 dy = -(signed char)mousebuf[i+2];
748 break;
749 case NUM_MOUSE_DRVS:
750 /* Uh oh.. */
751 dx = 0;
752 dy = 0;
753 break;
754 }
755 GS_vgamousecallback(button, dx, dy);
756 }
757 if ( i < nread ) {
758 memcpy(mousebuf, &mousebuf[i], (nread-i));
759 start = (nread-i);
760 } else {
761 start = 0;
762 }
763 return;
764 }
765
766 static void handle_keyboard(_THIS)
767 {
768 unsigned char keybuf[BUFSIZ];
769 int i, nread;
770 int pressed;
771 int scancode;
772 SDL_keysym keysym;
773
774 nread = read(keyboard_fd, keybuf, BUFSIZ);
775 for ( i=0; i<nread; ++i ) {
776 scancode = keybuf[i] & 0x7F;
777 if ( keybuf[i] & 0x80 ) {
778 pressed = SDL_RELEASED;
779 } else {
780 pressed = SDL_PRESSED;
781 }
782 TranslateKey(scancode, &keysym);
783 posted += SDL_PrivateKeyboard(pressed, &keysym);
784 }
785 }
786
787 void GS_PumpEvents(_THIS)
788 {
789 fd_set fdset;
790 int max_fd;
791 static struct timeval zero;
792
793 do {
794 posted = 0;
795
796 FD_ZERO(&fdset);
797 max_fd = 0;
798 if ( keyboard_fd >= 0 ) {
799 FD_SET(keyboard_fd, &fdset);
800 if ( max_fd < keyboard_fd ) {
801 max_fd = keyboard_fd;
802 }
803 }
804 if ( mouse_fd >= 0 ) {
805 FD_SET(mouse_fd, &fdset);
806 if ( max_fd < mouse_fd ) {
807 max_fd = mouse_fd;
808 }
809 }
810 if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
811 if ( keyboard_fd >= 0 ) {
812 if ( FD_ISSET(keyboard_fd, &fdset) ) {
813 handle_keyboard(this);
814 }
815 }
816 if ( mouse_fd >= 0 ) {
817 if ( FD_ISSET(mouse_fd, &fdset) ) {
818 handle_mouse(this);
819 }
820 }
821 }
822 } while ( posted );
823 }
824
825 void GS_InitOSKeymap(_THIS)
826 {
827 int i;
828
829 /* Initialize the Linux key translation table */
830
831 /* First get the ascii keys and others not well handled */
832 for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
833 switch(i) {
834 /* These aren't handled by the x86 kernel keymapping (?) */
835 case SCANCODE_PRINTSCREEN:
836 keymap[i] = SDLK_PRINT;
837 break;
838 case SCANCODE_BREAK:
839 keymap[i] = SDLK_BREAK;
840 break;
841 case SCANCODE_BREAK_ALTERNATIVE:
842 keymap[i] = SDLK_PAUSE;
843 break;
844 case SCANCODE_LEFTSHIFT:
845 keymap[i] = SDLK_LSHIFT;
846 break;
847 case SCANCODE_RIGHTSHIFT:
848 keymap[i] = SDLK_RSHIFT;
849 break;
850 case SCANCODE_LEFTCONTROL:
851 keymap[i] = SDLK_LCTRL;
852 break;
853 case SCANCODE_RIGHTCONTROL:
854 keymap[i] = SDLK_RCTRL;
855 break;
856 case SCANCODE_RIGHTWIN:
857 keymap[i] = SDLK_RSUPER;
858 break;
859 case SCANCODE_LEFTWIN:
860 keymap[i] = SDLK_LSUPER;
861 break;
862 case 127:
863 keymap[i] = SDLK_MENU;
864 break;
865 /* this should take care of all standard ascii keys */
866 default:
867 keymap[i] = KVAL(vga_keymap[0][i]);
868 break;
869 }
870 }
871 for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
872 switch(keymap_temp[i]) {
873 case K_F1: keymap[i] = SDLK_F1; break;
874 case K_F2: keymap[i] = SDLK_F2; break;
875 case K_F3: keymap[i] = SDLK_F3; break;
876 case K_F4: keymap[i] = SDLK_F4; break;
877 case K_F5: keymap[i] = SDLK_F5; break;
878 case K_F6: keymap[i] = SDLK_F6; break;
879 case K_F7: keymap[i] = SDLK_F7; break;
880 case K_F8: keymap[i] = SDLK_F8; break;
881 case K_F9: keymap[i] = SDLK_F9; break;
882 case K_F10: keymap[i] = SDLK_F10; break;
883 case K_F11: keymap[i] = SDLK_F11; break;
884 case K_F12: keymap[i] = SDLK_F12; break;
885
886 case K_DOWN: keymap[i] = SDLK_DOWN; break;
887 case K_LEFT: keymap[i] = SDLK_LEFT; break;
888 case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
889 case K_UP: keymap[i] = SDLK_UP; break;
890
891 case K_P0: keymap[i] = SDLK_KP0; break;
892 case K_P1: keymap[i] = SDLK_KP1; break;
893 case K_P2: keymap[i] = SDLK_KP2; break;
894 case K_P3: keymap[i] = SDLK_KP3; break;
895 case K_P4: keymap[i] = SDLK_KP4; break;
896 case K_P5: keymap[i] = SDLK_KP5; break;
897 case K_P6: keymap[i] = SDLK_KP6; break;
898 case K_P7: keymap[i] = SDLK_KP7; break;
899 case K_P8: keymap[i] = SDLK_KP8; break;
900 case K_P9: keymap[i] = SDLK_KP9; break;
901 case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break;
902 case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
903 case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break;
904 case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
905 case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
906 case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break;
907
908 case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT )
909 keymap[i] = SDLK_LSHIFT;
910 break;
911 case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
912 case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
913 case K_CTRL: if ( keymap[i] != SDLK_RCTRL )
914 keymap[i] = SDLK_LCTRL;
915 break;
916 case K_CTRLL: keymap[i] = SDLK_LCTRL; break;
917 case K_CTRLR: keymap[i] = SDLK_RCTRL; break;
918 case K_ALT: keymap[i] = SDLK_LALT; break;
919 case K_ALTGR: keymap[i] = SDLK_RALT; break;
920
921 case K_INSERT: keymap[i] = SDLK_INSERT; break;
922 case K_REMOVE: keymap[i] = SDLK_DELETE; break;
923 case K_PGUP: keymap[i] = SDLK_PAGEUP; break;
924 case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break;
925 case K_FIND: keymap[i] = SDLK_HOME; break;
926 case K_SELECT: keymap[i] = SDLK_END; break;
927
928 case K_NUM: keymap[i] = SDLK_NUMLOCK; break;
929 case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break;
930
931 case K_F13: keymap[i] = SDLK_PRINT; break;
932 case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break;
933 case K_PAUSE: keymap[i] = SDLK_PAUSE; break;
934
935 case 127: keymap[i] = SDLK_BACKSPACE; break;
936
937 default: break;
938 }
939 }
940 }
941
942 static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
943 {
944 /* Set the keysym information */
945 keysym->scancode = scancode;
946 keysym->sym = keymap[scancode];
947 keysym->mod = KMOD_NONE;
948
949 /* If UNICODE is on, get the UNICODE value for the key */
950 keysym->unicode = 0;
951 if ( SDL_TranslateUNICODE ) {
952 int map;
953 SDLMod modstate;
954
955 modstate = SDL_GetModState();
956 map = 0;
957 if ( modstate & KMOD_SHIFT ) {
958 map |= (1<<KG_SHIFT);
959 }
960 if ( modstate & KMOD_CTRL ) {
961 map |= (1<<KG_CTRL);
962 }
963 if ( modstate & KMOD_ALT ) {
964 map |= (1<<KG_ALT);
965 }
966 if ( modstate & KMOD_MODE ) {
967 map |= (1<<KG_ALTGR);
968 }
969 if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
970 if ( modstate & KMOD_CAPS ) {
971 map ^= (1<<KG_SHIFT);
972 }
973 }
974 if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
975 if ( modstate & KMOD_NUM ) {
976 keysym->unicode=KVAL(vga_keymap[map][scancode]);
977 }
978 } else {
979 keysym->unicode = KVAL(vga_keymap[map][scancode]);
980 }
981 }
982 return(keysym);
983 }