146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Handle the event stream, converting console events into SDL events */
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/types.h>
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/time.h>
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/ioctl.h>
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <unistd.h>
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <fcntl.h>
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <errno.h>
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <limits.h>
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* For parsing /proc */
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <dirent.h>
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <ctype.h>
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <linux/vt.h>
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <linux/kd.h>
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <linux/keyboard.h>
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_mutex.h"
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_sysvideo.h"
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../../events/SDL_sysevents.h"
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../../events/SDL_events_c.h"
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_gsvideo.h"
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_gsevents_c.h"
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_gskeys.h"
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifndef GPM_NODE_FIFO
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define GPM_NODE_FIFO	"/dev/gpmdata"
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The translation tables from a console scancode to a SDL keysym */
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDLKey keymap[128];
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint16 keymap_temp[128]; /* only used at startup */
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Ugh, we have to duplicate the kernel's keysym mapping code...
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   Oh, it's not so bad. :-)
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   FIXME: Add keyboard LED handling code
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void GS_vgainitkeymaps(int fd)
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct kbentry entry;
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int map, i;
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Don't do anything if we are passed a closed keyboard */
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( fd < 0 ) {
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return;
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Load all the keysym mappings */
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; i<NR_KEYS; ++i ) {
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			entry.kb_table = map;
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			entry.kb_index = i;
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* fill keytemp. This replaces SDL_fbkeys.h */
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( (map == 0) && (i<128) ) {
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					keymap_temp[i] = entry.kb_value;
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* The "Enter" key is a special case */
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( entry.kb_value == K_ENTER ) {
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					entry.kb_value = K(KT_ASCII,13);
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Handle numpad specially as well */
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( KTYP(entry.kb_value) == KT_PAD ) {
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					switch ( entry.kb_value ) {
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P0:
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P1:
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P2:
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P3:
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P4:
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P5:
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P6:
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P7:
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P8:
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case K_P9:
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=entry.kb_value;
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]+= '0';
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PPLUS:
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,'+');
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PMINUS:
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,'-');
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PSTAR:
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,'*');
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PSLASH:
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,'/');
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PENTER:
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,'\r');
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PCOMMA:
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,',');
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner										case K_PDOT:
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						vga_keymap[map][i]=K(KT_ASCII,'.');
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					default:
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					}
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Do the normal key translation */
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( (KTYP(entry.kb_value) == KT_LATIN) ||
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					 (KTYP(entry.kb_value) == KT_ASCII) ||
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					 (KTYP(entry.kb_value) == KT_LETTER) ) {
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					vga_keymap[map][i] = entry.kb_value;
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint GS_InGraphicsMode(_THIS)
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint GS_EnterGraphicsMode(_THIS)
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct termios keyboard_termios;
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set medium-raw keyboard mode */
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) {
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Switch to the correct virtual terminal */
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( current_vt > 0 ) {
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			struct vt_stat vtstate;
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				saved_vt = vtstate.v_active;
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Set the terminal input mode */
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_SetError("Unable to get terminal attributes");
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( keyboard_fd > 0 ) {
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				close(keyboard_fd);
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			keyboard_fd = -1;
17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_SetError("Unable to get current keyboard mode");
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( keyboard_fd > 0 ) {
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				close(keyboard_fd);
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			keyboard_fd = -1;
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		keyboard_termios = saved_kbd_termios;
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		keyboard_termios.c_cc[VMIN] = 0;
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		keyboard_termios.c_cc[VTIME] = 0;
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			GS_CloseKeyboard(this);
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_SetError("Unable to set terminal attributes");
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* This will fail if we aren't root or this isn't our tty */
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			GS_CloseKeyboard(this);
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_SetError("Unable to set keyboard in raw mode");
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			GS_CloseKeyboard(this);
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_SetError("Unable to set keyboard in graphics mode");
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(keyboard_fd);
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid GS_LeaveGraphicsMode(_THIS)
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( GS_InGraphicsMode(this) ) {
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		saved_kbd_mode = -1;
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Head back over to the original virtual terminal */
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( saved_vt > 0 ) {
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid GS_CloseKeyboard(_THIS)
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( keyboard_fd >= 0 ) {
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		GS_LeaveGraphicsMode(this);
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( keyboard_fd > 0 ) {
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			close(keyboard_fd);
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	keyboard_fd = -1;
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint GS_OpenKeyboard(_THIS)
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Open only if not already opened */
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 	if ( keyboard_fd < 0 ) {
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int i, tty0_fd;
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Try to query for a free virtual terminal */
24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		tty0_fd = -1;
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			tty0_fd = open(tty0[i], O_WRONLY, 0);
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( tty0_fd < 0 ) {
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			tty0_fd = dup(0); /* Maybe stdin is a VT? */
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		ioctl(tty0_fd, VT_OPENQRY, &current_vt);
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		close(tty0_fd);
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( (geteuid() == 0) && (current_vt > 0) ) {
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {
25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				char vtpath[12];
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt);
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				keyboard_fd = open(vtpath, O_RDWR, 0);
25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_KEYBOARD
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				fprintf(stderr, "vtpath = %s, fd = %d\n",
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					vtpath, keyboard_fd);
26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* DEBUG_KEYBOARD */
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* This needs to be our controlling tty
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				   so that the kernel ioctl() calls work
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				*/
26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( keyboard_fd >= 0 ) {
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					tty0_fd = open("/dev/tty", O_RDWR, 0);
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					if ( tty0_fd >= 0 ) {
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						ioctl(tty0_fd, TIOCNOTTY, 0);
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						close(tty0_fd);
27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					}
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 		if ( keyboard_fd < 0 ) {
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Last resort, maybe our tty is a usable VT */
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			current_vt = 0;
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			keyboard_fd = open("/dev/tty", O_RDWR);
28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 		}
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_KEYBOARD
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		fprintf(stderr, "Current VT: %d\n", current_vt);
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 		saved_kbd_mode = -1;
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Make sure that our input is a console terminal */
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{ int dummy;
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			close(keyboard_fd);
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			keyboard_fd = -1;
29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_SetError("Unable to open a console terminal");
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  }
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Set up keymap */
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		GS_vgainitkeymaps(keyboard_fd);
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 	}
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 	return(keyboard_fd);
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic enum {
30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MOUSE_NONE = -1,
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MOUSE_GPM,	/* Note: GPM uses the MSC protocol */
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MOUSE_PS2,
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MOUSE_IMPS2,
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MOUSE_MS,
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MOUSE_BM,
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	NUM_MOUSE_DRVS
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} mouse_drv = MOUSE_NONE;
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid GS_CloseMouse(_THIS)
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( mouse_fd > 0 ) {
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		close(mouse_fd);
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mouse_fd = -1;
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Returns processes listed in /proc with the desired name */
32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int find_pid(DIR *proc, const char *wanted_name)
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct dirent *entry;
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int pid;
32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* First scan proc for the gpm process */
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pid = 0;
32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( isdigit(entry->d_name[0]) ) {
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			FILE *status;
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			char path[PATH_MAX];
33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			char name[PATH_MAX];
33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name);
33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			status=fopen(path, "r");
33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( status ) {
33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				name[0] = '\0';
33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				fscanf(status, "Name: %s", name);
33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( SDL_strcmp(name, wanted_name) == 0 ) {
33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					pid = atoi(entry->d_name);
34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				fclose(status);
34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return pid;
34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Returns true if /dev/gpmdata is being written to by gpm */
34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int gpm_available(void)
35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int available;
35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DIR *proc;
35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int pid;
35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int cmdline, len, arglen;
35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char path[PATH_MAX];
35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char args[PATH_MAX], *arg;
35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Don't bother looking if the fifo isn't there */
35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	available = 0;
36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	proc = opendir("/proc");
36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( proc ) {
36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while ( (pid=find_pid(proc, "gpm")) > 0 ) {
36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid);
36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cmdline = open(path, O_RDONLY, 0);
36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( cmdline >= 0 ) {
37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				len = read(cmdline, args, sizeof(args));
37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				arg = args;
37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				while ( len > 0 ) {
37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					if ( SDL_strcmp(arg, "-R") == 0 ) {
37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						available = 1;
37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					}
37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					arglen = SDL_strlen(arg)+1;
37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					len -= arglen;
37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					arg += arglen;
37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				close(cmdline);
38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		closedir(proc);
38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return available;
38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* rcg06112001 Set up IMPS/2 mode, if possible. This gives
39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *  us access to the mousewheel, etc. Returns zero if
39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *  writes to device failed, but you still need to query the
39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *  device to see which mode it's actually in.
39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int set_imps2_mode(int fd)
39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* If you wanted to control the mouse mode (and we do :)  ) ...
39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Set IMPS/2 protocol:
39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			{0xf3,200,0xf3,100,0xf3,80}
39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Reset mouse device:
40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			{0xFF}
40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*/
40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 reset = 0xff;
40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	fd_set fdset;
40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct timeval tv;
40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int retval = 0;
40746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
40946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			retval = 1;
41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
41346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Get rid of any chatter from the above */
41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	FD_ZERO(&fdset);
41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	FD_SET(fd, &fdset);
41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	tv.tv_sec = 0;
41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	tv.tv_usec = 0;
41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		char temp[32];
42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		read(fd, temp, sizeof(temp));
42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return retval;
42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
42846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Returns true if the mouse uses the IMPS/2 protocol */
42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int detect_imps2(int fd)
43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int imps2;
43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	imps2 = 0;
43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_getenv("SDL_MOUSEDEV_IMPS2") ) {
43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		imps2 = 1;
43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( ! imps2 ) {
43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Uint8 query_ps2 = 0xF2;
44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		fd_set fdset;
44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		struct timeval tv;
44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Get rid of any mouse motion noise */
44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		FD_ZERO(&fdset);
44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		FD_SET(fd, &fdset);
44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		tv.tv_sec = 0;
44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		tv.tv_usec = 0;
44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			char temp[32];
45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			read(fd, temp, sizeof(temp));
45146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   		/* Query for the type of mouse protocol */
45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   		if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   			Uint8 ch = 0;
45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Get the mouse protocol response */
45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			do {
45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				FD_ZERO(&fdset);
46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				FD_SET(fd, &fdset);
46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				tv.tv_sec = 1;
46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				tv.tv_usec = 0;
46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {
46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					break;
46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			          ((ch == 0xFA) || (ch == 0xAA)) );
46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Experimental values (Logitech wheelmouse) */
47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerfprintf(stderr, "Last mouse mode: 0x%x\n", ch);
47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( ch == 3 ) {
47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				imps2 = 1;
47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return imps2;
47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint GS_OpenMouse(_THIS)
48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	const char *mousedev;
48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	const char *mousedrv;
48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mousedrv = SDL_getenv("SDL_MOUSEDRV");
48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mousedev = SDL_getenv("SDL_MOUSEDEV");
48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mouse_fd = -1;
49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* STD MICE */
49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( mousedev == NULL ) {
49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* FIXME someday... allow multiple mice in this driver */
49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		char *ps2mice[] = {
49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		    "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		};
49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* First try to use GPM in repeater mode */
49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( mouse_fd < 0 ) {
50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( gpm_available() ) {
50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( mouse_fd >= 0 ) {
50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerfprintf(stderr, "Using GPM mouse\n");
50546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					mouse_drv = MOUSE_GPM;
50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Now try to use a modern PS/2 mouse */
51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) {
51246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_fd = open(ps2mice[i], O_RDWR, 0);
51346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if (mouse_fd < 0) {
51446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				mouse_fd = open(ps2mice[i], O_RDONLY, 0);
51546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
51646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if (mouse_fd >= 0) {
51746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* rcg06112001 Attempt to set IMPS/2 mode */
51846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( i == 0 ) {
51946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					set_imps2_mode(mouse_fd);
52046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
52146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if (detect_imps2(mouse_fd)) {
52246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
52346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerfprintf(stderr, "Using IMPS2 mouse\n");
52446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
52546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					mouse_drv = MOUSE_IMPS2;
52646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				} else {
52746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					mouse_drv = MOUSE_PS2;
52846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
52946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerfprintf(stderr, "Using PS2 mouse\n");
53046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
53146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
53246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
53346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
53446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Next try to use a PPC ADB port mouse */
53546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( mouse_fd < 0 ) {
53646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
53746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( mouse_fd >= 0 ) {
53846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
53946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerfprintf(stderr, "Using ADB mouse\n");
54046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
54146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				mouse_drv = MOUSE_BM;
54246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
54346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
54446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
54546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Default to a serial Microsoft mouse */
54646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( mouse_fd < 0 ) {
54746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( mousedev == NULL ) {
54846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mousedev = "/dev/mouse";
54946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
55046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		mouse_fd = open(mousedev, O_RDONLY, 0);
55146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( mouse_fd >= 0 ) {
55246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			struct termios mouse_termios;
55346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
55446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Set the sampling speed to 1200 baud */
55546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			tcgetattr(mouse_fd, &mouse_termios);
55646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_iflag = IGNBRK | IGNPAR;
55746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_oflag = 0;
55846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_lflag = 0;
55946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_line = 0;
56046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_cc[VTIME] = 0;
56146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_cc[VMIN] = 1;
56246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
56346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_cflag |= CS8;
56446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_termios.c_cflag |= B1200;
56546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
56646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
56746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerfprintf(stderr, "Using Microsoft mouse on %s\n", mousedev);
56846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
56946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mouse_drv = MOUSE_MS;
57046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
57146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
57246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( mouse_fd < 0 ) {
57346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		mouse_drv = MOUSE_NONE;
57446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
57546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(mouse_fd);
57646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
57746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
57846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int posted = 0;
57946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
58046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid GS_vgamousecallback(int button, int dx, int dy)
58146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
58246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int button_1, button_3;
58346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int button_state;
58446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int state_changed;
58546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
58646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Uint8 state;
58746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
58846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( dx || dy ) {
58946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		posted += SDL_PrivateMouseMotion(0, 1, dx, dy);
59046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
59146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
59246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Swap button 1 and 3 */
59346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	button_1 = (button & 0x04) >> 2;
59446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	button_3 = (button & 0x01) << 2;
59546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	button &= ~0x05;
59646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	button |= (button_1|button_3);
59746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
59846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* See what changed */
59946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	button_state = SDL_GetMouseState(NULL, NULL);
60046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	state_changed = button_state ^ button;
60146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( i=0; i<8; ++i ) {
60246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( state_changed & (1<<i) ) {
60346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( button & (1<<i) ) {
60446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				state = SDL_PRESSED;
60546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} else {
60646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				state = SDL_RELEASED;
60746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
60846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			posted += SDL_PrivateMouseButton(state, i+1, 0, 0);
60946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
61046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
61146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
61246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
61346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* For now, use GPM, PS/2, and MS protocols
61446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
61546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */
61646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void handle_mouse(_THIS)
61746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
61846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static int start = 0;
61946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static unsigned char mousebuf[BUFSIZ];
62046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i, nread;
62146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int button = 0;
62246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int dx = 0, dy = 0;
62346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int packetsize = 0;
62446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
62546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Figure out the mouse packet size */
62646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch (mouse_drv) {
62746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MOUSE_NONE:
62846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Ack! */
62946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			read(mouse_fd, mousebuf, BUFSIZ);
63046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return;
63146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MOUSE_GPM:
63246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			packetsize = 5;
63346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
63446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MOUSE_IMPS2:
63546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			packetsize = 4;
63646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
63746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MOUSE_PS2:
63846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MOUSE_MS:
63946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MOUSE_BM:
64046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			packetsize = 3;
64146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
64246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case NUM_MOUSE_DRVS:
64346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			/* Uh oh.. */
64446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			packetsize = 0;
64546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
64646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
64746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
64846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Read as many packets as possible */
64946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
65046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( nread < 0 ) {
65146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return;
65246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
65346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	nread += start;
65446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_MOUSE
65546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start);
65646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
65746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
65846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		switch (mouse_drv) {
65946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MOUSE_NONE:
66046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
66146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MOUSE_GPM:
66246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* GPM protocol has 0x80 in high byte */
66346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( (mousebuf[i] & 0xF8) != 0x80 ) {
66446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Go to next byte */
66546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					i -= (packetsize-1);
66646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					continue;
66746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
66846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Get current mouse state */
66946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				button = (~mousebuf[i]) & 0x07;
67046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dx =   (signed char)(mousebuf[i+1]) +
67146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				       (signed char)(mousebuf[i+3]);
67246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dy = -((signed char)(mousebuf[i+2]) +
67346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				       (signed char)(mousebuf[i+4]));
67446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
67546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MOUSE_PS2:
67646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* PS/2 protocol has nothing in high byte */
67746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( (mousebuf[i] & 0xC0) != 0 ) {
67846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Go to next byte */
67946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					i -= (packetsize-1);
68046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					continue;
68146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
68246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Get current mouse state */
68346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
68446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  			 (mousebuf[i] & 0x02) >> 1 | /*Right*/
68546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  			 (mousebuf[i] & 0x01) << 2;  /*Left*/
68646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		dx = (mousebuf[i] & 0x10) ?
68746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		      mousebuf[i+1] - 256 : mousebuf[i+1];
68846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		dy = (mousebuf[i] & 0x20) ?
68946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		      -(mousebuf[i+2] - 256) : -mousebuf[i+2];
69046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
69146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MOUSE_IMPS2:
69246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Get current mouse state */
69346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
69446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  			 (mousebuf[i] & 0x02) >> 1 | /*Right*/
69546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  			 (mousebuf[i] & 0x01) << 2 | /*Left*/
69646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  			 (mousebuf[i] & 0x40) >> 3 | /* 4 */
69746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  			 (mousebuf[i] & 0x80) >> 3;  /* 5 */
69846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		dx = (mousebuf[i] & 0x10) ?
69946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		      mousebuf[i+1] - 256 : mousebuf[i+1];
70046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		dy = (mousebuf[i] & 0x20) ?
70146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		  		      -(mousebuf[i+2] - 256) : -mousebuf[i+2];
70246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				switch (mousebuf[i+3]&0x0F) {
70346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				    case 0x0E: /* DX = +1 */
70446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				    case 0x02: /* DX = -1 */
70546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					break;
70646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				    case 0x0F: /* DY = +1 (map button 4) */
70746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                       FB_vgamousecallback(button | (1<<3),
70846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                                           1, 0, 0);
70946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					break;
71046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				    case 0x01: /* DY = -1 (map button 5) */
71146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                       FB_vgamousecallback(button | (1<<4),
71246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                                           1, 0, 0);
71346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					break;
71446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
71546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
71646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MOUSE_MS:
71746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Microsoft protocol has 0x40 in high byte */
71846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( (mousebuf[i] & 0x40) != 0x40 ) {
71946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Go to next byte */
72046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					i -= (packetsize-1);
72146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					continue;
72246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
72346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Get current mouse state */
72446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				button = ((mousebuf[i] & 0x20) >> 3) |
72546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				         ((mousebuf[i] & 0x10) >> 4);
72646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
72746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				                   (mousebuf[i + 1] & 0x3F));
72846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
72946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				                    (mousebuf[i + 2] & 0x3F));
73046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
73146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MOUSE_BM:
73246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* BusMouse protocol has 0xF8 in high byte */
73346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( (mousebuf[i] & 0xF8) != 0x80 ) {
73446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Go to next byte */
73546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					i -= (packetsize-1);
73646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					continue;
73746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
73846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Get current mouse state */
73946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				button = (~mousebuf[i]) & 0x07;
74046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dx =  (signed char)mousebuf[i+1];
74146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dy = -(signed char)mousebuf[i+2];
74246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
74346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case NUM_MOUSE_DRVS:
74446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Uh oh.. */
74546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dx = 0;
74646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				dy = 0;
74746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
74846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
74946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		GS_vgamousecallback(button, dx, dy);
75046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
75146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( i < nread ) {
75246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_memcpy(mousebuf, &mousebuf[i], (nread-i));
75346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		start = (nread-i);
75446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {
75546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		start = 0;
75646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
75746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return;
75846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
75946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
76046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void handle_keyboard(_THIS)
76146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
76246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned char keybuf[BUFSIZ];
76346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i, nread;
76446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int pressed;
76546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int scancode;
76646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_keysym keysym;
76746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
76846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	nread = read(keyboard_fd, keybuf, BUFSIZ);
76946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( i=0; i<nread; ++i ) {
77046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		scancode = keybuf[i] & 0x7F;
77146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( keybuf[i] & 0x80 ) {
77246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			pressed = SDL_RELEASED;
77346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else {
77446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			pressed = SDL_PRESSED;
77546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
77646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		TranslateKey(scancode, &keysym);
77746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		posted += SDL_PrivateKeyboard(pressed, &keysym);
77846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
77946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
78046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
78146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid GS_PumpEvents(_THIS)
78246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
78346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	fd_set fdset;
78446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int max_fd;
78546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static struct timeval zero;
78646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
78746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	do {
78846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		posted = 0;
78946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
79046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		FD_ZERO(&fdset);
79146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		max_fd = 0;
79246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( keyboard_fd >= 0 ) {
79346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			FD_SET(keyboard_fd, &fdset);
79446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( max_fd < keyboard_fd ) {
79546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				max_fd = keyboard_fd;
79646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
79746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
79846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( mouse_fd >= 0 ) {
79946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			FD_SET(mouse_fd, &fdset);
80046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( max_fd < mouse_fd ) {
80146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				max_fd = mouse_fd;
80246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
80346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
80446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
80546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( keyboard_fd >= 0 ) {
80646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( FD_ISSET(keyboard_fd, &fdset) ) {
80746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					handle_keyboard(this);
80846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
80946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
81046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( mouse_fd >= 0 ) {
81146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( FD_ISSET(mouse_fd, &fdset) ) {
81246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					handle_mouse(this);
81346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
81446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
81546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
81646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} while ( posted );
81746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
81846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
81946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid GS_InitOSKeymap(_THIS)
82046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
82146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
82246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
82346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Initialize the Linux key translation table */
82446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
82546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* First get the ascii keys and others not well handled */
82646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for (i=0; i<SDL_arraysize(keymap); ++i) {
82746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  switch(i) {
82846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  /* These aren't handled by the x86 kernel keymapping (?) */
82946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_PRINTSCREEN:
83046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_PRINT;
83146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
83246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_BREAK:
83346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_BREAK;
83446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
83546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_BREAK_ALTERNATIVE:
83646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_PAUSE;
83746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
83846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_LEFTSHIFT:
83946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_LSHIFT;
84046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
84146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_RIGHTSHIFT:
84246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_RSHIFT;
84346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
84446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_LEFTCONTROL:
84546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_LCTRL;
84646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
84746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_RIGHTCONTROL:
84846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_RCTRL;
84946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
85046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_RIGHTWIN:
85146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_RSUPER;
85246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
85346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case SCANCODE_LEFTWIN:
85446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_LSUPER;
85546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
85646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  case 127:
85746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = SDLK_MENU;
85846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
85946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  /* this should take care of all standard ascii keys */
86046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  default:
86146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    keymap[i] = KVAL(vga_keymap[0][i]);
86246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    break;
86346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          }
86446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
86546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for (i=0; i<SDL_arraysize(keymap); ++i) {
86646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  switch(keymap_temp[i]) {
86746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F1:  keymap[i] = SDLK_F1;  break;
86846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F2:  keymap[i] = SDLK_F2;  break;
86946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F3:  keymap[i] = SDLK_F3;  break;
87046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F4:  keymap[i] = SDLK_F4;  break;
87146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F5:  keymap[i] = SDLK_F5;  break;
87246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F6:  keymap[i] = SDLK_F6;  break;
87346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F7:  keymap[i] = SDLK_F7;  break;
87446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F8:  keymap[i] = SDLK_F8;  break;
87546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F9:  keymap[i] = SDLK_F9;  break;
87646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F10: keymap[i] = SDLK_F10; break;
87746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F11: keymap[i] = SDLK_F11; break;
87846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F12: keymap[i] = SDLK_F12; break;
87946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
88046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_DOWN:  keymap[i] = SDLK_DOWN;  break;
88146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_LEFT:  keymap[i] = SDLK_LEFT;  break;
88246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
88346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_UP:    keymap[i] = SDLK_UP;    break;
88446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
88546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P0:     keymap[i] = SDLK_KP0; break;
88646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P1:     keymap[i] = SDLK_KP1; break;
88746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P2:     keymap[i] = SDLK_KP2; break;
88846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P3:     keymap[i] = SDLK_KP3; break;
88946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P4:     keymap[i] = SDLK_KP4; break;
89046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P5:     keymap[i] = SDLK_KP5; break;
89146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P6:     keymap[i] = SDLK_KP6; break;
89246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P7:     keymap[i] = SDLK_KP7; break;
89346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P8:     keymap[i] = SDLK_KP8; break;
89446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_P9:     keymap[i] = SDLK_KP9; break;
89546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PPLUS:  keymap[i] = SDLK_KP_PLUS; break;
89646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
89746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PSTAR:  keymap[i] = SDLK_KP_MULTIPLY; break;
89846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
89946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
90046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PDOT:   keymap[i] = SDLK_KP_PERIOD; break;
90146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
90246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_SHIFT:  if ( keymap[i] != SDLK_RSHIFT )
90346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	                     keymap[i] = SDLK_LSHIFT;
90446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	                   break;
90546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
90646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
90746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_CTRL:  if ( keymap[i] != SDLK_RCTRL )
90846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	                     keymap[i] = SDLK_LCTRL;
90946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	                   break;
91046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_CTRLL:  keymap[i] = SDLK_LCTRL;  break;
91146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_CTRLR:  keymap[i] = SDLK_RCTRL;  break;
91246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_ALT:    keymap[i] = SDLK_LALT;   break;
91346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_ALTGR:  keymap[i] = SDLK_RALT;   break;
91446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
91546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_INSERT: keymap[i] = SDLK_INSERT;   break;
91646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_REMOVE: keymap[i] = SDLK_DELETE;   break;
91746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PGUP:   keymap[i] = SDLK_PAGEUP;   break;
91846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PGDN:   keymap[i] = SDLK_PAGEDOWN; break;
91946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_FIND:   keymap[i] = SDLK_HOME;     break;
92046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_SELECT: keymap[i] = SDLK_END;      break;
92146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
92246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_NUM:  keymap[i] = SDLK_NUMLOCK;   break;
92346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_CAPS: keymap[i] = SDLK_CAPSLOCK;  break;
92446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
92546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_F13:   keymap[i] = SDLK_PRINT;     break;
92646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_HOLD:  keymap[i] = SDLK_SCROLLOCK; break;
92746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case K_PAUSE: keymap[i] = SDLK_PAUSE;     break;
92846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
92946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    case 127: keymap[i] = SDLK_BACKSPACE; break;
93046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    default: break;
93246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  }
93346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
93446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
93546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
93646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
93746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
93846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set the keysym information */
93946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	keysym->scancode = scancode;
94046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	keysym->sym = keymap[scancode];
94146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	keysym->mod = KMOD_NONE;
94246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
94346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* If UNICODE is on, get the UNICODE value for the key */
94446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	keysym->unicode = 0;
94546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_TranslateUNICODE ) {
94646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int map;
94746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDLMod modstate;
94846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
94946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		modstate = SDL_GetModState();
95046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		map = 0;
95146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( modstate & KMOD_SHIFT ) {
95246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			map |= (1<<KG_SHIFT);
95346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
95446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( modstate & KMOD_CTRL ) {
95546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			map |= (1<<KG_CTRL);
95646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
95746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( modstate & KMOD_ALT ) {
95846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			map |= (1<<KG_ALT);
95946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
96046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( modstate & KMOD_MODE ) {
96146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			map |= (1<<KG_ALTGR);
96246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
96346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
96446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( modstate & KMOD_CAPS ) {
96546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				map ^= (1<<KG_SHIFT);
96646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
96746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
96846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
96946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( modstate & KMOD_NUM ) {
97046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				keysym->unicode=KVAL(vga_keymap[map][scancode]);
97146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
97246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else {
97346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			keysym->unicode = KVAL(vga_keymap[map][scancode]);
97446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
97546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
97646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(keysym);
97746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
978