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