diff options
author | Robin Cutshaw <robin@intercore.com> | 1999-12-30 03:03:21 +0000 |
---|---|---|
committer | Robin Cutshaw <robin@intercore.com> | 1999-12-30 03:03:21 +0000 |
commit | 30e35cb44b6ea11d0eac8ce0d986517f3224852a (patch) | |
tree | a4bb0182dbcf5e4ce8cd61ed4e257815d9af3957 /hw/kdrive/linux | |
parent | f13b792a3a8d307a18cd6a41aa5a06622009e42f (diff) |
3516. Jumbo Tiny-X patch with Itsy support (#3527, Keith Packard).xf-3_9_17xf-3_9_16Za
Diffstat (limited to 'hw/kdrive/linux')
-rw-r--r-- | hw/kdrive/linux/Imakefile | 16 | ||||
-rw-r--r-- | hw/kdrive/linux/keyboard.c | 439 | ||||
-rw-r--r-- | hw/kdrive/linux/linux.c | 329 | ||||
-rw-r--r-- | hw/kdrive/linux/ps2.c | 131 |
4 files changed, 915 insertions, 0 deletions
diff --git a/hw/kdrive/linux/Imakefile b/hw/kdrive/linux/Imakefile new file mode 100644 index 000000000..0c8927c42 --- /dev/null +++ b/hw/kdrive/linux/Imakefile @@ -0,0 +1,16 @@ +XCOMM $XConsortium: Imakefile /main/10 1996/12/02 10:20:33 lehors $ +XCOMM $XFree86: $ +#include <Server.tmpl> + +SRCS = keyboard.c linux.c ps2.c + +OBJS = keyboard.o linux.o ps2.o + +INCLUDES = -I. -I.. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + -I../../../fb -I../../../mi -I../../../include -I../../../os \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) + +NormalLibraryObjectRule() +NormalLibraryTarget(linux,$(OBJS)) + +DependTarget() diff --git a/hw/kdrive/linux/keyboard.c b/hw/kdrive/linux/keyboard.c new file mode 100644 index 000000000..87fc0962e --- /dev/null +++ b/hw/kdrive/linux/keyboard.c @@ -0,0 +1,439 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "kdrive.h" +#include "kkeymap.h" +#include <linux/keyboard.h> +#include <linux/kd.h> +#include <X11/keysym.h> +#include <termios.h> + +extern int LinuxConsoleFd; + +static const KeySym linux_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_Delete, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis +}; + +static unsigned char tbl[KD_MAX_WIDTH] = +{ + 0, + 1 << KG_SHIFT, + (1 << KG_ALT), + (1 << KG_ALT) | (1 << KG_SHIFT) +}; + +static void +readKernelMapping() +{ + KeySym *k; + int i, j; + struct kbentry kbe; + int minKeyCode, maxKeyCode; + + minKeyCode = NR_KEYS; + maxKeyCode = 0; + k = kdKeymap; + for (i = 0; + i < NR_KEYS && (maxKeyCode - minKeyCode + 1) < KD_MAX_LENGTH; + ++i) + { + kbe.kb_index = i; + + for (j = 0; j < KD_MAX_WIDTH; ++j) + { + unsigned short kval; + + k[j] = NoSymbol; + + kbe.kb_table = tbl[j]; + if (ioctl(LinuxConsoleFd, KDGKBENT, &kbe)) + continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) + { + case KT_LATIN: + case KT_LETTER: + k[j] = linux_to_x[kval]; + break; + + case KT_FN: + if (kval <= 19) + k[j] = XK_F1 + kval; + else switch (kbe.kb_value) + { + case K_FIND: + k[j] = XK_Home; /* or XK_Find */ + break; + case K_INSERT: + k[j] = XK_Insert; + break; + case K_REMOVE: + k[j] = XK_Delete; + break; + case K_SELECT: + k[j] = XK_End; /* or XK_Select */ + break; + case K_PGUP: + k[j] = XK_Prior; + break; + case K_PGDN: + k[j] = XK_Next; + break; + case K_HELP: + k[j] = XK_Help; + break; + case K_DO: + k[j] = XK_Execute; + break; + case K_PAUSE: + k[j] = XK_Pause; + break; + case K_MACRO: + k[j] = XK_Menu; + break; + default: + break; + } + break; + + case KT_SPEC: + switch (kbe.kb_value) + { + case K_ENTER: + k[j] = XK_Return; + break; + case K_BREAK: + k[j] = XK_Break; + break; + case K_CAPS: + k[j] = XK_Caps_Lock; + break; + case K_NUM: + k[j] = XK_Num_Lock; + break; + case K_HOLD: + k[j] = XK_Scroll_Lock; + break; + case K_COMPOSE: + k[j] = XK_Multi_key; + break; + default: + break; + } + break; + + case KT_PAD: + switch (kbe.kb_value) + { + case K_PPLUS: + k[j] = XK_KP_Add; + break; + case K_PMINUS: + k[j] = XK_KP_Subtract; + break; + case K_PSTAR: + k[j] = XK_KP_Multiply; + break; + case K_PSLASH: + k[j] = XK_KP_Divide; + break; + case K_PENTER: + k[j] = XK_KP_Enter; + break; + case K_PCOMMA: + k[j] = XK_KP_Separator; + break; + case K_PDOT: + k[j] = XK_KP_Decimal; + break; + case K_PPLUSMINUS: + k[j] = XK_KP_Subtract; + break; + default: + if (kval <= 9) + k[j] = XK_KP_0 + kval; + break; + } + break; + + /* + * KT_DEAD keys are for accelerated diacritical creation. + */ + case KT_DEAD: + switch (kbe.kb_value) + { + case K_DGRAVE: + k[j] = XK_dead_grave; + break; + case K_DACUTE: + k[j] = XK_dead_acute; + break; + case K_DCIRCM: + k[j] = XK_dead_circumflex; + break; + case K_DTILDE: + k[j] = XK_dead_tilde; + break; + case K_DDIERE: + k[j] = XK_dead_diaeresis; + break; + } + break; + + case KT_CUR: + switch (kbe.kb_value) + { + case K_DOWN: + k[j] = XK_Down; + break; + case K_LEFT: + k[j] = XK_Left; + break; + case K_RIGHT: + k[j] = XK_Right; + break; + case K_UP: + k[j] = XK_Up; + break; + } + break; + + case KT_SHIFT: + switch (kbe.kb_value) + { + case K_ALTGR: + k[j] = XK_Alt_R; + break; + case K_ALT: + k[j] = (kbe.kb_index == 0x64 ? + XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + k[j] = (kbe.kb_index == 0x61 ? + XK_Control_R : XK_Control_L); + break; + case K_CTRLL: + k[j] = XK_Control_L; + break; + case K_CTRLR: + k[j] = XK_Control_R; + break; + case K_SHIFT: + k[j] = (kbe.kb_index == 0x36 ? + XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: + k[j] = XK_Shift_L; + break; + case K_SHIFTR: + k[j] = XK_Shift_R; + break; + default: + break; + } + break; + + /* + * KT_ASCII keys accumulate a 3 digit decimal number that gets + * emitted when the shift state changes. We can't emulate that. + */ + case KT_ASCII: + break; + + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) + k[j] = XK_Shift_Lock; + break; + + default: + break; + } + if (i < minKeyCode) + minKeyCode = i; + if (i > maxKeyCode) + maxKeyCode = i; + } + + if (minKeyCode == NR_KEYS) + continue; + + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[2] == k[1]) k[2] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; + if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol; + + k += KD_MAX_WIDTH; + } + kdMinScanCode = minKeyCode; + kdMaxScanCode = maxKeyCode; +} + +void +LinuxKeyboardLoad (void) +{ + readKernelMapping (); +} + +static int LinuxKbdTrans; +static struct termios LinuxTermios; + +int +LinuxKeyboardInit (void) +{ + struct termios nTty; + + ioctl (LinuxConsoleFd, KDGKBMODE, &LinuxKbdTrans); + tcgetattr (LinuxConsoleFd, &LinuxTermios); + + ioctl(LinuxConsoleFd, KDSKBMODE, K_MEDIUMRAW); + nTty = LinuxTermios; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME]=0; + nTty.c_cc[VMIN]=1; + cfsetispeed(&nTty, 9600); + cfsetospeed(&nTty, 9600); + tcsetattr(LinuxConsoleFd, TCSANOW, &nTty); + return LinuxConsoleFd; +} + +void +LinuxKeyboardFini (int fd) +{ + ioctl(LinuxConsoleFd, KDSKBMODE, LinuxKbdTrans); + tcsetattr(LinuxConsoleFd, TCSANOW, &LinuxTermios); +} + +void +LinuxKeyboardRead (int fd) +{ + unsigned char buf[256], *b; + int n; + + while ((n = read (fd, buf, sizeof (buf))) > 0) + { + b = buf; + while (n--) + { + KdEnqueueKeyboardEvent (b[0] & 0x7f, b[0] & 0x80); + b++; + } + } +} + +void +LinuxKeyboardLeds (int leds) +{ + ioctl (LinuxConsoleFd, KDSETLED, leds & 7); +} + +void +LinuxKeyboardBell (int volume, int pitch, int duration) +{ + if (volume && pitch) + { + ioctl(LinuxConsoleFd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration * + volume / 50) << 16)); + + } +} + +KdKeyboardFuncs LinuxKeyboardFuncs = { + LinuxKeyboardLoad, + LinuxKeyboardInit, + LinuxKeyboardRead, + LinuxKeyboardLeds, + LinuxKeyboardBell, + LinuxKeyboardFini, + 3, +}; diff --git a/hw/kdrive/linux/linux.c b/hw/kdrive/linux/linux.c new file mode 100644 index 000000000..68aa686df --- /dev/null +++ b/hw/kdrive/linux/linux.c @@ -0,0 +1,329 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "kdrive.h" +#include <errno.h> +#include <signal.h> +#include <linux/vt.h> +#include <linux/kd.h> +#include <sys/stat.h> +#include <keysym.h> + +static int vtno; +int LinuxConsoleFd; +static int activeVT; +static Bool enabled; + +void +LinuxVTRequest (int sig) +{ + kdSwitchPending = TRUE; +} + +/* Check before chowning -- this avoids touching the file system */ +void +LinuxCheckChown (char *file) +{ + struct stat st; + __uid_t u; + __gid_t g; + + if (stat (file, &st) < 0) + return; + u = getuid (); + g = getgid (); + if (st.st_uid != u || st.st_gid != g) + chown (file, u, g); +} + +int +LinuxInit () +{ + int i, fd; + char vtname[11]; + struct vt_stat vts; + struct stat statb; + + LinuxConsoleFd = -1; + /* check if we're run with euid==0 */ + if (geteuid() != 0) + { + FatalError("LinuxInit: Server must be suid root\n"); + } + + if ((fd = open("/dev/tty0",O_WRONLY,0)) < 0) + { + FatalError( + "LinuxInit: Cannot open /dev/tty0 (%s)\n", + strerror(errno)); + } + if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || + (vtno == -1)) + { + FatalError("xf86OpenConsole: Cannot find a free VT\n"); + } + close(fd); + +/* ErrorF("(using VT number %d)\n\n", vtno); */ + + sprintf(vtname,"/dev/tty%d",vtno); /* /dev/tty1-64 */ + + if ((LinuxConsoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0) + { + FatalError("LinuxInit: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + + /* change ownership of the vt */ + LinuxCheckChown (vtname); + + /* + * the current VT device we're running on is not "console", we want + * to grab all consoles too + * + * Why is this needed? + */ + LinuxCheckChown ("/dev/tty0"); + /* + * Linux doesn't switch to an active vt after the last close of a vt, + * so we do this ourselves by remembering which is active now. + */ + if (ioctl(LinuxConsoleFd, VT_GETSTATE, &vts) == 0) + { + activeVT = vts.v_active; + } + + return 1; +} + +Bool +LinuxFindPci (CARD16 vendor, CARD16 device, CARD32 count, KdCardAttr *attr) +{ + FILE *f; + char line[2048], *l, *end; + CARD32 bus, id, mode, addr; + int n; + CARD32 ven_dev; + Bool ret = FALSE; + int i; + + ven_dev = (((CARD32) vendor) << 16) | ((CARD32) device); + f = fopen ("/proc/bus/pci/devices", "r"); + if (!f) + return FALSE; + attr->io = 0; + while (fgets (line, sizeof (line)-1, f)) + { + line[sizeof(line)-1] = '\0'; + l = line; + bus = strtoul (l, &end, 16); + if (end == l) + continue; + l = end; + id = strtoul (l, &end, 16); + if (end == l) + continue; + l = end; + if (id != ven_dev) + continue; + if (count--) + continue; + (void) strtoul (l, &end, 16); + if (end == l) + continue; + l = end; + n = 0; + for (i = 0; i < 6; i++) + { + addr = strtoul (l, &end, 16); + if (end == l) + break; + if (addr & 1) + attr->io = addr & ~0xf; + else + { + if (n == KD_MAX_CARD_ADDRESS) + break; + attr->address[n++] = addr & ~0xf; + } + l = end; + } + while (n > 0) + { + if (attr->address[n-1] != 0) + break; + n--; + } + attr->naddr = n; + ret = TRUE; + break; + } + fclose (f); + return ret; +} + +void +LinuxEnable (void) +{ + struct sigaction act; + struct vt_mode VT; + + if (enabled) + return; + if (kdSwitchPending) + { + kdSwitchPending = FALSE; + ioctl (LinuxConsoleFd, VT_RELDISP, VT_ACKACQ); + } + /* + * now get the VT + */ + if (ioctl(LinuxConsoleFd, VT_ACTIVATE, vtno) != 0) + { + ErrorF("LinuxInit: VT_ACTIVATE failed\n"); + } + if (ioctl(LinuxConsoleFd, VT_WAITACTIVE, vtno) != 0) + { + ErrorF("LinuxInit: VT_WAITACTIVE failed\n"); + } + if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) < 0) + { + FatalError ("LinuxInit: VT_GETMODE failed\n"); + } + + act.sa_handler = LinuxVTRequest; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + act.sa_restorer = 0; + sigaction (SIGUSR1, &act, 0); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + if (ioctl(LinuxConsoleFd, VT_SETMODE, &VT) < 0) + { + FatalError("LinuxInit: VT_SETMODE VT_PROCESS failed\n"); + } + if (ioctl(LinuxConsoleFd, KDSETMODE, KD_GRAPHICS) < 0) + { + FatalError("LinuxInit: KDSETMODE KD_GRAPHICS failed\n"); + } + enabled = TRUE; +} + +Bool +LinuxSpecialKey (KeySym sym) +{ + struct vt_stat vts; + int con; + + if (XK_F1 <= sym && sym <= XK_F12) + { + con = sym - XK_F1 + 1; + ioctl (LinuxConsoleFd, VT_GETSTATE, &vts); + if (con != vts.v_active && (vts.v_state & (1 << con))) + { + ioctl (LinuxConsoleFd, VT_ACTIVATE, con); + return TRUE; + } + } + return FALSE; +} + +void +LinuxDisable (void) +{ + ioctl(LinuxConsoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */ + if (kdSwitchPending) + { + kdSwitchPending = FALSE; + ioctl (LinuxConsoleFd, VT_RELDISP, 1); + } + enabled = FALSE; +} + +void +LinuxFini (void) +{ + struct vt_mode VT; + struct vt_stat vts; + int fd; + + if (LinuxConsoleFd < 0) + return; + + if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; + ioctl(LinuxConsoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + } + ioctl (LinuxConsoleFd, VT_GETSTATE, &vts); + /* + * Find a legal VT to switch to, either the one we started from + * or the lowest active one that isn't ours + */ + if (activeVT < 0 || + activeVT == vts.v_active || + !(vts.v_state & (1 << activeVT))) + { + for (activeVT = 1; activeVT < 16; activeVT++) + if (activeVT != vtno && (vts.v_state & (1 << activeVT))) + break; + if (activeVT == 16) + activeVT = -1; + } + /* + * Perform a switch back to the active VT when we were started + */ + if (activeVT >= -1) + { + ioctl (LinuxConsoleFd, VT_ACTIVATE, activeVT); + ioctl (LinuxConsoleFd, VT_WAITACTIVE, activeVT); + activeVT = -1; + } + close(LinuxConsoleFd); /* make the vt-manager happy */ + fd = open ("/dev/tty0", O_RDWR|O_NDELAY, 0); + if (fd >= 0) + { + ioctl (fd, VT_GETSTATE, &vts); + if (ioctl (fd, VT_DISALLOCATE, vtno) < 0) + fprintf (stderr, "Can't deallocate console %d errno %d\n", vtno, errno); + close (fd); + } + return; +} + +KdOsFuncs LinuxFuncs = { + LinuxInit, + LinuxEnable, + LinuxSpecialKey, + LinuxDisable, + LinuxFini, +}; + +void +OsVendorInit (void) +{ + KdOsInit (&LinuxFuncs); +} diff --git a/hw/kdrive/linux/ps2.c b/hw/kdrive/linux/ps2.c new file mode 100644 index 000000000..efb541430 --- /dev/null +++ b/hw/kdrive/linux/ps2.c @@ -0,0 +1,131 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" +#include "Xpoll.h" + +int +Ps2ReadBytes (int fd, char *buf, int len, int min) +{ + int n, tot; + fd_set set; + struct timeval tv; + + tot = 0; + while (len) + { + n = read (fd, buf, len); + if (n > 0) + { + tot += n; + buf += n; + len -= n; + } + if (tot % min == 0) + break; + FD_ZERO (&set); + FD_SET (fd, &set); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + n = select (fd + 1, &set, 0, 0, &tv); + if (n <= 0) + break; + } + return tot; +} + +void +Ps2Read (int ps2Port) +{ + unsigned char buf[3 * 200]; + unsigned char *b; + int n; + int dx, dy; + unsigned long flags; + + while ((n = Ps2ReadBytes (ps2Port, buf, sizeof (buf), 3)) > 0) + { + b = buf; + while (n >= 3) + { + flags = KD_MOUSE_DELTA; + if (b[0] & 4) + flags |= KD_BUTTON_2; + if (b[0] & 2) + flags |= KD_BUTTON_3; + if (b[0] & 1) + flags |= KD_BUTTON_1; + + dx = b[1]; + if (b[0] & 0x10) + dx -= 256; + dy = b[2]; + if (b[0] & 0x20) + dy -= 256; + dy = -dy; + n -= 3; + b += 3; + KdEnqueueMouseEvent (flags, dx, dy); + } + } +} + +char *Ps2Names[] = { + "/dev/psaux", + "/dev/mouse", +}; + +#define NUM_PS2_NAMES (sizeof (Ps2Names) / sizeof (Ps2Names[0])) + +int +Ps2Init (void) +{ + int i; + int ps2Port; + + for (i = 0; i < NUM_PS2_NAMES; i++) + { + ps2Port = open (Ps2Names[i], 0); + if (ps2Port >= 0) + return ps2Port; + } +} + +void +Ps2Fini (int ps2Port) +{ + if (ps2Port >= 0) + close (ps2Port); +} + +KdMouseFuncs Ps2MouseFuncs = { + Ps2Init, + Ps2Read, + Ps2Fini +}; |