diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:56 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:56 +0000 |
commit | 724aeb56e7d6e5940ad6d329f53f5b80a9fc38ae (patch) | |
tree | 26bf7eeae3c1ca04f2cfcf6bf56a4d9123600342 |
Initial revisionXORG-STABLE
-rw-r--r-- | man/kbd.man | 99 | ||||
-rw-r--r-- | man/keyboard.man | 103 | ||||
-rw-r--r-- | src/kbd.c | 770 |
3 files changed, 972 insertions, 0 deletions
diff --git a/man/kbd.man b/man/kbd.man new file mode 100644 index 0000000..5719d56 --- /dev/null +++ b/man/kbd.man @@ -0,0 +1,99 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/keyboard/kbd.man,v 1.1 2002/10/11 01:40:33 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH KBD __drivermansuffix__ __vendorversion__ +.SH NAME +kbd \- Keyboard input driver +.SH SYNOPSIS +.nf +.B "Section \*qInputDevice\*q" +.BI " Identifier \*q" idevname \*q +.B " Driver \*qkbd\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B kbd +is an XFree86 input driver for keyboards. The driver supports the standard +OS-provided keyboard interface, but these are currently only available to +this driver module for Linux and BSD. This driver is experimental, but +will soon replace the built-in +.B keyboard +driver. +.PP +The +.B kbd +driver functions as a keyboard input device, and may be used as the +X server's core keyboard. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details and for options that can be used with all input drivers. This +section only covers configuration details specific to this driver. +.PP +The following driver +.B Options +are supported: +.TP 7 +.BI "Option \*qDevice\*q \*q" string \*q +Specify the keyboard device. Default: the OS's default console keyboard +input source. +.TP 7 +.BI "Option \*qProtocol\*q \*q" string \*q +Specify the keyboard protocol. Valid protocol types include: +.PP +.RS 12 +Standard, Xqueue. +.RE +.PP +.RS 7 +Not all protocols are supported on all platforms. Default: "Standard". +.RE +.TP 7 +.BI "Option \*qAutoRepeat\*q \*q" "delay rate" \*q +sets the auto repeat behaviour for the keyboard. This is not implemented +on all platforms. +.I delay +is the time in milliseconds before a key starts repeating. +.I rate +is the number of times a key repeats per second. Default: "500 30". +.TP 7 +.BI "Option \*qXLeds\*q \*q" ledlist \*q +makes the keyboard LEDs specified in +.I ledlist +available for client use instead of their traditional function +(Scroll Lock, Caps Lock and Num Lock). The numbers in the list are +in the range 1 to 3. Default: empty list. +.TP 7 +.BI "Option \*qXkbRules\*q \*q" rules \*q +specifies which XKB rules file to use for interpreting the +.BR XkbModel , +.BR XkbLayout , +.BR XkbVariant , +and +.B XkbOptions +settings. Default: "xfree86" for most platforms, but "xfree98" for the +Japanese PC-98 platforms. +.TP 7 +.BI "Option \*qXkbModel\*q \*q" modelname \*q +specifies the XKB keyboard model name. Default: "pc101" for most platforms, +but "pc98" for the Japanese PC-98 platforms, and "pc101_sol8x86" for +Solaris 8 on x86. +.TP 7 +.BI "Option \*qXkbLayout\*q \*q" layoutname \*q +specifies the XKB keyboard layout name. This is usually the country or +language type of the keyboard. Default: "us" for most platforms, but +"nec/jp" for the Japanese PC-98 platforms. +.TP 7 +.BI "Option \*qXkbVariant\*q \*q" variants \*q +specifies the XKB keyboard variant components. These can be used to +enhance the keyboard layout details. Default: not set. +.TP 7 +.BI "Option \*qXkbOptions\*q \*q" options \*q +specifies the XKB keyboard option components. These can be used to +enhance the keyboard behaviour. Default: not set. +.PP +Some other XKB-related options are available, but they are incompatible +with the ones listed above and are not recommended, so they are not +documented here. +.SH "SEE ALSO" +keyboard(__drivermansuffix__), XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__). diff --git a/man/keyboard.man b/man/keyboard.man new file mode 100644 index 0000000..93a5fd3 --- /dev/null +++ b/man/keyboard.man @@ -0,0 +1,103 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/keyboard/keyboard.man,v 1.3 2002/10/11 01:40:33 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH KEYBOARD __drivermansuffix__ __vendorversion__ +.SH NAME +keyboard \- Keyboard input driver +.SH SYNOPSIS +.nf +.B "Section \*qInputDevice\*q" +.BI " Identifier \*q" idevname \*q +.B " Driver \*qkeyboard\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B keyboard +is an XFree86 input driver for keyboards. The driver supports the standard +OS-provided keyboard interface. This driver is currently built-in to +the core X server. +.PP +The +.B keyboard +driver functions as a keyboard input device, and may be used as the +X server's core keyboard. This driver is currently built-in to the core +X server, and multiple instances are not yet supported. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details and for options that can be used with all input drivers. This +section only covers configuration details specific to this driver. +.PP +The following driver +.B Options +are supported: +.TP 7 +.BI "Option \*qProtocol\*q \*q" string \*q +Specify the keyboard protocol. Valid protocol types include: +.PP +.RS 12 +Standard, Xqueue. +.RE +.PP +.RS 7 +Not all protocols are supported on all platforms. Default: "Standard". +.RE +.TP 7 +.BI "Option \*qAutoRepeat\*q \*q" "delay rate" \*q +sets the auto repeat behaviour for the keyboard. This is not implemented +on all platforms. +.I delay +is the time in milliseconds before a key starts repeating. +.I rate +is the number of times a key repeats per second. Default: "500 30". +.TP 7 +.BI "Option \*qXLeds\*q \*q" ledlist \*q +makes the keyboard LEDs specified in +.I ledlist +available for client use instead of their traditional function +(Scroll Lock, Caps Lock and Num Lock). The numbers in the list are +in the range 1 to 3. Default: empty list. +.TP 7 +.BI "Option \*qXkbDisable\*q \*q" boolean \*q +disable/enable the XKEYBOARD extension. The \-kb command line +option overrides this config file option. Default: XKB is enabled. +.PP +.RS 7 +NOTE: This option should be specified in the +.B ServerFlags +section rather than here. It's use here is deprecated. +.RE +.TP 7 +.BI "Option \*qXkbRules\*q \*q" rules \*q +specifies which XKB rules file to use for interpreting the +.BR XkbModel , +.BR XkbLayout , +.BR XkbVariant , +and +.B XkbOptions +settings. Default: "xfree86" for most platforms, but "xfree98" for the +Japanese PC-98 platforms. +.TP 7 +.BI "Option \*qXkbModel\*q \*q" modelname \*q +specifies the XKB keyboard model name. Default: "pc101" for most platforms, +but "pc98" for the Japanese PC-98 platforms, and "pc101_sol8x86" for +Solaris 8 on x86. +.TP 7 +.BI "Option \*qXkbLayout\*q \*q" layoutname \*q +specifies the XKB keyboard layout name. This is usually the country or +language type of the keyboard. Default: "us" for most platforms, but +"nec/jp" for the Japanese PC-98 platforms. +.TP 7 +.BI "Option \*qXkbVariant\*q \*q" variants \*q +specifies the XKB keyboard variant components. These can be used to +enhance the keyboard layout details. Default: not set. +.TP 7 +.BI "Option \*qXkbOptions\*q \*q" options \*q +specifies the XKB keyboard option components. These can be used to +enhance the keyboard behaviour. Default: not set. +.PP +Some other XKB-related options are available, but they are incompatible +with the ones listed above and are not recommended, so they are not +documented here. +.SH "SEE ALSO" +kbd(__drivermansuffix__), XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__). diff --git a/src/kbd.c b/src/kbd.c new file mode 100644 index 0000000..f6d4152 --- /dev/null +++ b/src/kbd.c @@ -0,0 +1,770 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/input/keyboard/kbd.c,v 1.7 2003/02/17 16:08:29 dawes Exp $ */ + +/* + * Copyright (c) 2002 by The XFree86 Project, Inc. + * Author: Ivan Pascal. + * + * Based on the code from + * xf86Config.c which is + * Copyright 1991-2002 by The XFree86 Project, Inc. + * Copyright 1997 by Metro Link, Inc. + * xf86Events.c and xf86Io.c which are + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + */ + +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" + +#include "xf86.h" +#include "atKeynames.h" +#include "xf86Privstr.h" + +#ifdef XINPUT +#include "XI.h" +#include "XIproto.h" +#include "extnsionst.h" +#include "extinit.h" +#else +#include "inputstr.h" +#endif + +#include "xf86Xinput.h" +#include "xf86_OSproc.h" +#include "xf86OSKbd.h" +#include "xf86_ansic.h" +#include "compiler.h" + +#ifdef XKB +#include <X11/extensions/XKB.h> +#include <X11/extensions/XKBstr.h> +#include <X11/extensions/XKBsrv.h> +#endif + +#define CAPSFLAG 1 +#define NUMFLAG 2 +#define SCROLLFLAG 4 +#define MODEFLAG 8 +#define COMPOSEFLAG 16 + +static InputInfoPtr KbdPreInit(InputDriverPtr drv, IDevPtr dev, int flags); +static int KbdProc(DeviceIntPtr device, int what); +static int KbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl); +static void KbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused); +static void PostKbdEvent(InputInfoPtr pInfo, unsigned int key, Bool down); + +static void InitKBD(InputInfoPtr pInfo, Bool init); +static void SetXkbOption(InputInfoPtr pInfo, char *name, char **option); +static void UpdateLeds(InputInfoPtr pInfo); + +#undef KEYBOARD +InputDriverRec KEYBOARD = { + 1, + "kbd", + NULL, + KbdPreInit, + NULL, + NULL, + 0 +}; + +typedef enum { + OPTION_ALWAYS_CORE, + OPTION_SEND_CORE_EVENTS, + OPTION_CORE_KEYBOARD, + OPTION_DEVICE, + OPTION_PROTOCOL, + OPTION_AUTOREPEAT, + OPTION_XLEDS, + OPTION_XKB_DISABLE, + OPTION_XKB_KEYMAP, + OPTION_XKB_KEYCODES, + OPTION_XKB_TYPES, + OPTION_XKB_COMPAT, + OPTION_XKB_SYMBOLS, + OPTION_XKB_GEOMETRY, + OPTION_XKB_RULES, + OPTION_XKB_MODEL, + OPTION_XKB_LAYOUT, + OPTION_XKB_VARIANT, + OPTION_XKB_OPTIONS, + OPTION_PANIX106, + OPTION_CUSTOM_KEYCODES +} KeyboardOpts; + +static const OptionInfoRec KeyboardOptions[] = { + { OPTION_ALWAYS_CORE, "AlwaysCore", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SEND_CORE_EVENTS, "SendCoreEvents", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CORE_KEYBOARD, "CoreKeyboard", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE }, + { OPTION_PROTOCOL, "Protocol", OPTV_STRING, {0}, FALSE }, + { OPTION_AUTOREPEAT, "AutoRepeat", OPTV_STRING, {0}, FALSE }, + { OPTION_XLEDS, "XLeds", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_DISABLE, "XkbDisable", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XKB_KEYMAP, "XkbKeymap", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_KEYCODES, "XkbKeycodes", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_TYPES, "XkbTypes", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_COMPAT, "XkbCompat", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_SYMBOLS, "XkbSymbols", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_GEOMETRY, "XkbGeometry", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_RULES, "XkbRules", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_MODEL, "XkbModel", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_LAYOUT, "XkbLayout", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_VARIANT, "XkbVariant", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_OPTIONS, "XkbOptions", OPTV_STRING, {0}, FALSE }, + { OPTION_PANIX106, "Panix106", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CUSTOM_KEYCODES, "CustomKeycodes", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +static const char *kbdDefaults[] = { + "Protocol", "standard", + "AutoRepeat", "500 30", + "XkbRules", "xfree86", + "XkbModel", "pc101", + "XkbLayout", "us", + "Panix106", "off", + "CustomKeycodes", "off", + NULL +}; + +static const char *kbd98Defaults[] = { + "Protocol", "standard", + "AutoRepeat", "500 30", + "XkbRules", "xfree98", + "XkbModel", "pc98", + "XkbLayout", "nec/jp", + "Panix106", "off", + "CustomKeycodes", "off", + NULL +}; + +#ifdef XKB +static char *xkb_rules; +static char *xkb_model; +static char *xkb_layout; +static char *xkb_variant; +static char *xkb_options; + +static XkbComponentNamesRec xkbnames; +#endif /* XKB */ + +#ifdef XFree86LOADER +/*ARGSUSED*/ +static const OptionInfoRec * +KeyboardAvailableOptions(void *unused) +{ + return (KeyboardOptions); +} +#endif + +static void +SetXkbOption(InputInfoPtr pInfo, char *name, char **option) +{ + char *s; + + if ((s = xf86SetStrOption(pInfo->options, name, NULL))) { + if (!s[0]) { + xfree(s); + *option = NULL; + } else { + *option = s; + xf86Msg(X_CONFIG, "%s: %s: \"%s\"\n", pInfo->name, name, s); + } + } +} + +static InputInfoPtr +KbdPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +{ + InputInfoPtr pInfo; + KbdDevPtr pKbd; + MessageType from = X_DEFAULT; + char *s; + + if (!(pInfo = xf86AllocateInput(drv, 0))) + return NULL; + + /* Initialise the InputInfoRec. */ + pInfo->name = dev->identifier; + pInfo->type_name = XI_KEYBOARD; + pInfo->flags = XI86_KEYBOARD_CAPABLE; + pInfo->device_control = KbdProc; + pInfo->read_input = NULL; + pInfo->motion_history_proc = NULL; + pInfo->history_size = 0; + pInfo->control_proc = NULL; + pInfo->close_proc = NULL; + pInfo->switch_mode = NULL; + pInfo->conversion_proc = NULL; + pInfo->reverse_conversion_proc = NULL; + pInfo->fd = -1; + pInfo->dev = NULL; + pInfo->private_flags = 0; + pInfo->always_core_feedback = 0; + pInfo->conf_idev = dev; + + if (!xf86IsPc98()) + xf86CollectInputOptions(pInfo, kbdDefaults, NULL); + else + xf86CollectInputOptions(pInfo, kbd98Defaults, NULL); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + if (!(pKbd = xcalloc(sizeof(KbdDevRec), 1))) + return pInfo; + + pInfo->private = pKbd; + pKbd->PostEvent = PostKbdEvent; + + if (!xf86OSKbdPreInit(pInfo)) + return pInfo; + + if (!pKbd->OpenKeyboard(pInfo)) { + return pInfo; + } + + if ((s = xf86SetStrOption(pInfo->options, "AutoRepeat", NULL))) { + int delay, rate; + if (sscanf(s, "%d %d", &delay, &rate) != 2) { + xf86Msg(X_ERROR, "\"%s\" is not a valid AutoRepeat value", s); + } else { + pKbd->delay = delay; + pKbd->rate = rate; + } + xfree(s); + } + + if ((s = xf86SetStrOption(pInfo->options, "XLeds", NULL))) { + char *l, *end; + unsigned int i; + l = strtok(s, " \t\n"); + while (l) { + i = strtoul(l, &end, 0); + if (*end == '\0') + pKbd->xledsMask |= 1L << (i - 1); + else { + xf86Msg(X_ERROR, "\"%s\" is not a valid XLeds value", l); + } + l = strtok(NULL, " \t\n"); + } + xfree(s); + } + +#ifdef XKB + +/* XkbDisable must be a server flag but for compatibility we check it here */ + + if (xf86FindOption(pInfo->options, "XkbDisable")) + xf86Msg(X_WARNING, + "%s: XKB can't be disabled here. Use \"ServerFlags\" section.\n", + pInfo->name); + + pKbd->noXkb = noXkbExtension; + if (pKbd->noXkb) { + xf86Msg(X_CONFIG, "XKB: disabled\n"); + } else { + SetXkbOption(pInfo, "XkbKeymap", &xkbnames.keymap); + if (xkbnames.keymap) { + xf86Msg(X_CONFIG, "%s: XkbKeymap overrides all other XKB settings\n", + pInfo->name); + } else { + SetXkbOption(pInfo, "XkbRules", &xkb_rules); + SetXkbOption(pInfo, "XkbModel", &xkb_model); + SetXkbOption(pInfo, "XkbLayout", &xkb_layout); + SetXkbOption(pInfo, "XkbVariant", &xkb_variant); + SetXkbOption(pInfo, "XkbOptions", &xkb_options); + + SetXkbOption(pInfo, "XkbKeycodes", &xkbnames.keycodes); + SetXkbOption(pInfo, "XkbTypes", &xkbnames.types); + SetXkbOption(pInfo, "XkbCompat", &xkbnames.compat); + SetXkbOption(pInfo, "XkbSymbols", &xkbnames.symbols); + SetXkbOption(pInfo, "XkbGeometry", &xkbnames.geometry); + } + } + + if ((xkb_model && !strcmp(xkb_model, "sun")) || + (xkb_rules && !strcmp(xkb_rules, "sun"))) + pKbd->sunKbd = TRUE; +#endif + +#if defined(SVR4) && defined(i386) + if ((pKbd->Panix106 = + xf86SetBoolOption(pInfo->options, "Panix106", FALSE))) { + xf86Msg(X_CONFIG, "%s: PANIX106: enabled\n", pInfo->name); + } +#endif + + pKbd->CustomKeycodes = FALSE; + from = X_DEFAULT; + if (xf86FindOption(pInfo->options, "CustomKeycodes")) { + pKbd->CustomKeycodes = xf86SetBoolOption(pInfo->options, "CustomKeycodes", + pKbd->CustomKeycodes); + from = X_CONFIG; + } + + xf86Msg(from, "%s: CustomKeycodes %s\n", + pInfo->name, pKbd->CustomKeycodes ? "enabled" : "disabled"); + + pInfo->flags |= XI86_CONFIGURED; + + return pInfo; +} + +static void +KbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused) +{ + InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + pKbd->Bell(pInfo, percent, ((KeybdCtrl*) ctrl)->bell_pitch, + ((KeybdCtrl*) ctrl)->bell_duration); +} + +static void +UpdateLeds(InputInfoPtr pInfo) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + int leds = 0; + + if (pKbd->keyLeds & CAPSFLAG) leds |= XLED1; + if (pKbd->keyLeds & NUMFLAG) leds |= XLED2; + if (pKbd->keyLeds & SCROLLFLAG || + pKbd->keyLeds & MODEFLAG) leds |= XLED3; + if (pKbd->keyLeds & COMPOSEFLAG) leds |= XLED4; + + pKbd->leds = (pKbd->leds & pKbd->xledsMask) | (leds & ~pKbd->xledsMask); + pKbd->SetLeds(pInfo, pKbd->leds); +} + +static int +KbdCtrl( DeviceIntPtr device, KeybdCtrl *ctrl) +{ + int leds; + InputInfoPtr pInfo = (InputInfoPtr) device->public.devicePrivate; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + + if ( ctrl->leds & XCOMP ) { + pKbd->keyLeds |= COMPOSEFLAG; + } else { + pKbd->keyLeds &= ~COMPOSEFLAG; + } + leds = ctrl->leds & ~(XCAPS | XNUM | XSCR); /* ??? */ +#ifdef XKB + if (pKbd->noXkb) { +#endif + pKbd->leds = (leds & pKbd->xledsMask) | (pKbd->leds & ~pKbd->xledsMask); +#ifdef XKB + } else { + pKbd->leds = leds; + } +#endif + pKbd->SetLeds(pInfo, pKbd->leds); + + return (Success); +} + +static void +InitKBD(InputInfoPtr pInfo, Bool init) +{ + char rad; + unsigned int i; + xEvent kevent; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + DeviceIntPtr pKeyboard = pInfo->dev; + KeyClassRec *keyc = pKeyboard->key; + KeySym *map = keyc->curKeySyms.map; + + kevent.u.keyButtonPointer.time = GetTimeInMillis(); + kevent.u.keyButtonPointer.rootX = 0; + kevent.u.keyButtonPointer.rootY = 0; + + /* + * Hmm... here is the biggest hack of every time ! + * It may be possible that a switch-vt procedure has finished BEFORE + * you released all keys neccessary to do this. That peculiar behavior + * can fool the X-server pretty much, cause it assumes that some keys + * were not released. TWM may stuck alsmost completly.... + * OK, what we are doing here is after returning from the vt-switch + * exeplicitely unrelease all keyboard keys before the input-devices + * are reenabled. + */ + for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map; + i < keyc->curKeySyms.maxKeyCode; + i++, map += keyc->curKeySyms.mapWidth) + if (KeyPressed(i)) + { + switch (*map) { + /* Don't release the lock keys */ + case XK_Caps_Lock: + case XK_Shift_Lock: + case XK_Num_Lock: + case XK_Scroll_Lock: + case XK_Kana_Lock: + break; + default: + kevent.u.u.detail = i; + kevent.u.u.type = KeyRelease; + (* pKeyboard->public.processInputProc)(&kevent, pKeyboard, 1); + } + } + pKbd->scanPrefix = 0; + + if (init) { + pKbd->keyLeds = 0; + + UpdateLeds(pInfo); + + if( pKbd->delay <= 375) rad = 0x00; + else if (pKbd->delay <= 625) rad = 0x20; + else if (pKbd->delay <= 875) rad = 0x40; + else rad = 0x60; + if (pKbd->rate <= 2) rad |= 0x1F; + else if (pKbd->rate >= 30) rad |= 0x00; + else rad |= ((58 / pKbd->rate) - 2); + pKbd->SetKbdRepeat(pInfo, rad); + } +} + +static int +KbdProc(DeviceIntPtr device, int what) +{ + + InputInfoPtr pInfo = device->public.devicePrivate; + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + int ret; + + switch (what) { + case DEVICE_INIT: + ret = pKbd->KbdInit(pInfo, what); + if (ret != Success) + return ret; + + pKbd->KbdGetMapping(pInfo, &keySyms, modMap); + + device->public.on = FALSE; +#ifdef XKB + if (pKbd->noXkb) { +#endif + InitKeyboardDeviceStruct((DevicePtr) device, + &keySyms, + modMap, + KbdBell, + (KbdCtrlProcPtr)KbdCtrl); +#ifdef XKB + } else { + if (xkbnames.keymap) + xkb_rules = NULL; + XkbSetRulesDflts(xkb_rules, xkb_model, xkb_layout, + xkb_variant, xkb_options); + XkbInitKeyboardDeviceStruct(device, + &xkbnames, + &keySyms, + modMap, + KbdBell, + (KbdCtrlProcPtr)KbdCtrl); + } +#endif + InitKBD(pInfo, TRUE); + break; + case DEVICE_ON: + if (device->public.on) + break; + /* + * Set the keyboard into "direct" mode and turn on + * event translation. + */ + if ((ret = pKbd->KbdOn(pInfo, what)) != Success) + return ret; + /* + * Discard any pending input after a VT switch to prevent the server + * passing on parts of the VT switch sequence. + */ + if (pInfo->fd >= 0) { + sleep(1); + xf86FlushInput(pInfo->fd); + AddEnabledDevice(pInfo->fd); + } + + device->public.on = TRUE; + InitKBD(pInfo, FALSE); + break; + + case DEVICE_CLOSE: + case DEVICE_OFF: + + /* + * Restore original keyboard directness and translation. + */ + if (pInfo->fd != -1) + RemoveEnabledDevice(pInfo->fd); + pKbd->KbdOff(pInfo, what); + device->public.on = FALSE; + break; + } + return (Success); +} + +static void +PostKbdEvent(InputInfoPtr pInfo, unsigned int scanCode, Bool down) +{ + + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + DeviceIntPtr device = pInfo->dev; + KeyClassRec *keyc = device->key; + KbdFeedbackClassRec *kbdfeed = device->kbdfeed; + int specialkey = 0; + + Bool UsePrefix = FALSE; + KeySym *keysym; + int keycode; + unsigned long changeLock = 0; + static int lockkeys = 0; + + /* Disable any keyboard processing while in suspend */ + if (xf86inSuspend) + return; + + /* + * First do some special scancode remapping ... + */ + if (pKbd->RemapScanCode != NULL) { + if (pKbd->RemapScanCode(pInfo, (int*) &scanCode)) + return; + } else { + if (pKbd->scancodeMap != NULL) { + TransMapPtr map = pKbd->scancodeMap; + if (scanCode >= map->begin && scanCode < map->end) + scanCode = map->map[scanCode - map->begin]; + } + } + + /* + * and now get some special keysequences + */ + + specialkey = scanCode; + + if (pKbd->GetSpecialKey != NULL) { + specialkey = pKbd->GetSpecialKey(pInfo, scanCode); + } else { + if (pKbd->specialMap != NULL) { + TransMapPtr map = pKbd->specialMap; + if (scanCode >= map->begin && scanCode < map->end) + specialkey = map->map[scanCode - map->begin]; + } + } + +#ifndef TERMINATE_FALLBACK +#define TERMINATE_FALLBACK 1 +#endif +#ifdef XKB + if (noXkbExtension +#if TERMINATE_FALLBACK + || specialkey == KEY_BackSpace +#endif + ) +#endif + { + if (xf86CommonSpecialKey(specialkey, down, keyc->state)) + return; + if (pKbd->SpecialKey != NULL) + if (pKbd->SpecialKey(pInfo, specialkey, down, keyc->state)) + return; + } + + /* + * Now map the scancodes to real X-keycodes ... + */ + keycode = scanCode + MIN_KEYCODE; + keysym = (keyc->curKeySyms.map + + keyc->curKeySyms.mapWidth * + (keycode - keyc->curKeySyms.minKeyCode)); + +#ifdef XKB + if (pKbd->noXkb) { +#endif + /* + * Filter autorepeated caps/num/scroll lock keycodes. + */ + if( down ) { + switch( keysym[0] ) { + case XK_Caps_Lock : + if (lockkeys & CAPSFLAG) + return; + else + lockkeys |= CAPSFLAG; + break; + + case XK_Num_Lock : + if (lockkeys & NUMFLAG) + return; + else + lockkeys |= NUMFLAG; + break; + + case XK_Scroll_Lock : + if (lockkeys & SCROLLFLAG) + return; + else + lockkeys |= SCROLLFLAG; + break; + } + if (keysym[1] == XF86XK_ModeLock) + { + if (lockkeys & MODEFLAG) + return; + else + lockkeys |= MODEFLAG; + } + } + else { + switch( keysym[0] ) { + case XK_Caps_Lock : + lockkeys &= ~CAPSFLAG; + break; + + case XK_Num_Lock : + lockkeys &= ~NUMFLAG; + break; + + case XK_Scroll_Lock : + lockkeys &= ~SCROLLFLAG; + break; + } + if (keysym[1] == XF86XK_ModeLock) + lockkeys &= ~MODEFLAG; + } + + /* + * LockKey special handling: + * ignore releases, toggle on & off on presses. + * Don't deal with the Caps_Lock keysym directly, but check the lock modifier + */ + + if (keyc->modifierMap[keycode] & LockMask) + changeLock = CAPSFLAG; + if (keysym[0] == XK_Num_Lock) + changeLock = NUMFLAG; + if (keysym[0] == XK_Scroll_Lock) + changeLock = SCROLLFLAG; + if (keysym[1] == XF86XK_ModeLock) + changeLock = MODEFLAG; + + if (changeLock) { + if (!down) + return; + + pKbd->keyLeds &= ~changeLock; + + if (KeyPressed(keycode)) { + down = !down; + } else { + pKbd->keyLeds |= changeLock; + } + UpdateLeds(pInfo); + } + + if (!pKbd->CustomKeycodes) { + /* + * normal, non-keypad keys + */ + if (scanCode < KEY_KP_7 || scanCode > KEY_KP_Decimal) { +#if !defined(CSRG_BASED) && \ + !defined(__GNU__) && \ + defined(KB_84) + /* + * magic ALT_L key on AT84 keyboards for multilingual support + */ + if (pKbd->kbdType == KB_84 && + ModifierDown(AltMask) && + keysym[2] != NoSymbol) + { + UsePrefix = TRUE; + } +#endif /* !CSRG_BASED && ... */ + } + } +#ifdef XKB + } +#endif + + /* + * check for an autorepeat-event + */ + if (down) { + int num = keycode >> 3; + int bit = 1 << (keycode & 7); + if ((keyc->down[num] & bit) && + ((kbdfeed->ctrl.autoRepeat != AutoRepeatModeOn) || + keyc->modifierMap[keycode] || + !(kbdfeed->ctrl.autoRepeats[num] & bit))) + return; + } + + if (UsePrefix) { + xf86PostKeyboardEvent(device, + keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], TRUE); + xf86PostKeyboardEvent(device, keycode, down); + xf86PostKeyboardEvent(device, + keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], FALSE); + } else { + xf86PostKeyboardEvent(device, keycode, down); + } +} + +#ifdef XFree86LOADER +ModuleInfoRec KeyboardInfo = { + 1, + "KBD", + NULL, + 0, + KeyboardAvailableOptions, +}; + +static void +xf86KbdUnplug(pointer p) +{ +} + +static pointer +xf86KbdPlug(pointer module, + pointer options, + int *errmaj, + int *errmin) +{ + static Bool Initialised = FALSE; + + if (!Initialised) { + Initialised = TRUE; +#ifndef REMOVE_LOADER_CHECK_MODULE_INFO + if (xf86LoaderCheckSymbol("xf86AddModuleInfo")) +#endif + xf86AddModuleInfo(&KeyboardInfo, module); + } + + xf86AddInputDriver(&KEYBOARD, module, 0); + + return module; +} + +static XF86ModuleVersionInfo xf86KeyboardVersionRec = +{ + "kbd", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_XINPUT, + ABI_XINPUT_VERSION, + MOD_CLASS_XINPUT, + {0, 0, 0, 0} /* signature, to be patched into the file by */ + /* a tool */ +}; + +XF86ModuleData kbdModuleData = {&xf86KeyboardVersionRec, + xf86KbdPlug, + xf86KbdUnplug}; + +#endif /* XFree86LOADER */ |