src/video/fbcon/SDL_fbevents.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. FB_vgainitkeymaps
  2. FB_InGraphicsMode
  3. FB_EnterGraphicsMode
  4. FB_LeaveGraphicsMode
  5. FB_CloseKeyboard
  6. FB_OpenKeyboard
  7. FB_CloseMouse
  8. find_pid
  9. gpm_available
  10. detect_imps2
  11. FB_OpenMouse
  12. FB_vgamousecallback
  13. handle_mouse
  14. switch_vt
  15. handle_keyboard
  16. FB_PumpEvents
  17. FB_InitOSKeymap
  18. TranslateKey

   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: SDL_fbevents.c,v 1.5.2.19 2001/02/28 12:06:11 hercules Exp $";
  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)
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
 155 {
 156         return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
 157 }
 158 
 159 int FB_EnterGraphicsMode(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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, &current_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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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;
 622 
 623         /* Figure out the mouse packet size */
 624         switch (mouse_drv) {
 625                 case MOUSE_NONE:
 626                         /* Ack! */
 627                         read(mouse_fd, mousebuf, BUFSIZ);
 628                         return;
 629                 case MOUSE_GPM:
 630                         packetsize = 5;
 631                         break;
 632                 case MOUSE_IMPS2:
 633                         packetsize = 4;
 634                         break;
 635                 case MOUSE_PS2:
 636                 case MOUSE_MS:
 637                 case MOUSE_BM:
 638                         packetsize = 3;
 639                         break;
 640                 case MOUSE_ELO:
 641                         packetsize = ELO_PACKET_SIZE;
 642                         relative = 0;
 643                         break;
 644                 case NUM_MOUSE_DRVS:
 645                         /* Uh oh.. */
 646                         packetsize = 0;
 647                         break;
 648         }
 649 
 650         /* Read as many packets as possible */
 651         nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
 652         if ( nread < 0 ) {
 653                 return;
 654         }
 655         nread += start;
 656 #ifdef DEBUG_MOUSE
 657         fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
 658 #endif
 659         for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
 660                 switch (mouse_drv) {
 661                         case MOUSE_NONE:
 662                                 break;
 663                         case MOUSE_GPM:
 664                                 /* GPM protocol has 0x80 in high byte */
 665                                 if ( (mousebuf[i] & 0xF8) != 0x80 ) {
 666                                         /* Go to next byte */
 667                                         i -= (packetsize-1);
 668                                         continue;
 669                                 }
 670                                 /* Get current mouse state */
 671                                 button = (~mousebuf[i]) & 0x07;
 672                                 dx =   (signed char)(mousebuf[i+1]) +
 673                                        (signed char)(mousebuf[i+3]);
 674                                 dy = -((signed char)(mousebuf[i+2]) +
 675                                        (signed char)(mousebuf[i+4]));
 676                                 break;
 677                         case MOUSE_PS2:
 678                                 /* PS/2 protocol has nothing in high byte */
 679                                 if ( (mousebuf[i] & 0xC0) != 0 ) {
 680                                         /* Go to next byte */
 681                                         i -= (packetsize-1);
 682                                         continue;
 683                                 }
 684                                 /* Get current mouse state */
 685                                 button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
 686                                          (mousebuf[i] & 0x02) >> 1 | /*Right*/
 687                                          (mousebuf[i] & 0x01) << 2;  /*Left*/
 688                                 dx = (mousebuf[i] & 0x10) ?
 689                                       mousebuf[i+1] - 256 : mousebuf[i+1];
 690                                 dy = (mousebuf[i] & 0x20) ?
 691                                       -(mousebuf[i+2] - 256) : -mousebuf[i+2];
 692                                 break;
 693                         case MOUSE_IMPS2:
 694                                 /* Get current mouse state */
 695                                 button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
 696                                          (mousebuf[i] & 0x02) >> 1 | /*Right*/
 697                                          (mousebuf[i] & 0x01) << 2 | /*Left*/
 698                                          (mousebuf[i] & 0x40) >> 3 | /* 4 */
 699                                          (mousebuf[i] & 0x80) >> 3;  /* 5 */
 700                                 dx = (mousebuf[i] & 0x10) ?
 701                                       mousebuf[i+1] - 256 : mousebuf[i+1];
 702                                 dy = (mousebuf[i] & 0x20) ?
 703                                       -(mousebuf[i+2] - 256) : -mousebuf[i+2];
 704                                 switch (mousebuf[i+3]&0x0F) {
 705                                     case 0x0E: /* DX = +1 */
 706                                     case 0x02: /* DX = -1 */
 707                                         break;
 708                                     case 0x0F: /* DY = +1 (map button 4) */
 709                                         button |= (1<<3);
 710                                         break;
 711                                     case 0x01: /* DY = -1 (map button 5) */
 712                                         button |= (1<<4);
 713                                         break;
 714                                 }
 715                                 break;
 716                         case MOUSE_MS:
 717                                 /* Microsoft protocol has 0x40 in high byte */
 718                                 if ( (mousebuf[i] & 0x40) != 0x40 ) {
 719                                         /* Go to next byte */
 720                                         i -= (packetsize-1);
 721                                         continue;
 722                                 }
 723                                 /* Get current mouse state */
 724                                 button = ((mousebuf[i] & 0x20) >> 3) |
 725                                          ((mousebuf[i] & 0x10) >> 4);
 726                                 dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
 727                                                    (mousebuf[i + 1] & 0x3F));
 728                                 dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
 729                                                     (mousebuf[i + 2] & 0x3F));
 730                                 break;
 731                         case MOUSE_BM:
 732                                 /* BusMouse protocol has 0xF8 in high byte */
 733                                 if ( (mousebuf[i] & 0xF8) != 0x80 ) {
 734                                         /* Go to next byte */
 735                                         i -= (packetsize-1);
 736                                         continue;
 737                                 }
 738                                 /* Get current mouse state */
 739                                 button = (~mousebuf[i]) & 0x07;
 740                                 dx =  (signed char)mousebuf[i+1];
 741                                 dy = -(signed char)mousebuf[i+2];
 742                                 break;
 743                         case MOUSE_ELO:
 744                                 /* ELO protocol has ELO_START_BYTE as first byte */
 745                                 if ( mousebuf[i] != ELO_START_BYTE ) {
 746                                         /* Go to next byte */
 747                                         i -= (packetsize-1);
 748                                         continue;
 749                                 }
 750 
 751                                 /* parse the packet */
 752                                 if(!eloParsePacket(&(mousebuf[i]), &dx, &dy, &button)) {
 753                                         break;
 754                                 }
 755                                 
 756                                 button = (button & 0x01) << 2;
 757 
 758                                 /* convert to screen coordinates */
 759                                 eloConvertXY(this, &dx, &dy);
 760                                 break;
 761 
 762                         case NUM_MOUSE_DRVS:
 763                                 /* Uh oh.. */
 764                                 dx = 0;
 765                                 dy = 0;
 766                                 break;
 767                 }
 768                 FB_vgamousecallback(button, relative, dx, dy);
 769         }
 770         if ( i < nread ) {
 771                 memcpy(mousebuf, &mousebuf[i], (nread-i));
 772                 start = (nread-i);
 773         } else {
 774                 start = 0;
 775         }
 776         return;
 777 }
 778 
 779 /* Handle switching to another VC, returns when our VC is back */
 780 static void switch_vt(_THIS, unsigned short which)
     /* [<][>][^][v][top][bottom][index][help] */
 781 {
 782         struct vt_stat vtstate;
 783         unsigned short current;
 784         SDL_Surface *screen;
 785         __u16 saved_pal[3*256];
 786         Uint32 screen_arealen;
 787         Uint8 *screen_contents;
 788 
 789         /* Figure out whether or not we're switching to a new console */
 790         if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
 791              (which == vtstate.v_active) ) {
 792                 return;
 793         }
 794         current = vtstate.v_active;
 795 
 796         /* Save the contents of the screen, and go to text mode */
 797         SDL_mutexP(hw_lock);
 798         screen = SDL_VideoSurface;
 799         screen_arealen = (screen->h*screen->pitch);
 800         screen_contents = (Uint8 *)malloc(screen_arealen);
 801         if ( screen_contents ) {
 802                 memcpy(screen_contents, screen->pixels, screen_arealen);
 803         }
 804         FB_SavePaletteTo(this, 256, saved_pal);
 805         ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
 806 
 807         /* New console, switch to it */
 808         if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) {
 809                 /* Wait for our console to be activated again */
 810                 ioctl(keyboard_fd, VT_WAITACTIVE, which);
 811                 while ( ioctl(keyboard_fd, VT_WAITACTIVE, current) < 0 ) {
 812                         if ( (errno != EINTR) && (errno != EAGAIN) ) {
 813                                 /* Unknown VT error - cancel this */
 814                                 break;
 815                         }
 816                         SDL_Delay(500);
 817                 }
 818         }
 819 
 820         /* Restore graphics mode and the contents of the screen */
 821         ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
 822         FB_RestorePaletteFrom(this, 256, saved_pal);
 823         if ( screen_contents ) {
 824                 memcpy(screen->pixels, screen_contents, screen_arealen);
 825                 free(screen_contents);
 826         }
 827         SDL_mutexV(hw_lock);
 828 }
 829 
 830 static void handle_keyboard(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 831 {
 832         unsigned char keybuf[BUFSIZ];
 833         int i, nread;
 834         int pressed;
 835         int scancode;
 836         SDL_keysym keysym;
 837 
 838         nread = read(keyboard_fd, keybuf, BUFSIZ);
 839         for ( i=0; i<nread; ++i ) {
 840                 scancode = keybuf[i] & 0x7F;
 841                 if ( keybuf[i] & 0x80 ) {
 842                         pressed = SDL_RELEASED;
 843                 } else {
 844                         pressed = SDL_PRESSED;
 845                 }
 846                 TranslateKey(scancode, &keysym);
 847                 /* Handle Alt-FN for vt switch */
 848                 switch (keysym.sym) {
 849                     case SDLK_F1:
 850                     case SDLK_F2:
 851                     case SDLK_F3:
 852                     case SDLK_F4:
 853                     case SDLK_F5:
 854                     case SDLK_F6:
 855                     case SDLK_F7:
 856                     case SDLK_F8:
 857                     case SDLK_F9:
 858                     case SDLK_F10:
 859                     case SDLK_F11:
 860                     case SDLK_F12:
 861                         if ( SDL_GetModState() & KMOD_ALT ) {
 862                                 switch_vt(this, (keysym.sym-SDLK_F1)+1);
 863                                 break;
 864                         }
 865                         /* Fall through to normal processing */
 866                     default:
 867                         posted += SDL_PrivateKeyboard(pressed, &keysym);
 868                         break;
 869                 }
 870         }
 871 }
 872 
 873 void FB_PumpEvents(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 874 {
 875         fd_set fdset;
 876         int max_fd;
 877         static struct timeval zero;
 878 
 879         do {
 880                 posted = 0;
 881 
 882                 FD_ZERO(&fdset);
 883                 max_fd = 0;
 884                 if ( keyboard_fd >= 0 ) {
 885                         FD_SET(keyboard_fd, &fdset);
 886                         if ( max_fd < keyboard_fd ) {
 887                                 max_fd = keyboard_fd;
 888                         }
 889                 }
 890                 if ( mouse_fd >= 0 ) {
 891                         FD_SET(mouse_fd, &fdset);
 892                         if ( max_fd < mouse_fd ) {
 893                                 max_fd = mouse_fd;
 894                         }
 895                 }
 896                 if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
 897                         if ( keyboard_fd >= 0 ) {
 898                                 if ( FD_ISSET(keyboard_fd, &fdset) ) {
 899                                         handle_keyboard(this);
 900                                 }
 901                         }
 902                         if ( mouse_fd >= 0 ) {
 903                                 if ( FD_ISSET(mouse_fd, &fdset) ) {
 904                                         handle_mouse(this);
 905                                 }
 906                         }
 907                 }
 908         } while ( posted );
 909 }
 910 
 911 void FB_InitOSKeymap(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 912 {
 913         int i;
 914 
 915         /* Initialize the Linux key translation table */
 916 
 917         /* First get the ascii keys and others not well handled */
 918         for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
 919           switch(i) {
 920           /* These aren't handled by the x86 kernel keymapping (?) */
 921           case SCANCODE_PRINTSCREEN:
 922             keymap[i] = SDLK_PRINT;
 923             break;
 924           case SCANCODE_BREAK:
 925             keymap[i] = SDLK_BREAK;
 926             break;
 927           case SCANCODE_BREAK_ALTERNATIVE:
 928             keymap[i] = SDLK_PAUSE;
 929             break;
 930           case SCANCODE_LEFTSHIFT:
 931             keymap[i] = SDLK_LSHIFT;
 932             break;
 933           case SCANCODE_RIGHTSHIFT:
 934             keymap[i] = SDLK_RSHIFT;
 935             break;
 936           case SCANCODE_LEFTCONTROL:
 937             keymap[i] = SDLK_LCTRL;
 938             break;
 939           case SCANCODE_RIGHTCONTROL:
 940             keymap[i] = SDLK_RCTRL;
 941             break;
 942           case SCANCODE_RIGHTWIN:
 943             keymap[i] = SDLK_RSUPER;
 944             break;
 945           case SCANCODE_LEFTWIN:
 946             keymap[i] = SDLK_LSUPER;
 947             break;
 948           case 127:
 949             keymap[i] = SDLK_MENU;
 950             break;
 951           /* this should take care of all standard ascii keys */
 952           default:
 953             keymap[i] = KVAL(vga_keymap[0][i]);
 954             break;
 955           }
 956         }
 957         for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
 958           switch(keymap_temp[i]) {
 959             case K_F1:  keymap[i] = SDLK_F1;  break;
 960             case K_F2:  keymap[i] = SDLK_F2;  break;
 961             case K_F3:  keymap[i] = SDLK_F3;  break;
 962             case K_F4:  keymap[i] = SDLK_F4;  break;
 963             case K_F5:  keymap[i] = SDLK_F5;  break;
 964             case K_F6:  keymap[i] = SDLK_F6;  break;
 965             case K_F7:  keymap[i] = SDLK_F7;  break;
 966             case K_F8:  keymap[i] = SDLK_F8;  break;
 967             case K_F9:  keymap[i] = SDLK_F9;  break;
 968             case K_F10: keymap[i] = SDLK_F10; break;
 969             case K_F11: keymap[i] = SDLK_F11; break;
 970             case K_F12: keymap[i] = SDLK_F12; break;
 971 
 972             case K_DOWN:  keymap[i] = SDLK_DOWN;  break;
 973             case K_LEFT:  keymap[i] = SDLK_LEFT;  break;
 974             case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
 975             case K_UP:    keymap[i] = SDLK_UP;    break;
 976 
 977             case K_P0:     keymap[i] = SDLK_KP0; break;
 978             case K_P1:     keymap[i] = SDLK_KP1; break;
 979             case K_P2:     keymap[i] = SDLK_KP2; break;
 980             case K_P3:     keymap[i] = SDLK_KP3; break;
 981             case K_P4:     keymap[i] = SDLK_KP4; break;
 982             case K_P5:     keymap[i] = SDLK_KP5; break;
 983             case K_P6:     keymap[i] = SDLK_KP6; break;
 984             case K_P7:     keymap[i] = SDLK_KP7; break;
 985             case K_P8:     keymap[i] = SDLK_KP8; break;
 986             case K_P9:     keymap[i] = SDLK_KP9; break;
 987             case K_PPLUS:  keymap[i] = SDLK_KP_PLUS; break;
 988             case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
 989             case K_PSTAR:  keymap[i] = SDLK_KP_MULTIPLY; break;
 990             case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
 991             case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
 992             case K_PDOT:   keymap[i] = SDLK_KP_PERIOD; break;
 993 
 994             case K_SHIFT:  if ( keymap[i] != SDLK_RSHIFT )
 995                              keymap[i] = SDLK_LSHIFT;
 996                            break;
 997             case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
 998             case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
 999             case K_CTRL:  if ( keymap[i] != SDLK_RCTRL )
1000                              keymap[i] = SDLK_LCTRL;
1001                            break;
1002             case K_CTRLL:  keymap[i] = SDLK_LCTRL;  break;
1003             case K_CTRLR:  keymap[i] = SDLK_RCTRL;  break;
1004             case K_ALT:    keymap[i] = SDLK_LALT;   break;
1005             case K_ALTGR:  keymap[i] = SDLK_RALT;   break;
1006 
1007             case K_INSERT: keymap[i] = SDLK_INSERT;   break;
1008             case K_REMOVE: keymap[i] = SDLK_DELETE;   break;
1009             case K_PGUP:   keymap[i] = SDLK_PAGEUP;   break;
1010             case K_PGDN:   keymap[i] = SDLK_PAGEDOWN; break;
1011             case K_FIND:   keymap[i] = SDLK_HOME;     break;
1012             case K_SELECT: keymap[i] = SDLK_END;      break;
1013 
1014             case K_NUM:  keymap[i] = SDLK_NUMLOCK;   break;
1015             case K_CAPS: keymap[i] = SDLK_CAPSLOCK;  break;
1016 
1017             case K_F13:   keymap[i] = SDLK_PRINT;     break;
1018             case K_HOLD:  keymap[i] = SDLK_SCROLLOCK; break;
1019             case K_PAUSE: keymap[i] = SDLK_PAUSE;     break;
1020 
1021             case 127: keymap[i] = SDLK_BACKSPACE; break;
1022              
1023             default: break;
1024           }
1025         }
1026 }
1027 
1028 static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
     /* [<][>][^][v][top][bottom][index][help] */
