src/video/fbcon/SDL_fbevents.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1659 14717b52abc0
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

The headers are being converted to automatically generate doxygen documentation.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 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     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* Handle the event stream, converting console events into SDL events */
    25 
    26 #include <stdio.h>
    27 #include <sys/types.h>
    28 #include <sys/time.h>
    29 #include <sys/ioctl.h>
    30 #include <unistd.h>
    31 #include <fcntl.h>
    32 #include <errno.h>
    33 #include <limits.h>
    34 
    35 /* For parsing /proc */
    36 #include <dirent.h>
    37 #include <ctype.h>
    38 
    39 #include <linux/vt.h>
    40 #include <linux/kd.h>
    41 #include <linux/keyboard.h>
    42 
    43 #include "SDL_timer.h"
    44 #include "SDL_mutex.h"
    45 #include "../SDL_sysvideo.h"
    46 #include "../../events/SDL_sysevents.h"
    47 #include "../../events/SDL_events_c.h"
    48 #include "SDL_fbvideo.h"
    49 #include "SDL_fbevents_c.h"
    50 #include "SDL_fbkeys.h"
    51 
    52 #include "SDL_fbelo.h"
    53 
    54 #ifndef GPM_NODE_FIFO
    55 #define GPM_NODE_FIFO	"/dev/gpmdata"
    56 #endif
    57 
    58 /*#define DEBUG_KEYBOARD*/
    59 /*#define DEBUG_MOUSE*/
    60 
    61 /* The translation tables from a console scancode to a SDL keysym */
    62 #define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)
    63 static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
    64 static SDLKey keymap[128];
    65 static Uint16 keymap_temp[128]; /* only used at startup */
    66 static SDL_keysym *TranslateKey (int scancode, SDL_keysym * keysym);
    67 
    68 /* Ugh, we have to duplicate the kernel's keysym mapping code...
    69    Oh, it's not so bad. :-)
    70 
    71    FIXME: Add keyboard LED handling code
    72  */
    73 static void
    74 FB_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         SDL_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
   152 FB_InGraphicsMode (_THIS)
   153 {
   154     return ((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
   155 }
   156 
   157 int
   158 FB_EnterGraphicsMode (_THIS)
   159 {
   160     struct termios keyboard_termios;
   161 
   162     /* Set medium-raw keyboard mode */
   163     if ((keyboard_fd >= 0) && !FB_InGraphicsMode (this)) {
   164 
   165         /* Switch to the correct virtual terminal */
   166         if (current_vt > 0) {
   167             struct vt_stat vtstate;
   168 
   169             if (ioctl (keyboard_fd, VT_GETSTATE, &vtstate) == 0) {
   170                 saved_vt = vtstate.v_active;
   171             }
   172             if (ioctl (keyboard_fd, VT_ACTIVATE, current_vt) == 0) {
   173                 ioctl (keyboard_fd, VT_WAITACTIVE, current_vt);
   174             }
   175         }
   176 
   177         /* Set the terminal input mode */
   178         if (tcgetattr (keyboard_fd, &saved_kbd_termios) < 0) {
   179             SDL_SetError ("Unable to get terminal attributes");
   180             if (keyboard_fd > 0) {
   181                 close (keyboard_fd);
   182             }
   183             keyboard_fd = -1;
   184             return (-1);
   185         }
   186         if (ioctl (keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0) {
   187             SDL_SetError ("Unable to get current keyboard mode");
   188             if (keyboard_fd > 0) {
   189                 close (keyboard_fd);
   190             }
   191             keyboard_fd = -1;
   192             return (-1);
   193         }
   194         keyboard_termios = saved_kbd_termios;
   195         keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
   196         keyboard_termios.c_iflag &=
   197             ~(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         /* Prevent switching the virtual terminal */
   217         ioctl (keyboard_fd, VT_LOCKSWITCH, 1);
   218     }
   219     return (keyboard_fd);
   220 }
   221 
   222 void
   223 FB_LeaveGraphicsMode (_THIS)
   224 {
   225     if (FB_InGraphicsMode (this)) {
   226         ioctl (keyboard_fd, KDSETMODE, KD_TEXT);
   227         ioctl (keyboard_fd, KDSKBMODE, saved_kbd_mode);
   228         tcsetattr (keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
   229         saved_kbd_mode = -1;
   230 
   231         /* Head back over to the original virtual terminal */
   232         ioctl (keyboard_fd, VT_UNLOCKSWITCH, 1);
   233         if (saved_vt > 0) {
   234             ioctl (keyboard_fd, VT_ACTIVATE, saved_vt);
   235         }
   236     }
   237 }
   238 
   239 void
   240 FB_CloseKeyboard (_THIS)
   241 {
   242     if (keyboard_fd >= 0) {
   243         FB_LeaveGraphicsMode (this);
   244         if (keyboard_fd > 0) {
   245             close (keyboard_fd);
   246         }
   247     }
   248     keyboard_fd = -1;
   249 }
   250 
   251 int
   252 FB_OpenKeyboard (_THIS)
   253 {
   254     /* Open only if not already opened */
   255     if (keyboard_fd < 0) {
   256         static const char *const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
   257         static const char *const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
   258         int i, tty0_fd;
   259 
   260         /* Try to query for a free virtual terminal */
   261         tty0_fd = -1;
   262         for (i = 0; tty0[i] && (tty0_fd < 0); ++i) {
   263             tty0_fd = open (tty0[i], O_WRONLY, 0);
   264         }
   265         if (tty0_fd < 0) {
   266             tty0_fd = dup (0);  /* Maybe stdin is a VT? */
   267         }
   268         ioctl (tty0_fd, VT_OPENQRY, &current_vt);
   269         close (tty0_fd);
   270         if ((geteuid () == 0) && (current_vt > 0)) {
   271             for (i = 0; vcs[i] && (keyboard_fd < 0); ++i) {
   272                 char vtpath[12];
   273 
   274                 SDL_snprintf (vtpath, SDL_arraysize (vtpath), vcs[i],
   275                               current_vt);
   276                 keyboard_fd = open (vtpath, O_RDWR, 0);
   277 #ifdef DEBUG_KEYBOARD
   278                 fprintf (stderr, "vtpath = %s, fd = %d\n",
   279                          vtpath, keyboard_fd);
   280 #endif /* DEBUG_KEYBOARD */
   281 
   282                 /* This needs to be our controlling tty
   283                    so that the kernel ioctl() calls work
   284                  */
   285                 if (keyboard_fd >= 0) {
   286                     tty0_fd = open ("/dev/tty", O_RDWR, 0);
   287                     if (tty0_fd >= 0) {
   288                         ioctl (tty0_fd, TIOCNOTTY, 0);
   289                         close (tty0_fd);
   290                     }
   291                 }
   292             }
   293         }
   294         if (keyboard_fd < 0) {
   295             /* Last resort, maybe our tty is a usable VT */
   296             struct vt_stat vtstate;
   297 
   298             keyboard_fd = open ("/dev/tty", O_RDWR);
   299 
   300             if (ioctl (keyboard_fd, VT_GETSTATE, &vtstate) == 0) {
   301                 current_vt = vtstate.v_active;
   302             } else {
   303                 current_vt = 0;
   304             }
   305         }
   306 #ifdef DEBUG_KEYBOARD
   307         fprintf (stderr, "Current VT: %d\n", current_vt);
   308 #endif
   309         saved_kbd_mode = -1;
   310 
   311         /* Make sure that our input is a console terminal */
   312         {
   313             int dummy;
   314             if (ioctl (keyboard_fd, KDGKBMODE, &dummy) < 0) {
   315                 close (keyboard_fd);
   316                 keyboard_fd = -1;
   317                 SDL_SetError ("Unable to open a console terminal");
   318             }
   319         }
   320 
   321         /* Set up keymap */
   322         FB_vgainitkeymaps (keyboard_fd);
   323     }
   324     return (keyboard_fd);
   325 }
   326 
   327 static enum
   328 {
   329     MOUSE_NONE = -1,
   330     MOUSE_MSC,                  /* Note: GPM uses the MSC protocol */
   331     MOUSE_PS2,
   332     MOUSE_IMPS2,
   333     MOUSE_MS,
   334     MOUSE_BM,
   335     MOUSE_ELO,
   336     MOUSE_TSLIB,
   337     NUM_MOUSE_DRVS
   338 } mouse_drv = MOUSE_NONE;
   339 
   340 void
   341 FB_CloseMouse (_THIS)
   342 {
   343 #if SDL_INPUT_TSLIB
   344     if (ts_dev != NULL) {
   345         ts_close (ts_dev);
   346         ts_dev = NULL;
   347         mouse_fd = -1;
   348     }
   349 #endif /* SDL_INPUT_TSLIB */
   350     if (mouse_fd > 0) {
   351         close (mouse_fd);
   352     }
   353     mouse_fd = -1;
   354 }
   355 
   356 /* Returns processes listed in /proc with the desired name */
   357 static int
   358 find_pid (DIR * proc, const char *wanted_name)
   359 {
   360     struct dirent *entry;
   361     int pid;
   362 
   363     /* First scan proc for the gpm process */
   364     pid = 0;
   365     while ((pid == 0) && ((entry = readdir (proc)) != NULL)) {
   366         if (isdigit (entry->d_name[0])) {
   367             FILE *status;
   368             char path[PATH_MAX];
   369             char name[PATH_MAX];
   370 
   371             SDL_snprintf (path, SDL_arraysize (path), "/proc/%s/status",
   372                           entry->d_name);
   373             status = fopen (path, "r");
   374             if (status) {
   375                 name[0] = '\0';
   376                 fscanf (status, "Name: %s", name);
   377                 if (SDL_strcmp (name, wanted_name) == 0) {
   378                     pid = SDL_atoi (entry->d_name);
   379                 }
   380                 fclose (status);
   381             }
   382         }
   383     }
   384     return pid;
   385 }
   386 
   387 /* Returns true if /dev/gpmdata is being written to by gpm */
   388 static int
   389 gpm_available (char *proto, size_t protolen)
   390 {
   391     int available;
   392     DIR *proc;
   393     int pid;
   394     int cmdline, len, arglen;
   395     char path[PATH_MAX];
   396     char args[PATH_MAX], *arg;
   397 
   398     /* Don't bother looking if the fifo isn't there */
   399 #ifdef DEBUG_MOUSE
   400     fprintf (stderr, "testing gpm\n");
   401 #endif
   402     if (access (GPM_NODE_FIFO, F_OK) < 0) {
   403         return (0);
   404     }
   405 
   406     available = 0;
   407     proc = opendir ("/proc");
   408     if (proc) {
   409         char raw_proto[10] = { '\0' };
   410         char repeat_proto[10] = { '\0' };
   411         while (!available && (pid = find_pid (proc, "gpm")) > 0) {
   412             SDL_snprintf (path, SDL_arraysize (path), "/proc/%d/cmdline",
   413                           pid);
   414             cmdline = open (path, O_RDONLY, 0);
   415             if (cmdline >= 0) {
   416                 len = read (cmdline, args, sizeof (args));
   417                 arg = args;
   418                 while (len > 0) {
   419                     arglen = SDL_strlen (arg) + 1;
   420 #ifdef DEBUG_MOUSE
   421                     fprintf (stderr, "gpm arg %s len %d\n", arg, arglen);
   422 #endif
   423                     if (SDL_strcmp (arg, "-t") == 0) {
   424                         /* protocol string, keep it for later */
   425                         char *t, *s;
   426                         t = arg + arglen;
   427                         s = SDL_strchr (t, ' ');
   428                         if (s)
   429                             *s = 0;
   430                         SDL_strlcpy (raw_proto, t, SDL_arraysize (raw_proto));
   431                         if (s)
   432                             *s = ' ';
   433                     }
   434                     if (SDL_strncmp (arg, "-R", 2) == 0) {
   435                         char *t, *s;
   436                         available = 1;
   437                         t = arg + 2;
   438                         s = SDL_strchr (t, ' ');
   439                         if (s)
   440                             *s = 0;
   441                         SDL_strlcpy (repeat_proto, t,
   442                                      SDL_arraysize (repeat_proto));
   443                         if (s)
   444                             *s = ' ';
   445                     }
   446                     len -= arglen;
   447                     arg += arglen;
   448                 }
   449                 close (cmdline);
   450             }
   451         }
   452         closedir (proc);
   453 
   454         if (available) {
   455             if (SDL_strcmp (repeat_proto, "raw") == 0) {
   456                 SDL_strlcpy (proto, raw_proto, protolen);
   457             } else if (*repeat_proto) {
   458                 SDL_strlcpy (proto, repeat_proto, protolen);
   459             } else {
   460                 SDL_strlcpy (proto, "msc", protolen);
   461             }
   462         }
   463     }
   464     return available;
   465 }
   466 
   467 
   468 /* rcg06112001 Set up IMPS/2 mode, if possible. This gives
   469  *  us access to the mousewheel, etc. Returns zero if
   470  *  writes to device failed, but you still need to query the
   471  *  device to see which mode it's actually in.
   472  */
   473 static int
   474 set_imps2_mode (int fd)
   475 {
   476     /* If you wanted to control the mouse mode (and we do :)  ) ...
   477        Set IMPS/2 protocol:
   478        {0xf3,200,0xf3,100,0xf3,80}
   479        Reset mouse device:
   480        {0xFF}
   481      */
   482     Uint8 set_imps2[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
   483     /*Uint8 reset = 0xff; */
   484     fd_set fdset;
   485     struct timeval tv;
   486     int retval = 0;
   487 
   488     if (write (fd, &set_imps2, sizeof (set_imps2)) == sizeof (set_imps2)) {
   489         /* Don't reset it, that'll clear IMPS/2 mode on some mice
   490            if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
   491            retval = 1;
   492            }
   493          */
   494     }
   495 
   496     /* Get rid of any chatter from the above */
   497     FD_ZERO (&fdset);
   498     FD_SET (fd, &fdset);
   499     tv.tv_sec = 0;
   500     tv.tv_usec = 0;
   501     while (select (fd + 1, &fdset, 0, 0, &tv) > 0) {
   502         char temp[32];
   503         read (fd, temp, sizeof (temp));
   504     }
   505 
   506     return retval;
   507 }
   508 
   509 
   510 /* Returns true if the mouse uses the IMPS/2 protocol */
   511 static int
   512 detect_imps2 (int fd)
   513 {
   514     int imps2;
   515 
   516     imps2 = 0;
   517 
   518     if (SDL_getenv ("SDL_MOUSEDEV_IMPS2")) {
   519         imps2 = 1;
   520     }
   521     if (!imps2) {
   522         Uint8 query_ps2 = 0xF2;
   523         fd_set fdset;
   524         struct timeval tv;
   525 
   526         /* Get rid of any mouse motion noise */
   527         FD_ZERO (&fdset);
   528         FD_SET (fd, &fdset);
   529         tv.tv_sec = 0;
   530         tv.tv_usec = 0;
   531         while (select (fd + 1, &fdset, 0, 0, &tv) > 0) {
   532             char temp[32];
   533             read (fd, temp, sizeof (temp));
   534         }
   535 
   536         /* Query for the type of mouse protocol */
   537         if (write (fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
   538             Uint8 ch = 0;
   539 
   540             /* Get the mouse protocol response */
   541             do {
   542                 FD_ZERO (&fdset);
   543                 FD_SET (fd, &fdset);
   544                 tv.tv_sec = 1;
   545                 tv.tv_usec = 0;
   546                 if (select (fd + 1, &fdset, 0, 0, &tv) < 1) {
   547                     break;
   548                 }
   549             }
   550             while ((read (fd, &ch, sizeof (ch)) == sizeof (ch)) &&
   551                    ((ch == 0xFA) || (ch == 0xAA)));
   552 
   553             /* Experimental values (Logitech wheelmouse) */
   554 #ifdef DEBUG_MOUSE
   555             fprintf (stderr, "Last mouse mode: 0x%x\n", ch);
   556 #endif
   557             if ((ch == 3) || (ch == 4)) {
   558                 imps2 = 1;
   559             }
   560         }
   561     }
   562     return imps2;
   563 }
   564 
   565 int
   566 FB_OpenMouse (_THIS)
   567 {
   568     int i;
   569     const char *mousedev;
   570     const char *mousedrv;
   571 
   572     mousedrv = SDL_getenv ("SDL_MOUSEDRV");
   573     mousedev = SDL_getenv ("SDL_MOUSEDEV");
   574     mouse_fd = -1;
   575 
   576 #if SDL_INPUT_TSLIB
   577     if (mousedrv && (SDL_strcmp (mousedrv, "TSLIB") == 0)) {
   578         if (mousedev == NULL)
   579             mousedev = SDL_getenv ("TSLIB_TSDEVICE");
   580         if (mousedev != NULL) {
   581             ts_dev = ts_open (mousedev, 1);
   582             if ((ts_dev != NULL) && (ts_config (ts_dev) >= 0)) {
   583 #ifdef DEBUG_MOUSE
   584                 fprintf (stderr, "Using tslib touchscreen\n");
   585 #endif
   586                 mouse_drv = MOUSE_TSLIB;
   587                 mouse_fd = ts_fd (ts_dev);
   588                 return mouse_fd;
   589             }
   590         }
   591         mouse_drv = MOUSE_NONE;
   592         return mouse_fd;
   593     }
   594 #endif /* SDL_INPUT_TSLIB */
   595 
   596     /* ELO TOUCHSCREEN SUPPORT */
   597 
   598     if (mousedrv && (SDL_strcmp (mousedrv, "ELO") == 0)) {
   599         mouse_fd = open (mousedev, O_RDWR);
   600         if (mouse_fd >= 0) {
   601             if (eloInitController (mouse_fd)) {
   602 #ifdef DEBUG_MOUSE
   603                 fprintf (stderr, "Using ELO touchscreen\n");
   604 #endif
   605                 mouse_drv = MOUSE_ELO;
   606             }
   607 
   608         } else if (mouse_fd < 0) {
   609             mouse_drv = MOUSE_NONE;
   610         }
   611 
   612         return (mouse_fd);
   613     }
   614 
   615     /* STD MICE */
   616 
   617     if (mousedev == NULL) {
   618         /* FIXME someday... allow multiple mice in this driver */
   619         static const char *ps2mice[] = {
   620             "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
   621         };
   622         /* First try to use GPM in repeater mode */
   623         if (mouse_fd < 0) {
   624             char proto[10];
   625             if (gpm_available (proto, SDL_arraysize (proto))) {
   626                 mouse_fd = open (GPM_NODE_FIFO, O_RDONLY, 0);
   627                 if (mouse_fd >= 0) {
   628                     if (SDL_strcmp (proto, "msc") == 0) {
   629                         mouse_drv = MOUSE_MSC;
   630                     } else if (SDL_strcmp (proto, "ps2") == 0) {
   631                         mouse_drv = MOUSE_PS2;
   632                     } else if (SDL_strcmp (proto, "imps2") == 0) {
   633                         mouse_drv = MOUSE_IMPS2;
   634                     } else if (SDL_strcmp (proto, "ms") == 0 ||
   635                                SDL_strcmp (proto, "bare") == 0) {
   636                         mouse_drv = MOUSE_MS;
   637                     } else if (SDL_strcmp (proto, "bm") == 0) {
   638                         mouse_drv = MOUSE_BM;
   639                     } else {
   640                         /* Unknown protocol... */
   641 #ifdef DEBUG_MOUSE
   642                         fprintf (stderr,
   643                                  "GPM mouse using unknown protocol = %s\n",
   644                                  proto);
   645 #endif
   646                         close (mouse_fd);
   647                         mouse_fd = -1;
   648                     }
   649                 }
   650 #ifdef DEBUG_MOUSE
   651                 if (mouse_fd >= 0) {
   652                     fprintf (stderr,
   653                              "Using GPM mouse, protocol = %s\n", proto);
   654                 }
   655 #endif /* DEBUG_MOUSE */
   656             }
   657         }
   658         /* Now try to use a modern PS/2 mouse */
   659         for (i = 0; (mouse_fd < 0) && ps2mice[i]; ++i) {
   660             mouse_fd = open (ps2mice[i], O_RDWR, 0);
   661             if (mouse_fd < 0) {
   662                 mouse_fd = open (ps2mice[i], O_RDONLY, 0);
   663             }
   664             if (mouse_fd >= 0) {
   665                 /* rcg06112001 Attempt to set IMPS/2 mode */
   666                 set_imps2_mode (mouse_fd);
   667                 if (detect_imps2 (mouse_fd)) {
   668 #ifdef DEBUG_MOUSE
   669                     fprintf (stderr, "Using IMPS2 mouse\n");
   670 #endif
   671                     mouse_drv = MOUSE_IMPS2;
   672                 } else {
   673 #ifdef DEBUG_MOUSE
   674                     fprintf (stderr, "Using PS2 mouse\n");
   675 #endif
   676                     mouse_drv = MOUSE_PS2;
   677                 }
   678             }
   679         }
   680         /* Next try to use a PPC ADB port mouse */
   681         if (mouse_fd < 0) {
   682             mouse_fd = open ("/dev/adbmouse", O_RDONLY, 0);
   683             if (mouse_fd >= 0) {
   684 #ifdef DEBUG_MOUSE
   685                 fprintf (stderr, "Using ADB mouse\n");
   686 #endif
   687                 mouse_drv = MOUSE_BM;
   688             }
   689         }
   690     }
   691     /* Default to a serial Microsoft mouse */
   692     if (mouse_fd < 0) {
   693         if (mousedev == NULL) {
   694             mousedev = "/dev/mouse";
   695         }
   696         mouse_fd = open (mousedev, O_RDONLY, 0);
   697         if (mouse_fd >= 0) {
   698             struct termios mouse_termios;
   699 
   700             /* Set the sampling speed to 1200 baud */
   701             tcgetattr (mouse_fd, &mouse_termios);
   702             mouse_termios.c_iflag = IGNBRK | IGNPAR;
   703             mouse_termios.c_oflag = 0;
   704             mouse_termios.c_lflag = 0;
   705             mouse_termios.c_line = 0;
   706             mouse_termios.c_cc[VTIME] = 0;
   707             mouse_termios.c_cc[VMIN] = 1;
   708             mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
   709             mouse_termios.c_cflag |= CS8;
   710             mouse_termios.c_cflag |= B1200;
   711             tcsetattr (mouse_fd, TCSAFLUSH, &mouse_termios);
   712             if (mousedrv && (SDL_strcmp (mousedrv, "PS2") == 0)) {
   713 #ifdef DEBUG_MOUSE
   714                 fprintf (stderr,
   715                          "Using (user specified) PS2 mouse on %s\n",
   716                          mousedev);
   717 #endif
   718                 mouse_drv = MOUSE_PS2;
   719             } else {
   720 #ifdef DEBUG_MOUSE
   721                 fprintf (stderr, "Using (default) MS mouse on %s\n",
   722                          mousedev);
   723 #endif
   724                 mouse_drv = MOUSE_MS;
   725             }
   726         }
   727     }
   728     if (mouse_fd < 0) {
   729         mouse_drv = MOUSE_NONE;
   730     }
   731     return (mouse_fd);
   732 }
   733 
   734 static int posted = 0;
   735 
   736 void
   737 FB_vgamousecallback (int button, int relative, int dx, int dy)
   738 {
   739     int button_1, button_3;
   740     int button_state;
   741     int state_changed;
   742     int i;
   743     Uint8 state;
   744 
   745     if (dx || dy) {
   746         posted += SDL_PrivateMouseMotion (0, relative, dx, dy);
   747     }
   748 
   749     /* Swap button 1 and 3 */
   750     button_1 = (button & 0x04) >> 2;
   751     button_3 = (button & 0x01) << 2;
   752     button &= ~0x05;
   753     button |= (button_1 | button_3);
   754 
   755     /* See what changed */
   756     button_state = SDL_GetMouseState (NULL, NULL);
   757     state_changed = button_state ^ button;
   758     for (i = 0; i < 8; ++i) {
   759         if (state_changed & (1 << i)) {
   760             if (button & (1 << i)) {
   761                 state = SDL_PRESSED;
   762             } else {
   763                 state = SDL_RELEASED;
   764             }
   765             posted += SDL_PrivateMouseButton (state, i + 1, 0, 0);
   766         }
   767     }
   768 }
   769 
   770 /* Handle input from tslib */
   771 #if SDL_INPUT_TSLIB
   772 static void
   773 handle_tslib (_THIS)
   774 {
   775     struct ts_sample sample;
   776     int button;
   777 
   778     while (ts_read (ts_dev, &sample, 1) > 0) {
   779         button = (sample.pressure > 0) ? 1 : 0;
   780         button <<= 2;           /* must report it as button 3 */
   781         FB_vgamousecallback (button, 0, sample.x, sample.y);
   782     }
   783     return;
   784 }
   785 #endif /* SDL_INPUT_TSLIB */
   786 
   787 /* For now, use MSC, PS/2, and MS protocols
   788    Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
   789  */
   790 static void
   791 handle_mouse (_THIS)
   792 {
   793     static int start = 0;
   794     static unsigned char mousebuf[BUFSIZ];
   795     static int relative = 1;
   796 
   797     int i, nread;
   798     int button = 0;
   799     int dx = 0, dy = 0;
   800     int packetsize = 0;
   801     int realx, realy;
   802 
   803     /* Figure out the mouse packet size */
   804     switch (mouse_drv) {
   805     case MOUSE_NONE:
   806         /* Ack! */
   807         read (mouse_fd, mousebuf, BUFSIZ);
   808         return;
   809     case MOUSE_MSC:
   810         packetsize = 5;
   811         break;
   812     case MOUSE_IMPS2:
   813         packetsize = 4;
   814         break;
   815     case MOUSE_PS2:
   816     case MOUSE_MS:
   817     case MOUSE_BM:
   818         packetsize = 3;
   819         break;
   820     case MOUSE_ELO:
   821         /* try to read the next packet */
   822         if (eloReadPosition
   823             (this, mouse_fd, &dx, &dy, &button, &realx, &realy)) {
   824             button = (button & 0x01) << 2;
   825             FB_vgamousecallback (button, 0, dx, dy);
   826         }
   827         return;                 /* nothing left to do */
   828     case MOUSE_TSLIB:
   829 #if SDL_INPUT_TSLIB
   830         handle_tslib (this);
   831 #endif
   832         return;                 /* nothing left to do */
   833     default:
   834         /* Uh oh.. */
   835         packetsize = 0;
   836         break;
   837     }
   838 
   839     /* Special handling for the quite sensitive ELO controller */
   840     if (mouse_drv == MOUSE_ELO) {
   841 
   842     }
   843 
   844     /* Read as many packets as possible */
   845     nread = read (mouse_fd, &mousebuf[start], BUFSIZ - start);
   846     if (nread < 0) {
   847         return;
   848     }
   849     nread += start;
   850 #ifdef DEBUG_MOUSE
   851     fprintf (stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
   852 #endif
   853     for (i = 0; i < (nread - (packetsize - 1)); i += packetsize) {
   854         switch (mouse_drv) {
   855         case MOUSE_NONE:
   856             break;
   857         case MOUSE_MSC:
   858             /* MSC protocol has 0x80 in high byte */
   859             if ((mousebuf[i] & 0xF8) != 0x80) {
   860                 /* Go to next byte */
   861                 i -= (packetsize - 1);
   862                 continue;
   863             }
   864             /* Get current mouse state */
   865             button = (~mousebuf[i]) & 0x07;
   866             dx = (signed char) (mousebuf[i + 1]) +
   867                 (signed char) (mousebuf[i + 3]);
   868             dy = -((signed char) (mousebuf[i + 2]) +
   869                    (signed char) (mousebuf[i + 4]));
   870             break;
   871         case MOUSE_PS2:
   872             /* PS/2 protocol has nothing in high byte */
   873             if ((mousebuf[i] & 0xC0) != 0) {
   874                 /* Go to next byte */
   875                 i -= (packetsize - 1);
   876                 continue;
   877             }
   878             /* Get current mouse state */
   879             button = (mousebuf[i] & 0x04) >> 1 |        /*Middle */
   880                 (mousebuf[i] & 0x02) >> 1 |     /*Right */
   881                 (mousebuf[i] & 0x01) << 2;      /*Left */
   882             dx = (mousebuf[i] & 0x10) ?
   883                 mousebuf[i + 1] - 256 : mousebuf[i + 1];
   884             dy = (mousebuf[i] & 0x20) ?
   885                 -(mousebuf[i + 2] - 256) : -mousebuf[i + 2];
   886             break;
   887         case MOUSE_IMPS2:
   888             /* Get current mouse state */
   889             button = (mousebuf[i] & 0x04) >> 1 |        /*Middle */
   890                 (mousebuf[i] & 0x02) >> 1 |     /*Right */
   891                 (mousebuf[i] & 0x01) << 2 |     /*Left */
   892                 (mousebuf[i] & 0x40) >> 3 |     /* 4 */
   893                 (mousebuf[i] & 0x80) >> 3;      /* 5 */
   894             dx = (mousebuf[i] & 0x10) ?
   895                 mousebuf[i + 1] - 256 : mousebuf[i + 1];
   896             dy = (mousebuf[i] & 0x20) ?
   897                 -(mousebuf[i + 2] - 256) : -mousebuf[i + 2];
   898             switch (mousebuf[i + 3] & 0x0F) {
   899             case 0x0E:         /* DX = +1 */
   900             case 0x02:         /* DX = -1 */
   901                 break;
   902             case 0x0F:         /* DY = +1 (map button 4) */
   903                 FB_vgamousecallback (button | (1 << 3), 1, 0, 0);
   904                 break;
   905             case 0x01:         /* DY = -1 (map button 5) */
   906                 FB_vgamousecallback (button | (1 << 4), 1, 0, 0);
   907                 break;
   908             }
   909             break;
   910         case MOUSE_MS:
   911             /* Microsoft protocol has 0x40 in high byte */
   912             if ((mousebuf[i] & 0x40) != 0x40) {
   913                 /* Go to next byte */
   914                 i -= (packetsize - 1);
   915                 continue;
   916             }
   917             /* Get current mouse state */
   918             button = ((mousebuf[i] & 0x20) >> 3) |
   919                 ((mousebuf[i] & 0x10) >> 4);
   920             dx = (signed char) (((mousebuf[i] & 0x03) << 6) |
   921                                 (mousebuf[i + 1] & 0x3F));
   922             dy = (signed char) (((mousebuf[i] & 0x0C) << 4) |
   923                                 (mousebuf[i + 2] & 0x3F));
   924             break;
   925         case MOUSE_BM:
   926             /* BusMouse protocol has 0xF8 in high byte */
   927             if ((mousebuf[i] & 0xF8) != 0x80) {
   928                 /* Go to next byte */
   929                 i -= (packetsize - 1);
   930                 continue;
   931             }
   932             /* Get current mouse state */
   933             button = (~mousebuf[i]) & 0x07;
   934             dx = (signed char) mousebuf[i + 1];
   935             dy = -(signed char) mousebuf[i + 2];
   936             break;
   937         default:
   938             /* Uh oh.. */
   939             dx = 0;
   940             dy = 0;
   941             break;
   942         }
   943         FB_vgamousecallback (button, relative, dx, dy);
   944     }
   945     if (i < nread) {
   946         SDL_memcpy (mousebuf, &mousebuf[i], (nread - i));
   947         start = (nread - i);
   948     } else {
   949         start = 0;
   950     }
   951     return;
   952 }
   953 
   954 /* Handle switching to another VC, returns when our VC is back */
   955 static void
   956 switch_vt_prep (_THIS)
   957 {
   958     SDL_Surface *screen = SDL_VideoSurface;
   959 
   960     SDL_PrivateAppActive (0,
   961                           (SDL_APPACTIVE | SDL_APPINPUTFOCUS |
   962                            SDL_APPMOUSEFOCUS));
   963 
   964     /* Save the contents of the screen, and go to text mode */
   965     wait_idle (this);
   966     screen_arealen = ((screen->h + (2 * this->offset_y)) * screen->pitch);
   967     screen_contents = (Uint8 *) SDL_malloc (screen_arealen);
   968     if (screen_contents) {
   969         SDL_memcpy (screen_contents, screen->pixels, screen_arealen);
   970     }
   971     FB_SavePaletteTo (this, 256, screen_palette);
   972     ioctl (console_fd, FBIOGET_VSCREENINFO, &screen_vinfo);
   973     ioctl (keyboard_fd, KDSETMODE, KD_TEXT);
   974     ioctl (keyboard_fd, VT_UNLOCKSWITCH, 1);
   975 }
   976 static void
   977 switch_vt_done (_THIS)
   978 {
   979     SDL_Surface *screen = SDL_VideoSurface;
   980 
   981     /* Restore graphics mode and the contents of the screen */
   982     ioctl (keyboard_fd, VT_LOCKSWITCH, 1);
   983     ioctl (keyboard_fd, KDSETMODE, KD_GRAPHICS);
   984     ioctl (console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo);
   985     FB_RestorePaletteFrom (this, 256, screen_palette);
   986     if (screen_contents) {
   987         SDL_memcpy (screen->pixels, screen_contents, screen_arealen);
   988         SDL_free (screen_contents);
   989         screen_contents = NULL;
   990     }
   991 
   992     /* Get updates to the shadow surface while switched away */
   993     if (SDL_ShadowSurface) {
   994         SDL_UpdateRect (SDL_ShadowSurface, 0, 0, 0, 0);
   995     }
   996 
   997     SDL_PrivateAppActive (1,
   998                           (SDL_APPACTIVE | SDL_APPINPUTFOCUS |
   999                            SDL_APPMOUSEFOCUS));
  1000 }
  1001 static void
  1002 switch_vt (_THIS, unsigned short which)
  1003 {
  1004     struct vt_stat vtstate;
  1005 
  1006     /* Figure out whether or not we're switching to a new console */
  1007     if ((ioctl (keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
  1008         (which == vtstate.v_active)) {
  1009         return;
  1010     }
  1011 
  1012     /* New console, switch to it */
  1013     SDL_mutexP (hw_lock);
  1014     switch_vt_prep (this);
  1015     if (ioctl (keyboard_fd, VT_ACTIVATE, which) == 0) {
  1016         ioctl (keyboard_fd, VT_WAITACTIVE, which);
  1017         switched_away = 1;
  1018     } else {
  1019         switch_vt_done (this);
  1020     }
  1021     SDL_mutexV (hw_lock);
  1022 }
  1023 
  1024 static void
  1025 handle_keyboard (_THIS)
  1026 {
  1027     unsigned char keybuf[BUFSIZ];
  1028     int i, nread;
  1029     int pressed;
  1030     int scancode;
  1031     SDL_keysym keysym;
  1032 
  1033     nread = read (keyboard_fd, keybuf, BUFSIZ);
  1034     for (i = 0; i < nread; ++i) {
  1035         scancode = keybuf[i] & 0x7F;
  1036         if (keybuf[i] & 0x80) {
  1037             pressed = SDL_RELEASED;
  1038         } else {
  1039             pressed = SDL_PRESSED;
  1040         }
  1041         TranslateKey (scancode, &keysym);
  1042         /* Handle Ctrl-Alt-FN for vt switch */
  1043         switch (keysym.sym) {
  1044         case SDLK_F1:
  1045         case SDLK_F2:
  1046         case SDLK_F3:
  1047         case SDLK_F4:
  1048         case SDLK_F5:
  1049         case SDLK_F6:
  1050         case SDLK_F7:
  1051         case SDLK_F8:
  1052         case SDLK_F9:
  1053         case SDLK_F10:
  1054         case SDLK_F11:
  1055         case SDLK_F12:
  1056             if ((SDL_GetModState () & KMOD_CTRL) &&
  1057                 (SDL_GetModState () & KMOD_ALT)) {
  1058                 if (pressed) {
  1059                     switch_vt (this, (keysym.sym - SDLK_F1) + 1);
  1060                 }
  1061                 break;
  1062             }
  1063             /* Fall through to normal processing */
  1064         default:
  1065             posted += SDL_PrivateKeyboard (pressed, &keysym);
  1066             break;
  1067         }
  1068     }
  1069 }
  1070 
  1071 void
  1072 FB_PumpEvents (_THIS)
  1073 {
  1074     fd_set fdset;
  1075     int max_fd;
  1076     static struct timeval zero;
  1077 
  1078     do {
  1079         if (switched_away) {
  1080             struct vt_stat vtstate;
  1081 
  1082             SDL_mutexP (hw_lock);
  1083             if ((ioctl (keyboard_fd, VT_GETSTATE, &vtstate) == 0) &&
  1084                 vtstate.v_active == current_vt) {
  1085                 switched_away = 0;
  1086                 switch_vt_done (this);
  1087             }
  1088             SDL_mutexV (hw_lock);
  1089         }
  1090 
  1091         posted = 0;
  1092 
  1093         FD_ZERO (&fdset);
  1094         max_fd = 0;
  1095         if (keyboard_fd >= 0) {
  1096             FD_SET (keyboard_fd, &fdset);
  1097             if (max_fd < keyboard_fd) {
  1098                 max_fd = keyboard_fd;
  1099             }
  1100         }
  1101         if (mouse_fd >= 0) {
  1102             FD_SET (mouse_fd, &fdset);
  1103             if (max_fd < mouse_fd) {
  1104                 max_fd = mouse_fd;
  1105             }
  1106         }
  1107         if (select (max_fd + 1, &fdset, NULL, NULL, &zero) > 0) {
  1108             if (keyboard_fd >= 0) {
  1109                 if (FD_ISSET (keyboard_fd, &fdset)) {
  1110                     handle_keyboard (this);
  1111                 }
  1112             }
  1113             if (mouse_fd >= 0) {
  1114                 if (FD_ISSET (mouse_fd, &fdset)) {
  1115                     handle_mouse (this);
  1116                 }
  1117             }
  1118         }
  1119     }
  1120     while (posted);
  1121 }
  1122 
  1123 void
  1124 FB_InitOSKeymap (_THIS)
  1125 {
  1126     int i;
  1127 
  1128     /* Initialize the Linux key translation table */
  1129 
  1130     /* First get the ascii keys and others not well handled */
  1131     for (i = 0; i < SDL_arraysize (keymap); ++i) {
  1132         switch (i) {
  1133             /* These aren't handled by the x86 kernel keymapping (?) */
  1134         case SCANCODE_PRINTSCREEN:
  1135             keymap[i] = SDLK_PRINT;
  1136             break;
  1137         case SCANCODE_BREAK:
  1138             keymap[i] = SDLK_BREAK;
  1139             break;
  1140         case SCANCODE_BREAK_ALTERNATIVE:
  1141             keymap[i] = SDLK_PAUSE;
  1142             break;
  1143         case SCANCODE_LEFTSHIFT:
  1144             keymap[i] = SDLK_LSHIFT;
  1145             break;
  1146         case SCANCODE_RIGHTSHIFT:
  1147             keymap[i] = SDLK_RSHIFT;
  1148             break;
  1149         case SCANCODE_LEFTCONTROL:
  1150             keymap[i] = SDLK_LCTRL;
  1151             break;
  1152         case SCANCODE_RIGHTCONTROL:
  1153             keymap[i] = SDLK_RCTRL;
  1154             break;
  1155         case SCANCODE_RIGHTWIN:
  1156             keymap[i] = SDLK_RSUPER;
  1157             break;
  1158         case SCANCODE_LEFTWIN:
  1159             keymap[i] = SDLK_LSUPER;
  1160             break;
  1161         case SCANCODE_LEFTALT:
  1162             keymap[i] = SDLK_LALT;
  1163             break;
  1164         case SCANCODE_RIGHTALT:
  1165             keymap[i] = SDLK_RALT;
  1166             break;
  1167         case 127:
  1168             keymap[i] = SDLK_MENU;
  1169             break;
  1170             /* this should take care of all standard ascii keys */
  1171         default:
  1172             keymap[i] = KVAL (vga_keymap[0][i]);
  1173             break;
  1174         }
  1175     }
  1176     for (i = 0; i < SDL_arraysize (keymap); ++i) {
  1177         switch (keymap_temp[i]) {
  1178         case K_F1:
  1179             keymap[i] = SDLK_F1;
  1180             break;
  1181         case K_F2:
  1182             keymap[i] = SDLK_F2;
  1183             break;
  1184         case K_F3:
  1185             keymap[i] = SDLK_F3;
  1186             break;
  1187         case K_F4:
  1188             keymap[i] = SDLK_F4;
  1189             break;
  1190         case K_F5:
  1191             keymap[i] = SDLK_F5;
  1192             break;
  1193         case K_F6:
  1194             keymap[i] = SDLK_F6;
  1195             break;
  1196         case K_F7:
  1197             keymap[i] = SDLK_F7;
  1198             break;
  1199         case K_F8:
  1200             keymap[i] = SDLK_F8;
  1201             break;
  1202         case K_F9:
  1203             keymap[i] = SDLK_F9;
  1204             break;
  1205         case K_F10:
  1206             keymap[i] = SDLK_F10;
  1207             break;
  1208         case K_F11:
  1209             keymap[i] = SDLK_F11;
  1210             break;
  1211         case K_F12:
  1212             keymap[i] = SDLK_F12;
  1213             break;
  1214 
  1215         case K_DOWN:
  1216             keymap[i] = SDLK_DOWN;
  1217             break;
  1218         case K_LEFT:
  1219             keymap[i] = SDLK_LEFT;
  1220             break;
  1221         case K_RIGHT:
  1222             keymap[i] = SDLK_RIGHT;
  1223             break;
  1224         case K_UP:
  1225             keymap[i] = SDLK_UP;
  1226             break;
  1227 
  1228         case K_P0:
  1229             keymap[i] = SDLK_KP0;
  1230             break;
  1231         case K_P1:
  1232             keymap[i] = SDLK_KP1;
  1233             break;
  1234         case K_P2:
  1235             keymap[i] = SDLK_KP2;
  1236             break;
  1237         case K_P3:
  1238             keymap[i] = SDLK_KP3;
  1239             break;
  1240         case K_P4:
  1241             keymap[i] = SDLK_KP4;
  1242             break;
  1243         case K_P5:
  1244             keymap[i] = SDLK_KP5;
  1245             break;
  1246         case K_P6:
  1247             keymap[i] = SDLK_KP6;
  1248             break;
  1249         case K_P7:
  1250             keymap[i] = SDLK_KP7;
  1251             break;
  1252         case K_P8:
  1253             keymap[i] = SDLK_KP8;
  1254             break;
  1255         case K_P9:
  1256             keymap[i] = SDLK_KP9;
  1257             break;
  1258         case K_PPLUS:
  1259             keymap[i] = SDLK_KP_PLUS;
  1260             break;
  1261         case K_PMINUS:
  1262             keymap[i] = SDLK_KP_MINUS;
  1263             break;
  1264         case K_PSTAR:
  1265             keymap[i] = SDLK_KP_MULTIPLY;
  1266             break;
  1267         case K_PSLASH:
  1268             keymap[i] = SDLK_KP_DIVIDE;
  1269             break;
  1270         case K_PENTER:
  1271             keymap[i] = SDLK_KP_ENTER;
  1272             break;
  1273         case K_PDOT:
  1274             keymap[i] = SDLK_KP_PERIOD;
  1275             break;
  1276 
  1277         case K_SHIFT:
  1278             if (keymap[i] != SDLK_RSHIFT)
  1279                 keymap[i] = SDLK_LSHIFT;
  1280             break;
  1281         case K_SHIFTL:
  1282             keymap[i] = SDLK_LSHIFT;
  1283             break;
  1284         case K_SHIFTR:
  1285             keymap[i] = SDLK_RSHIFT;
  1286             break;
  1287         case K_CTRL:
  1288             if (keymap[i] != SDLK_RCTRL)
  1289                 keymap[i] = SDLK_LCTRL;
  1290             break;
  1291         case K_CTRLL:
  1292             keymap[i] = SDLK_LCTRL;
  1293             break;
  1294         case K_CTRLR:
  1295             keymap[i] = SDLK_RCTRL;
  1296             break;
  1297         case K_ALT:
  1298             keymap[i] = SDLK_LALT;
  1299             break;
  1300         case K_ALTGR:
  1301             keymap[i] = SDLK_RALT;
  1302             break;
  1303 
  1304         case K_INSERT:
  1305             keymap[i] = SDLK_INSERT;
  1306             break;
  1307         case K_REMOVE:
  1308             keymap[i] = SDLK_DELETE;
  1309             break;
  1310         case K_PGUP:
  1311             keymap[i] = SDLK_PAGEUP;
  1312             break;
  1313         case K_PGDN:
  1314             keymap[i] = SDLK_PAGEDOWN;
  1315             break;
  1316         case K_FIND:
  1317             keymap[i] = SDLK_HOME;
  1318             break;
  1319         case K_SELECT:
  1320             keymap[i] = SDLK_END;
  1321             break;
  1322 
  1323         case K_NUM:
  1324             keymap[i] = SDLK_NUMLOCK;
  1325             break;
  1326         case K_CAPS:
  1327             keymap[i] = SDLK_CAPSLOCK;
  1328             break;
  1329 
  1330         case K_F13:
  1331             keymap[i] = SDLK_PRINT;
  1332             break;
  1333         case K_HOLD:
  1334             keymap[i] = SDLK_SCROLLOCK;
  1335             break;
  1336         case K_PAUSE:
  1337             keymap[i] = SDLK_PAUSE;
  1338             break;
  1339 
  1340         case 127:
  1341             keymap[i] = SDLK_BACKSPACE;
  1342             break;
  1343 
  1344         default:
  1345             break;
  1346         }
  1347     }
  1348 }
  1349 
  1350 static SDL_keysym *
  1351 TranslateKey (int scancode, SDL_keysym * keysym)
  1352 {
  1353     /* Set the keysym information */
  1354     keysym->scancode = scancode;
  1355     keysym->sym = keymap[scancode];
  1356     keysym->mod = KMOD_NONE;
  1357 
  1358     /* If UNICODE is on, get the UNICODE value for the key */
  1359     keysym->unicode = 0;
  1360     if (SDL_TranslateUNICODE) {
  1361         int map;
  1362         SDLMod modstate;
  1363 
  1364         modstate = SDL_GetModState ();
  1365         map = 0;
  1366         if (modstate & KMOD_SHIFT) {
  1367             map |= (1 << KG_SHIFT);
  1368         }
  1369         if (modstate & KMOD_CTRL) {
  1370             map |= (1 << KG_CTRL);
  1371         }
  1372         if (modstate & KMOD_LALT) {
  1373             map |= (1 << KG_ALT);
  1374         }
  1375         if (modstate & KMOD_RALT) {
  1376             map |= (1 << KG_ALTGR);
  1377         }
  1378         if (KTYP (vga_keymap[map][scancode]) == KT_LETTER) {
  1379             if (modstate & KMOD_CAPS) {
  1380                 map ^= (1 << KG_SHIFT);
  1381             }
  1382         }
  1383         if (KTYP (vga_keymap[map][scancode]) == KT_PAD) {
  1384             if (modstate & KMOD_NUM) {
  1385                 keysym->unicode = KVAL (vga_keymap[map][scancode]);
  1386             }
  1387         } else {
  1388             keysym->unicode = KVAL (vga_keymap[map][scancode]);
  1389         }
  1390     }
  1391     return (keysym);
  1392 }
  1393 
  1394 /* vi: set ts=4 sw=4 expandtab: */