From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../Xserver/hw/xfree86/os-support/linux/lnx_kbd.c | 559 +++++++++++++++++++++ 1 file changed, 559 insertions(+) create mode 100644 nx-X11/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c') diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c new file mode 100644 index 000000000..b1fc95b56 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c @@ -0,0 +1,559 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c,v 1.4 2003/11/03 05:11:52 tsi Exp $ */ + +/* + * Copyright (c) 2002 by The XFree86 Project, Inc. + * Author: Ivan Pascal. + * + * Based on the code from lnx_io.c which is + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Dawes + */ + +#define NEED_EVENTS +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#include "xf86Xinput.h" +#include "xf86OSKbd.h" +#include "atKeynames.h" +#if defined(DO_OS_FONTRESTORE) +#include "lnx.h" +#endif +#include "lnx_kbd.h" + +#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ + +static KbdProtocolRec protocols[] = { + {"standard", PROT_STD }, + { NULL, PROT_UNKNOWN_KBD } +}; + +extern Bool VTSwitchEnabled; +#ifdef USE_VT_SYSREQ +extern Bool VTSysreqToggle; +#endif + +static void +SoundBell(InputInfoPtr pInfo, int loudness, int pitch, int duration) +{ + if (loudness && pitch) + { + ioctl(pInfo->fd, KDMKTONE, + ((1193190 / pitch) & 0xffff) | + (((unsigned long)duration * + loudness / 50) << 16)); + } +} + +static void +SetKbdLeds(InputInfoPtr pInfo, int leds) +{ + int real_leds = 0; + +#if defined (__sparc__) + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + if (pKbd->sunKbd) { + if (leds & 0x08) real_leds |= XLED1; + if (leds & 0x04) real_leds |= XLED3; + if (leds & 0x02) real_leds |= XLED4; + if (leds & 0x01) real_leds |= XLED2; + leds = real_leds; + real_leds = 0; + } +#endif /* defined (__sparc__) */ +#ifdef LED_CAP + if (leds & XLED1) real_leds |= LED_CAP; + if (leds & XLED2) real_leds |= LED_NUM; + if (leds & XLED3) real_leds |= LED_SCR; +#ifdef LED_COMP + if (leds & XLED4) real_leds |= LED_COMP; +#else + if (leds & XLED4) real_leds |= LED_SCR; +#endif +#endif + ioctl(pInfo->fd, KDSETLED, real_leds); +} + +static int +GetKbdLeds(InputInfoPtr pInfo) +{ + int real_leds, leds = 0; + + ioctl(pInfo->fd, KDGETLED, &real_leds); + + if (real_leds & LED_CAP) leds |= XLED1; + if (real_leds & LED_NUM) leds |= XLED2; + if (real_leds & LED_SCR) leds |= XLED3; + + return(leds); +} + +/* kbd rate stuff based on kbdrate.c from Rik Faith et.al. + * from util-linux-2.9t package */ + +#include +#include +#ifdef __sparc__ +#include +#include +#endif + +/* Deal with spurious kernel header change in struct kbd_repeat. + We undo this define after the routine using that struct is over, + so as not to interfere with other 'rate' elements. */ +#if defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,42) +# define rate period +# endif +#endif + +static int +KDKBDREP_ioctl_ok(int rate, int delay) { +#if defined(KDKBDREP) && !defined(__sparc__) + /* This ioctl is defined in but is not + implemented anywhere - must be in some m68k patches. */ + struct kbd_repeat kbdrep_s; + + /* don't change, just test */ + kbdrep_s.rate = -1; + kbdrep_s.delay = -1; + if (ioctl( xf86Info.consoleFd, KDKBDREP, &kbdrep_s )) { + return 0; + } + + /* do the change */ + if (rate == 0) /* switch repeat off */ + kbdrep_s.rate = 0; + else + kbdrep_s.rate = 10000 / rate; /* convert cps to msec */ + if (kbdrep_s.rate < 1) + kbdrep_s.rate = 1; + kbdrep_s.delay = delay; + if (kbdrep_s.delay < 1) + kbdrep_s.delay = 1; + + if (ioctl( xf86Info.consoleFd, KDKBDREP, &kbdrep_s )) { + return 0; + } + + return 1; /* success! */ +#else /* no KDKBDREP */ + return 0; +#endif /* KDKBDREP */ +} + +#undef rate + +/* Undo the earlier define for the struct kbd_repeat problem. */ +#if defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,42) +# undef rate +# endif +#endif + +static int +KIOCSRATE_ioctl_ok(int rate, int delay) { +#ifdef KIOCSRATE + struct kbd_rate kbdrate_s; + int fd; + + fd = open("/dev/kbd", O_RDONLY); + if (fd == -1) + return 0; + + kbdrate_s.rate = (rate + 5) / 10; /* must be integer, so round up */ + kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */ + if (kbdrate_s.rate > 50) + kbdrate_s.rate = 50; + + if (ioctl( fd, KIOCSRATE, &kbdrate_s )) { + return 0; + } + + close( fd ); + + return 1; +#else /* no KIOCSRATE */ + return 0; +#endif /* KIOCSRATE */ +} + +#undef rate + +static void +SetKbdRepeat(InputInfoPtr pInfo, char rad) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + int i; + int timeout; + int value = 0x7f; /* Maximum delay with slowest rate */ + +#ifdef __sparc__ + int rate = 500; /* Default rate */ + int delay = 200; /* Default delay */ +#else + int rate = 300; /* Default rate */ + int delay = 250; /* Default delay */ +#endif + + static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150, + 133, 120, 109, 100, 92, 86, 80, 75, 67, + 60, 55, 50, 46, 43, 40, 37, 33, 30, 27, + 25, 23, 21, 20 }; +#define RATE_COUNT (sizeof( valid_rates ) / sizeof( int )) + + static int valid_delays[] = { 250, 500, 750, 1000 }; +#define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int )) + + if (pKbd->rate >= 0) + rate = pKbd->rate * 10; + if (pKbd->delay >= 0) + delay = pKbd->delay; + + if(KDKBDREP_ioctl_ok(rate, delay)) /* m68k? */ + return; + + if(KIOCSRATE_ioctl_ok(rate, delay)) /* sparc? */ + return; + + if (xf86IsPc98()) + return; + +#if defined(__alpha__) || defined (__i386__) || defined(__ia64__) + + if (!xorgHWAccess) { + if (xf86EnableIO()) + xorgHWAccess = TRUE; + else + return; + } + + /* The ioport way */ + + for (i = 0; i < RATE_COUNT; i++) + if (rate >= valid_rates[i]) { + value &= 0x60; + value |= i; + break; + } + + for (i = 0; i < DELAY_COUNT; i++) + if (delay <= valid_delays[i]) { + value &= 0x1f; + value |= i << 5; + break; + } + + timeout = KBC_TIMEOUT; + while (((inb(0x64) & 2) == 2) && --timeout) + usleep(1000); /* wait */ + + if (timeout == 0) + return; + + outb(0x60, 0xf3); /* set typematic rate */ + while (((inb(0x64) & 2) == 2) && --timeout) + usleep(1000); /* wait */ + + usleep(10000); + outb(0x60, value); + +#endif /* __alpha__ || __i386__ || __ia64__ */ +} + +typedef struct { + int kbdtrans; + struct termios kbdtty; +} LnxKbdPrivRec, *LnxKbdPrivPtr; + +static int +KbdInit(InputInfoPtr pInfo, int what) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; + + if (pKbd->isConsole) { + ioctl (pInfo->fd, KDGKBMODE, &(priv->kbdtrans)); + tcgetattr (pInfo->fd, &(priv->kbdtty)); + } + if (!pKbd->CustomKeycodes) { + pKbd->RemapScanCode = ATScancode; + } + + return Success; +} + +static int +KbdOn(InputInfoPtr pInfo, int what) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; + struct termios nTty; + + if (pKbd->isConsole) { + if (pKbd->CustomKeycodes) + ioctl(pInfo->fd, KDSKBMODE, K_MEDIUMRAW); + else + ioctl(pInfo->fd, KDSKBMODE, K_RAW); + + nTty = priv->kbdtty; + 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(pInfo->fd, TCSANOW, &nTty); + } + return Success; +} + +static int +KbdOff(InputInfoPtr pInfo, int what) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + LnxKbdPrivPtr priv = (LnxKbdPrivPtr) pKbd->private; + + if (pKbd->isConsole) { + ioctl(pInfo->fd, KDSKBMODE, priv->kbdtrans); + tcsetattr(pInfo->fd, TCSANOW, &(priv->kbdtty)); + } + return Success; +} + +static int +GetSpecialKey(InputInfoPtr pInfo, int scanCode) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + int specialkey = scanCode; + +#if defined (__sparc__) + if (pKbd->sunKbd) { + switch (scanCode) { + case 0x2b: specialkey = KEY_BackSpace; break; + case 0x47: specialkey = KEY_KP_Minus; break; + case 0x7d: specialkey = KEY_KP_Plus; break; + /* XXX needs cases for KEY_KP_Divide and KEY_KP_Multiply */ + case 0x05: specialkey = KEY_F1; break; + case 0x06: specialkey = KEY_F2; break; + case 0x08: specialkey = KEY_F3; break; + case 0x0a: specialkey = KEY_F4; break; + case 0x0c: specialkey = KEY_F5; break; + case 0x0e: specialkey = KEY_F6; break; + case 0x10: specialkey = KEY_F7; break; + case 0x11: specialkey = KEY_F8; break; + case 0x12: specialkey = KEY_F9; break; + case 0x07: specialkey = KEY_F10; break; + case 0x09: specialkey = KEY_F11; break; + case 0x0b: specialkey = KEY_F12; break; + default: specialkey = 0; break; + } + return specialkey; + } +#endif + + if (pKbd->CustomKeycodes) { + specialkey = pKbd->specialMap->map[scanCode]; + } + return specialkey; +} + +#define ModifierSet(k) ((modifiers & (k)) == (k)) + +static +Bool SpecialKey(InputInfoPtr pInfo, int key, Bool down, int modifiers) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + + if(!pKbd->vtSwitchSupported) + return FALSE; + + if ((ModifierSet(ControlMask | AltMask)) || + (ModifierSet(ControlMask | AltLangMask))) { + if (VTSwitchEnabled && !xf86Info.vtSysreq && !xf86Info.dontVTSwitch) { + switch (key) { + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + if (down) { + ioctl(xf86Info.consoleFd, VT_ACTIVATE, key - KEY_F1 + 1); + return TRUE; + } + case KEY_F11: + case KEY_F12: + if (down) { + ioctl(xf86Info.consoleFd, VT_ACTIVATE, key - KEY_F11 + 11); + return TRUE; + } + } + } + } +#ifdef USE_VT_SYSREQ + if (VTSwitchEnabled && xf86Info.vtSysreq && !xf86Info.dontVTSwitch) { + switch (key) { + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + if (VTSysreqToggle && down) { + ioctl(xf86Info.consoleFd, VT_ACTIVATE, key - KEY_F1 + 1); + VTSysreqToggle = FALSE; + return TRUE; + } + break; + case KEY_F11: + case KEY_F12: + if (VTSysreqToggle && down) { + ioctl(xf86Info.consoleFd, VT_ACTIVATE, key - KEY_F11 + 11); + VTSysreqToggle = FALSE; + return TRUE; + } + break; + /* Ignore these keys -- ie don't let them cancel an alt-sysreq */ + case KEY_Alt: + case KEY_AltLang: + break; + case KEY_SysReqest: + if ((ModifierSet(AltMask) || ModifierSet(AltLangMask)) && down) + VTSysreqToggle = TRUE; + break; + default: + /* + * We only land here when Alt-SysReq is followed by a + * non-switching key. + */ + if (VTSysreqToggle) + VTSysreqToggle = FALSE; + } + } +#endif /* USE_VT_SYSREQ */ + return FALSE; +} + +static void +stdReadInput(InputInfoPtr pInfo) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + unsigned char rBuf[64]; + int nBytes, i; + if ((nBytes = read( pInfo->fd, (char *)rBuf, sizeof(rBuf))) > 0) { + for (i = 0; i < nBytes; i++) + pKbd->PostEvent(pInfo, rBuf[i] & 0x7f, + rBuf[i] & 0x80 ? FALSE : TRUE); + } +} + +static Bool +OpenKeyboard(InputInfoPtr pInfo) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + int i; + KbdProtocolId prot = PROT_UNKNOWN_KBD; + char *s; + + s = xf86SetStrOption(pInfo->options, "Protocol", NULL); + for (i = 0; protocols[i].name; i++) { + if (xf86NameCmp(s, protocols[i].name) == 0) { + prot = protocols[i].id; + break; + } + } + + switch (prot) { + case PROT_STD: + pInfo->read_input = stdReadInput; + break; + default: + xf86Msg(X_ERROR,"\"%s\" is not a valid keyboard protocol name\n", s); + xfree(s); + return FALSE; + } + + xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, s); + xfree(s); + + s = xf86SetStrOption(pInfo->options, "Device", NULL); + if (s == NULL) { + pInfo->fd = xf86Info.consoleFd; + pKbd->isConsole = TRUE; + } else { + pInfo->fd = open(s, O_RDONLY | O_NONBLOCK | O_EXCL); + if (pInfo->fd == -1) { + xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", pInfo->name, s); + xfree(s); + return FALSE; + } + pKbd->isConsole = FALSE; + xfree(s); + } + + if (pKbd->isConsole) + pKbd->vtSwitchSupported = TRUE; + + return TRUE; +} + +Bool +xf86OSKbdPreInit(InputInfoPtr pInfo) +{ + KbdDevPtr pKbd = pInfo->private; + + pKbd->KbdInit = KbdInit; + pKbd->KbdOn = KbdOn; + pKbd->KbdOff = KbdOff; + pKbd->Bell = SoundBell; + pKbd->SetLeds = SetKbdLeds; + pKbd->GetLeds = GetKbdLeds; + pKbd->SetKbdRepeat = SetKbdRepeat; + pKbd->KbdGetMapping = KbdGetMapping; + pKbd->SpecialKey = SpecialKey; + + pKbd->RemapScanCode = NULL; + pKbd->GetSpecialKey = GetSpecialKey; + + pKbd->OpenKeyboard = OpenKeyboard; + pKbd->vtSwitchSupported = FALSE; + + pKbd->private = xcalloc(sizeof(LnxKbdPrivRec), 1); + if (pKbd->private == NULL) { + xf86Msg(X_ERROR,"can't allocate keyboard OS private data\n"); + return FALSE; + } + +#if defined(__powerpc__) + { + FILE *f; + f = fopen("/proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes","r"); + if (f) { + if (fgetc(f) == '0') + pKbd->CustomKeycodes = TRUE; + fclose(f); + } + } +#endif + return TRUE; +} -- cgit v1.2.3