1029 {
1030         /* Set the keysym information */
1031         keysym->scancode = scancode;
1032         keysym->sym = keymap[scancode];
1033         keysym->mod = KMOD_NONE;
1034 
1035         /* If UNICODE is on, get the UNICODE value for the key */
1036         keysym->unicode = 0;
1037         if ( SDL_TranslateUNICODE ) {
1038                 int map;
1039                 SDLMod modstate;
1040 
1041                 modstate = SDL_GetModState();
1042                 map = 0;
1043                 if ( modstate & KMOD_SHIFT ) {
1044                         map |= (1<<KG_SHIFT);
1045                 }
1046                 if ( modstate & KMOD_CTRL ) {
1047                         map |= (1<<KG_CTRL);
1048                 }
1049                 if ( modstate & KMOD_ALT ) {
1050                         map |= (1<<KG_ALT);
1051                 }
1052                 if ( modstate & KMOD_MODE ) {
1053                         map |= (1<<KG_ALTGR);
1054                 }
1055                 if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
1056                         if ( modstate & KMOD_CAPS ) {
1057                                 map ^= (1<<KG_SHIFT);
1058                         }
1059                 }
1060                 if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
1061                         if ( modstate & KMOD_NUM ) {
1062                                 keysym->unicode=KVAL(vga_keymap[map][scancode]);
1063                         }
1064                 } else {
1065                         keysym->unicode = KVAL(vga_keymap[map][scancode]);
1066                 }
1067         }
1068         return(keysym);
1069 }

/* [<][>][^][v][top][bottom][index][help] */