diff options
Diffstat (limited to 'xorg-server/hw/dmx/input')
-rw-r--r-- | xorg-server/hw/dmx/input/dmxinputinit.c | 2622 | ||||
-rw-r--r-- | xorg-server/hw/dmx/input/dmxmotion.c | 284 | ||||
-rw-r--r-- | xorg-server/hw/dmx/input/lnx-keyboard.c | 1980 | ||||
-rw-r--r-- | xorg-server/hw/dmx/input/usb-keyboard.c | 888 |
4 files changed, 2887 insertions, 2887 deletions
diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c index 5a486a464..f9acaa039 100644 --- a/xorg-server/hw/dmx/input/dmxinputinit.c +++ b/xorg-server/hw/dmx/input/dmxinputinit.c @@ -1,1311 +1,1311 @@ -/* - * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * Authors: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * This file provides generic input support. Functions here set up - * input and lead to the calling of low-level device drivers for - * input. */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#define DMX_WINDOW_DEBUG 0 - -#include "dmxinputinit.h" -#include "dmxextension.h" /* For dmxInputCount */ - -#include "dmxdummy.h" -#include "dmxbackend.h" -#include "dmxconsole.h" -#include "dmxcommon.h" -#include "dmxevents.h" -#include "dmxmotion.h" -#include "dmxprop.h" -#include "config/dmxconfig.h" -#include "dmxcursor.h" - -#include "lnx-keyboard.h" -#include "lnx-ms.h" -#include "lnx-ps2.h" -#include "usb-keyboard.h" -#include "usb-mouse.h" -#include "usb-other.h" -#include "usb-common.h" - -#include "dmxsigio.h" -#include "dmxarg.h" - -#include "inputstr.h" -#include "input.h" -#include "mipointer.h" -#include "windowstr.h" -#include "mi.h" -#include "xkbsrv.h" - -#include <X11/extensions/XI.h> -#include <X11/extensions/XIproto.h> -#include "exevents.h" -#include "extinit.h" - -DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard; - -static DMXLocalInputInfoRec DMXDummyMou = { - "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo -}; - -static DMXLocalInputInfoRec DMXDummyKbd = { - "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo -}; - -static DMXLocalInputInfoRec DMXBackendMou = { - "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2, - dmxBackendCreatePrivate, dmxBackendDestroyPrivate, - dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo, - dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition, - NULL, NULL, NULL, - dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL, - dmxCommonMouCtrl -}; - -static DMXLocalInputInfoRec DMXBackendKbd = { - "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND, - 1, /* With backend-mou or console-mou */ - dmxCommonCopyPrivate, NULL, - dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo, - dmxCommonKbdOn, dmxCommonKbdOff, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, dmxCommonKbdCtrl, dmxCommonKbdBell -}; - -static DMXLocalInputInfoRec DMXConsoleMou = { - "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2, - dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate, - dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo, - dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition, - NULL, NULL, NULL, - dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo, - dmxCommonMouCtrl -}; - -static DMXLocalInputInfoRec DMXConsoleKbd = { - "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE, - 1, /* With backend-mou or console-mou */ - dmxCommonCopyPrivate, NULL, - dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo, - dmxCommonKbdOn, dmxCommonKbdOff, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, dmxCommonKbdCtrl, dmxCommonKbdBell -}; - -static DMXLocalInputInfoRec DMXCommonOth = { - "common-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_COMMON, 1, - dmxCommonCopyPrivate, NULL, - NULL, NULL, NULL, dmxCommonOthGetInfo, - dmxCommonOthOn, dmxCommonOthOff -}; - - -static DMXLocalInputInfoRec DMXLocalDevices[] = { - /* Dummy drivers that can compile on any OS */ -#ifdef __linux__ - /* Linux-specific drivers */ - { - "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate, - kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo, - kbdLinuxOn, kbdLinuxOff, NULL, - kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch, - kbdLinuxRead, NULL, NULL, NULL, - NULL, kbdLinuxCtrl, kbdLinuxBell - }, - { - "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - msLinuxCreatePrivate, msLinuxDestroyPrivate, - msLinuxInit, NULL, NULL, msLinuxGetInfo, - msLinuxOn, msLinuxOff, NULL, - msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL, - msLinuxRead - }, - { - "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate, - ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo, - ps2LinuxOn, ps2LinuxOff, NULL, - ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL, - ps2LinuxRead - }, -#endif -#ifdef __linux__ - /* USB drivers, currently only for - Linux, but relatively easy to port to - other OSs */ - { - "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - kbdUSBInit, NULL, NULL, kbdUSBGetInfo, - kbdUSBOn, usbOff, NULL, - NULL, NULL, NULL, - kbdUSBRead, NULL, NULL, NULL, - NULL, kbdUSBCtrl - }, - { - "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - mouUSBInit, NULL, NULL, mouUSBGetInfo, - mouUSBOn, usbOff, NULL, - NULL, NULL, NULL, - mouUSBRead - }, - { - "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - othUSBInit, NULL, NULL, othUSBGetInfo, - othUSBOn, usbOff, NULL, - NULL, NULL, NULL, - othUSBRead - }, -#endif - { - "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo - }, - { - "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo - }, - { NULL } /* Must be last */ -}; - - -#if 11 /*BP*/ -void -DDXRingBell(int volume, int pitch, int duration) -{ - /* NO-OP */ -} - -/* taken from kdrive/src/kinput.c: */ -static void -dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) -{ -#if 0 - KdKeyboardInfo *ki; - - for (ki = kdKeyboards; ki; ki = ki->next) { - if (ki->dixdev && ki->dixdev->id == pDevice->id) - break; - } - - if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) - return; - - KdSetLeds(ki, ctrl->leds); - ki->bellPitch = ctrl->bell_pitch; - ki->bellDuration = ctrl->bell_duration; -#endif -} - -/* taken from kdrive/src/kinput.c: */ -static void -dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something) -{ -#if 0 - KeybdCtrl *ctrl = arg; - KdKeyboardInfo *ki = NULL; - - for (ki = kdKeyboards; ki; ki = ki->next) { - if (ki->dixdev && ki->dixdev->id == pDev->id) - break; - } - - if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) - return; - - KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); -#endif -} - -#endif /*BP*/ - -static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal, - PtrCtrl *ctrl) -{ - if (!dmxLocal) return; - dmxLocal->mctrl = *ctrl; - if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl); -} - -/** Change the pointer control information for the \a pDevice. If the - * device sends core events, then also change the control information - * for all of the pointer devices that send core events. */ -void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl) -{ - GETDMXLOCALFROMPDEVICE; - int i, j; - - if (dmxLocal->sendsCore) { /* Do for all core devices */ - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; - for (j = 0; j < dmxInput->numDevs; j++) - if (dmxInput->devs[j]->sendsCore) - _dmxChangePointerControl(dmxInput->devs[j], ctrl); - } - } else { /* Do for this device only */ - _dmxChangePointerControl(dmxLocal, ctrl); - } -} - -static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, - KeybdCtrl *ctrl) -{ - dmxLocal->kctrl = *ctrl; - if (dmxLocal->kCtrl) { - dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl); - if (dmxLocal->pDevice->kbdfeed) { - XkbEventCauseRec cause; - XkbSetCauseUnknown(&cause); - /* Generate XKB events, as necessary */ - XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False, - NULL, &cause); - } - } -} - - -/** Change the keyboard control information for the \a pDevice. If the - * device sends core events, then also change the control information - * for all of the keyboard devices that send core events. */ -void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl) -{ - GETDMXLOCALFROMPDEVICE; - int i, j; - - if (dmxLocal->sendsCore) { /* Do for all core devices */ - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; - for (j = 0; j < dmxInput->numDevs; j++) - if (dmxInput->devs[j]->sendsCore) - _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl); - } - } else { /* Do for this device only */ - _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl); - } -} - -static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent) -{ - if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public, - percent, - dmxLocal->kctrl.bell, - dmxLocal->kctrl.bell_pitch, - dmxLocal->kctrl.bell_duration); -} - -/** Sound the bell on the device. If the device send core events, then - * sound the bell on all of the devices that send core events. */ -void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice, - pointer ctrl, int unknown) -{ - GETDMXLOCALFROMPDEVICE; - int i, j; - - if (dmxLocal->sendsCore) { /* Do for all core devices */ - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; - for (j = 0; j < dmxInput->numDevs; j++) - if (dmxInput->devs[j]->sendsCore) - _dmxKeyboardBellProc(dmxInput->devs[j], percent); - } - } else { /* Do for this device only */ - _dmxKeyboardBellProc(dmxLocal, percent); - } -} - -static void dmxKeyboardFreeNames(XkbComponentNamesPtr names) -{ - if (names->keycodes) XFree(names->keycodes); - if (names->types) XFree(names->types); - if (names->compat) XFree(names->compat); - if (names->symbols) XFree(names->symbols); - if (names->geometry) XFree(names->geometry); -} - - -static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) -{ - GETDMXINPUTFROMPDEVICE; - XkbRMLVOSet rmlvo; - - rmlvo.rules = dmxConfigGetXkbRules(); - rmlvo.model = dmxConfigGetXkbModel(); - rmlvo.layout = dmxConfigGetXkbLayout(); - rmlvo.variant = dmxConfigGetXkbVariant(); - rmlvo.options = dmxConfigGetXkbOptions(); - - XkbSetRulesDflts(&rmlvo); - if (!info->force && (dmxInput->keycodes - || dmxInput->symbols - || dmxInput->geometry)) { - if (info->freenames) dmxKeyboardFreeNames(&info->names); - info->freenames = 0; - info->names.keycodes = dmxInput->keycodes; - info->names.types = NULL; - info->names.compat = NULL; - info->names.symbols = dmxInput->symbols; - info->names.geometry = dmxInput->geometry; - - dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s", - info->names.keycodes); - if (info->names.symbols && *info->names.symbols) - dmxLogInputCont(dmxInput, " %s", info->names.symbols); - if (info->names.geometry && *info->names.geometry) - dmxLogInputCont(dmxInput, " %s", info->names.geometry); - dmxLogInputCont(dmxInput, "\n"); - } else if (info->names.keycodes) { - dmxLogInput(dmxInput, "XKEYBOARD: From device: %s", - info->names.keycodes); - if (info->names.symbols && *info->names.symbols) - dmxLogInputCont(dmxInput, " %s", info->names.symbols); - if (info->names.geometry && *info->names.geometry) - dmxLogInputCont(dmxInput, " %s", info->names.geometry); - dmxLogInputCont(dmxInput, "\n"); - } else { - dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n", - dmxConfigGetXkbRules(), - dmxConfigGetXkbLayout(), - dmxConfigGetXkbModel(), - dmxConfigGetXkbVariant() - ? dmxConfigGetXkbVariant() : "", - dmxConfigGetXkbOptions() - ? dmxConfigGetXkbOptions() : ""); - } - InitKeyboardDeviceStruct(pDevice, &rmlvo, - dmxKeyboardBellProc, - dmxKeyboardKbdCtrlProc); - - if (info->freenames) dmxKeyboardFreeNames(&info->names); - - return Success; -} - - -static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) -{ - GETDMXINPUTFROMPDEVICE; - int fd; - DMXLocalInitInfo info; - int i; - Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */ - Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */ - - if (dmxInput->detached) return Success; - - memset(&info, 0, sizeof(info)); - switch (what) { - case DEVICE_INIT: - if (dmxLocal->init) - dmxLocal->init(pDev); - if (dmxLocal->get_info) - dmxLocal->get_info(pDev, &info); - if (info.keyboard) { /* XKEYBOARD makes this a special case */ - dmxKeyboardOn(pDevice, &info); - break; - } - if (info.keyClass) { - XkbRMLVOSet rmlvo; - - rmlvo.rules = dmxConfigGetXkbRules(); - rmlvo.model = dmxConfigGetXkbModel(); - rmlvo.layout = dmxConfigGetXkbLayout(); - rmlvo.variant = dmxConfigGetXkbVariant(); - rmlvo.options = dmxConfigGetXkbOptions(); - - InitKeyboardDeviceStruct(pDevice, - &rmlvo, - dmxBell, dmxKbdCtrl); - } - if (info.buttonClass) { - InitButtonClassDeviceStruct(pDevice, info.numButtons, - btn_labels, info.map); - } - if (info.valuatorClass) { - if (info.numRelAxes && dmxLocal->sendsCore) { - InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, - axis_labels, - GetMaximumEventsNum(), - Relative); - for (i = 0; i < info.numRelAxes; i++) - InitValuatorAxisStruct(pDevice, i, axis_labels[i], - info.minval[i], info.maxval[i], - info.res[i], - info.minres[i], info.maxres[i]); - } else if (info.numRelAxes) { - InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, - axis_labels, - dmxPointerGetMotionBufferSize(), - Relative); - for (i = 0; i < info.numRelAxes; i++) - InitValuatorAxisStruct(pDevice, i, axis_labels[i], - info.minval[i], - info.maxval[i], info.res[i], - info.minres[i], info.maxres[i]); - } else if (info.numAbsAxes) { - InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes, - axis_labels, - dmxPointerGetMotionBufferSize(), - Absolute); - for (i = 0; i < info.numAbsAxes; i++) - InitValuatorAxisStruct(pDevice, i, - axis_labels[i], - info.minval[i], info.maxval[i], - info.res[i], info.minres[i], - info.maxres[i]); - } - } - if (info.focusClass) InitFocusClassDeviceStruct(pDevice); - if (info.proximityClass) InitProximityClassDeviceStruct(pDevice); - if (info.ptrFeedbackClass) - InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl); - if (info.intFeedbackClass || info.strFeedbackClass) - dmxLog(dmxWarning, - "Integer and string feedback not supported for %s\n", - pDevice->name); - if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass)) - dmxLog(dmxWarning, - "Led and bel feedback not supported for non-keyboard %s\n", - pDevice->name); - break; - case DEVICE_ON: - if (!pDev->on) { - if (dmxLocal->on && (fd = dmxLocal->on(pDev)) >= 0) - dmxSigioRegister(dmxInput, fd); - pDev->on = TRUE; - } - break; - case DEVICE_OFF: - case DEVICE_CLOSE: - /* This can get called twice consecutively: once for a - * detached screen (DEVICE_OFF), and then again at server - * generation time (DEVICE_CLOSE). */ - if (pDev->on) { - dmxSigioUnregister(dmxInput); - if (dmxLocal->off) dmxLocal->off(pDev); - pDev->on = FALSE; - } - break; - } - if (info.keySyms.map && info.freemap) { - XFree(info.keySyms.map); - info.keySyms.map = NULL; - } - if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True); - return Success; -} - -static void dmxProcessInputEvents(DMXInputInfo *dmxInput) -{ - int i; - - mieqProcessInputEvents(); -#if 00 /*BP*/ - miPointerUpdate(); -#endif - if (dmxInput->detached) - return; - for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) - if (dmxInput->devs[i]->process_input) { -#if 11 /*BP*/ - miPointerUpdateSprite(dmxInput->devs[i]->pDevice); -#endif - dmxInput->devs[i]->process_input(dmxInput->devs[i]->private); - } - -#if 11 /*BP*/ - mieqProcessInputEvents(); -#endif -} - -static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput, - DMXUpdateType type, - WindowPtr pWindow) -{ - int i; - -#ifdef PANORAMIX - if (!noPanoramiXExtension && pWindow && pWindow->parent != WindowTable[0]) - return; -#endif -#if DMX_WINDOW_DEBUG - { - const char *name = "Unknown"; - switch (type) { - case DMX_UPDATE_REALIZE: name = "Realize"; break; - case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break; - case DMX_UPDATE_RESTACK: name = "Restack"; break; - case DMX_UPDATE_COPY: name = "Copy"; break; - case DMX_UPDATE_RESIZE: name = "Resize"; break; - case DMX_UPDATE_REPARENT: name = "Repaint"; break; - } - dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name); - } -#endif - - if (dmxInput->detached) - return; - for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) - if (dmxInput->devs[i]->update_info) - dmxInput->devs[i]->update_info(dmxInput->devs[i]->private, - type, pWindow); -} - -static void dmxCollectAll(DMXInputInfo *dmxInput) -{ - int i; - - if (dmxInput->detached) - return; - for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) - if (dmxInput->devs[i]->collect_events) - dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public, - dmxMotion, - dmxEnqueue, - dmxCheckSpecialKeys, DMX_BLOCK); -} - -static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout, - pointer pReadMask) -{ - DMXInputInfo *dmxInput = &dmxInputs[(int)blockData]; - static unsigned long generation = 0; - - if (generation != serverGeneration) { - generation = serverGeneration; - dmxCollectAll(dmxInput); - } -} - -static void dmxSwitchReturn(pointer p) -{ - DMXInputInfo *dmxInput = p; - int i; - - dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched); - - if (!dmxInput->vt_switched) - dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n"); - dmxSigioEnableInput(); - for (i = 0; i < dmxInput->numDevs; i++) - if (dmxInput->devs[i]->vt_post_switch) - dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private); - dmxInput->vt_switched = 0; -} - -static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask) -{ - DMXInputInfo *dmxInput = &dmxInputs[(int)blockData]; - int i; - - if (dmxInput->vt_switch_pending) { - dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending); - for (i = 0; i < dmxInput->numDevs; i++) - if (dmxInput->devs[i]->vt_pre_switch) - dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private); - dmxInput->vt_switched = dmxInput->vt_switch_pending; - dmxInput->vt_switch_pending = 0; - for (i = 0; i < dmxInput->numDevs; i++) { - if (dmxInput->devs[i]->vt_switch) { - dmxSigioDisableInput(); - if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private, - dmxInput->vt_switched, - dmxSwitchReturn, - dmxInput)) - dmxSwitchReturn(dmxInput); - break; /* Only call one vt_switch routine */ - } - } - } - dmxCollectAll(dmxInput); -} - -static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal) -{ - static int k = 0; - static int m = 0; - static int o = 0; - static unsigned long dmxGeneration = 0; -#define LEN 32 - char * buf = xalloc(LEN); - - if (dmxGeneration != serverGeneration) { - k = m = o = 0; - dmxGeneration = serverGeneration; - } - - switch (dmxLocal->type) { - case DMX_LOCAL_KEYBOARD: XmuSnprintf(buf, LEN, "Keyboard%d", k++); break; - case DMX_LOCAL_MOUSE: XmuSnprintf(buf, LEN, "Mouse%d", m++); break; - default: XmuSnprintf(buf, LEN, "Other%d", o++); break; - } - - return buf; -} - -static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) -{ - DeviceIntPtr pDevice; - Atom atom; - const char *name = NULL; - void (*registerProcPtr)(DeviceIntPtr) = NULL; - char *devname; - DMXInputInfo *dmxInput; - - if (!dmxLocal) - return NULL; - dmxInput = &dmxInputs[dmxLocal->inputIdx]; - - if (dmxLocal->sendsCore) { - if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) { - dmxLocal->isCore = 1; - dmxLocalCoreKeyboard = dmxLocal; - name = "keyboard"; - registerProcPtr = RegisterKeyboardDevice; - } - if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) { - dmxLocal->isCore = 1; - dmxLocalCorePointer = dmxLocal; - name = "pointer"; - registerProcPtr = RegisterPointerDevice; - } - } - - if (!name) { - name = "extension"; - registerProcPtr = RegisterOtherDevice; - } - - if (!name || !registerProcPtr) - dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name); - - pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE); - if (!pDevice) { - dmxLog(dmxError, "Too many devices -- cannot add device %s\n", - dmxLocal->name); - return NULL; - } - pDevice->public.devicePrivate = dmxLocal; - dmxLocal->pDevice = pDevice; - - devname = dmxMakeUniqueDeviceName(dmxLocal); - atom = MakeAtom((char *)devname, strlen(devname), TRUE); - pDevice->type = atom; - pDevice->name = devname; - - registerProcPtr(pDevice); - - if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) { -#if 00 /*BP*/ - miRegisterPointerDevice(screenInfo.screens[0], pDevice); -#else - /* Nothing? dmxDeviceOnOff() should get called to init, right? */ -#endif - } - - if (dmxLocal->create_private) - dmxLocal->private = dmxLocal->create_private(pDevice); - - dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n", - dmxLocal->name, name, devname, - dmxLocal->isCore - ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); - - return pDevice; -} - -static DMXLocalInputInfoPtr dmxLookupLocal(const char *name) -{ - DMXLocalInputInfoPtr pt; - - for (pt = &DMXLocalDevices[0]; pt->name; ++pt) - if (!strcmp(pt->name, name)) return pt; /* search for device name */ - return NULL; -} - -/** Copy the local input information from \a s into a new \a devs slot - * in \a dmxInput. */ -DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput, - DMXLocalInputInfoPtr s) -{ - DMXLocalInputInfoPtr dmxLocal = xalloc(sizeof(*dmxLocal)); - - if (!dmxLocal) - dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n"); - - memcpy(dmxLocal, s, sizeof(*dmxLocal)); - dmxLocal->inputIdx = dmxInput->inputIdx; - dmxLocal->sendsCore = dmxInput->core; - dmxLocal->savedSendsCore = dmxInput->core; - dmxLocal->deviceId = -1; - - ++dmxInput->numDevs; - dmxInput->devs = xrealloc(dmxInput->devs, - dmxInput->numDevs * sizeof(*dmxInput->devs)); - dmxInput->devs[dmxInput->numDevs-1] = dmxLocal; - - return dmxLocal; -} - -static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a) -{ - int i; - int help = 0; - DMXLocalInputInfoRec *pt; - - for (i = 1; i < dmxArgC(a); i++) { - const char *name = dmxArgV(a, i); - if ((pt = dmxLookupLocal(name))) { - dmxInputCopyLocal(dmxInput, pt); - } else { - if (strlen(name)) - dmxLog(dmxWarning, - "Could not find a driver called %s\n", name); - ++help; - } - } - if (help) { - dmxLog(dmxInfo, "Available local device drivers:\n"); - for (pt = &DMXLocalDevices[0]; pt->name; ++pt) { - const char *type; - switch (pt->type) { - case DMX_LOCAL_KEYBOARD: type = "keyboard"; break; - case DMX_LOCAL_MOUSE: type = "pointer"; break; - default: type = "unknown"; break; - } - dmxLog(dmxInfo, " %s (%s)\n", pt->name, type); - } - dmxLog(dmxFatal, "Must have valid local device driver\n"); - } -} - -int dmxInputExtensionErrorHandler(Display *dsp, char *name, char *reason) -{ - return 0; -} - -static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) -{ - XExtensionVersion *ext; - XDeviceInfo *devices; - Display *display; - int num; - int i, j; - DMXLocalInputInfoPtr dmxLocal; - int (*handler)(Display *, char *, char *); - - if (!(display = XOpenDisplay(dmxInput->name))) return; - - /* Print out information about the XInput Extension. */ - handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler); - ext = XGetExtensionVersion(display, INAME); - XSetExtensionErrorHandler(handler); - - if (!ext || ext == (XExtensionVersion *)NoSuchExtension) { - dmxLogInput(dmxInput, "%s is not available\n", INAME); - } else { - dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n", - dmxInput->name, INAME, - ext->major_version, ext->minor_version); - devices = XListInputDevices(display, &num); - - XFree(ext); - ext = NULL; - - /* Print a list of all devices */ - for (i = 0; i < num; i++) { - const char *use = "Unknown"; - switch (devices[i].use) { - case IsXPointer: use = "XPointer"; break; - case IsXKeyboard: use = "XKeyboard"; break; - case IsXExtensionDevice: use = "XExtensionDevice"; break; - case IsXExtensionPointer: use = "XExtensionPointer"; break; - case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break; - } - dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n", - devices[i].id, - devices[i].name ? devices[i].name : "", - use); - } - - /* Search for extensions */ - for (i = 0; i < num; i++) { - switch (devices[i].use) { - case IsXKeyboard: - for (j = 0; j < dmxInput->numDevs; j++) { - DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; - if (dmxL->type == DMX_LOCAL_KEYBOARD - && dmxL->deviceId < 0) { - dmxL->deviceId = devices[i].id; - dmxL->deviceName = (devices[i].name - ? xstrdup(devices[i].name) - : NULL); - } - } - break; - case IsXPointer: - for (j = 0; j < dmxInput->numDevs; j++) { - DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; - if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) { - dmxL->deviceId = devices[i].id; - dmxL->deviceName = (devices[i].name - ? xstrdup(devices[i].name) - : NULL); - } - } - break; -#if 0 - case IsXExtensionDevice: - case IsXExtensionKeyboard: - case IsXExtensionPointer: - if (doXI) { - if (!dmxInput->numDevs) { - dmxLog(dmxWarning, - "Cannot use remote (%s) XInput devices if" - " not also using core devices\n", - dmxInput->name); - } else { - dmxLocal = dmxInputCopyLocal(dmxInput, - &DMXCommonOth); - dmxLocal->isCore = FALSE; - dmxLocal->sendsCore = FALSE; - dmxLocal->deviceId = devices[i].id; - dmxLocal->deviceName = (devices[i].name - ? xstrdup(devices[i].name) - : NULL); - } - } - break; -#endif - } - } - XFreeDeviceList(devices); - } - XCloseDisplay(display); -} - -/** Re-initialize all the devices described in \a dmxInput. Called from - #dmxAdjustCursorBoundaries before the cursor is redisplayed. */ -void dmxInputReInit(DMXInputInfo *dmxInput) -{ - int i; - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (dmxLocal->reinit) - dmxLocal->reinit(&dmxLocal->pDevice->public); - } -} - -/** Re-initialize all the devices described in \a dmxInput. Called from - #dmxAdjustCursorBoundaries after the cursor is redisplayed. */ -void dmxInputLateReInit(DMXInputInfo *dmxInput) -{ - int i; - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (dmxLocal->latereinit) - dmxLocal->latereinit(&dmxLocal->pDevice->public); - } -} - -/** Initialize all of the devices described in \a dmxInput. */ -void dmxInputInit(DMXInputInfo *dmxInput) -{ - DeviceIntPtr pPointer = NULL, pKeyboard = NULL; - dmxArg a; - const char *name; - int i; - int doXI = 1; /* Include by default */ - int forceConsole = 0; - int doWindows = 1; /* On by default */ - int hasXkb = 0; - - a = dmxArgParse(dmxInput->name); - - for (i = 1; i < dmxArgC(a); i++) { - switch (hasXkb) { - case 1: - dmxInput->keycodes = xstrdup(dmxArgV(a, i)); - ++hasXkb; - break; - case 2: - dmxInput->symbols = xstrdup(dmxArgV(a, i)); - ++hasXkb; - break; - case 3: - dmxInput->geometry = xstrdup(dmxArgV(a, i)); - hasXkb = 0; - break; - case 0: - if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0; - else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1; - else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1; - else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0; - else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1; - else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0; - else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1; - else { - dmxLog(dmxFatal, - "Unknown input argument: %s\n", dmxArgV(a, i)); - } - } - } - - name = dmxArgV(a, 0); - - if (!strcmp(name, "local")) { - dmxPopulateLocal(dmxInput, a); - } else if (!strcmp(name, "dummy")) { - dmxInputCopyLocal(dmxInput, &DMXDummyMou); - dmxInputCopyLocal(dmxInput, &DMXDummyKbd); - dmxLogInput(dmxInput, "Using dummy input\n"); - } else { - int found; - - for (found = 0, i = 0; i < dmxNumScreens; i++) { - if (dmxPropertySameDisplay(&dmxScreens[i], name)) { - if (dmxScreens[i].shared) - dmxLog(dmxFatal, - "Cannot take input from shared backend (%s)\n", - name); - if (!dmxInput->core) { - dmxLog(dmxWarning, - "Cannot use core devices on a backend (%s)" - " as XInput devices\n", name); - } else { - char *pt; - for (pt = (char *)dmxInput->name; pt && *pt; pt++) - if (*pt == ',') *pt = '\0'; - dmxInputCopyLocal(dmxInput, &DMXBackendMou); - dmxInputCopyLocal(dmxInput, &DMXBackendKbd); - dmxInput->scrnIdx = i; - dmxLogInput(dmxInput, - "Using backend input from %s\n", name); - } - ++found; - break; - } - } - if (!found || forceConsole) { - char *pt; - if (found) dmxInput->console = TRUE; - for (pt = (char *)dmxInput->name; pt && *pt; pt++) - if (*pt == ',') *pt = '\0'; - dmxInputCopyLocal(dmxInput, &DMXConsoleMou); - dmxInputCopyLocal(dmxInput, &DMXConsoleKbd); - if (doWindows) { - dmxInput->windows = TRUE; - dmxInput->updateWindowInfo = dmxUpdateWindowInformation; - } - dmxLogInput(dmxInput, - "Using console input from %s (%s windows)\n", - name, doWindows ? "with" : "without"); - } - } - - dmxArgFree(a); - - /* Locate extensions we may be interested in */ - dmxInputScanForExtensions(dmxInput, doXI); - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - dmxLocal->pDevice = dmxAddDevice(dmxLocal); - if (dmxLocal->isCore) { - if (dmxLocal->type == DMX_LOCAL_MOUSE) - pPointer = dmxLocal->pDevice; - if (dmxLocal->type == DMX_LOCAL_KEYBOARD) - pKeyboard = dmxLocal->pDevice; - } - } - - dmxInput->processInputEvents = dmxProcessInputEvents; - dmxInput->detached = False; - - RegisterBlockAndWakeupHandlers(dmxBlockHandler, - dmxWakeupHandler, - (void *)dmxInput->inputIdx); -} - -static void dmxInputFreeLocal(DMXLocalInputInfoRec *local) -{ - if (!local) return; - if (local->isCore && local->type == DMX_LOCAL_MOUSE) - dmxLocalCorePointer = NULL; - if (local->isCore && local->type == DMX_LOCAL_KEYBOARD) - dmxLocalCoreKeyboard = NULL; - if (local->destroy_private) local->destroy_private(local->private); - if (local->history) xfree(local->history); - if (local->valuators) xfree(local->valuators); - if (local->deviceName) xfree(local->deviceName); - local->private = NULL; - local->history = NULL; - local->deviceName = NULL; - xfree(local); -} - -/** Free all of the memory associated with \a dmxInput */ -void dmxInputFree(DMXInputInfo *dmxInput) -{ - int i; - - if (!dmxInput) return; - - if (dmxInput->keycodes) xfree(dmxInput->keycodes); - if (dmxInput->symbols) xfree(dmxInput->symbols); - if (dmxInput->geometry) xfree(dmxInput->geometry); - - for (i = 0; i < dmxInput->numDevs; i++) { - dmxInputFreeLocal(dmxInput->devs[i]); - dmxInput->devs[i] = NULL; - } - xfree(dmxInput->devs); - dmxInput->devs = NULL; - dmxInput->numDevs = 0; - if (dmxInput->freename) xfree(dmxInput->name); - dmxInput->name = NULL; -} - -/** Log information about all of the known devices using #dmxLog(). */ -void dmxInputLogDevices(void) -{ - int i, j; - - dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount()); - dmxLog(dmxInfo, " Id Name Classes\n"); - for (j = 0; j < dmxNumInputs; j++) { - DMXInputInfo *dmxInput = &dmxInputs[j]; - const char *pt = strchr(dmxInput->name, ','); - int len = (pt - ? (size_t)(pt-dmxInput->name) - : strlen(dmxInput->name)); - - for (i = 0; i < dmxInput->numDevs; i++) { - DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice; - if (pDevice) { - dmxLog(dmxInfo, " %2d%c %-20.20s", - pDevice->id, - dmxInput->detached ? 'D' : ' ', - pDevice->name); - if (pDevice->key) dmxLogCont(dmxInfo, " key"); - if (pDevice->valuator) dmxLogCont(dmxInfo, " val"); - if (pDevice->button) dmxLogCont(dmxInfo, " btn"); - if (pDevice->focus) dmxLogCont(dmxInfo, " foc"); - if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd"); - if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr"); - if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int"); - if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str"); - if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel"); - if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led"); - if (!pDevice->key && !pDevice->valuator && !pDevice->button - && !pDevice->focus && !pDevice->kbdfeed - && !pDevice->ptrfeed && !pDevice->intfeed - && !pDevice->stringfeed && !pDevice->bell - && !pDevice->leds) dmxLogCont(dmxInfo, " (none)"); - - dmxLogCont(dmxInfo, "\t[i%d/%*.*s", - dmxInput->inputIdx, len, len, dmxInput->name); - if (dmxInput->devs[i]->deviceId >= 0) - dmxLogCont(dmxInfo, "/id%d", dmxInput->devs[i]->deviceId); - if (dmxInput->devs[i]->deviceName) - dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName); - dmxLogCont(dmxInfo, "] %s\n", - dmxInput->devs[i]->isCore - ? "core" - : (dmxInput->devs[i]->sendsCore - ? "extension (sends core events)" - : "extension")); - } - } - } -} - -/** Detach an input */ -int dmxInputDetach(DMXInputInfo *dmxInput) -{ - int i; - - if (dmxInput->detached) return BadAccess; - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n", - dmxLocal->pDevice->id, - dmxLocal->pDevice->name, - dmxLocal->isCore - ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); - DisableDevice(dmxLocal->pDevice, TRUE); - } - dmxInput->detached = True; - dmxInputLogDevices(); - return 0; -} - -/** Search for input associated with \a dmxScreen, and detach. */ -void dmxInputDetachAll(DMXScreenInfo *dmxScreen) -{ - int i; - - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput); - } -} - -/** Search for input associated with \a deviceId, and detach. */ -int dmxInputDetachId(int id) -{ - DMXInputInfo *dmxInput = dmxInputLocateId(id); - - if (!dmxInput) return BadValue; - - return dmxInputDetach(dmxInput); -} - -DMXInputInfo *dmxInputLocateId(int id) -{ - int i, j; - - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - for (j = 0; j < dmxInput->numDevs; j++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j]; - if (dmxLocal->pDevice->id == id) return dmxInput; - } - } - return NULL; -} - -static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id) -{ - dmxInputInit(dmxInput); - InitAndStartDevices(); - if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id; - dmxInputLogDevices(); - return 0; -} - -static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id) -{ - int i; - - dmxInput->detached = False; - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (id) *id = dmxLocal->pDevice->id; - dmxLogInput(dmxInput, - "Attaching device id %d: %s%s\n", - dmxLocal->pDevice->id, - dmxLocal->pDevice->name, - dmxLocal->isCore - ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); - EnableDevice(dmxLocal->pDevice, TRUE); - } - dmxInputLogDevices(); - return 0; -} - -int dmxInputAttachConsole(const char *name, int isCore, int *id) -{ - DMXInputInfo *dmxInput; - int i; - - for (i = 0; i < dmxNumInputs; i++) { - dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx == -1 - && dmxInput->detached - && !strcmp(dmxInput->name, name)) { - /* Found match */ - dmxLogInput(dmxInput, "Reattaching detached console input\n"); - return dmxInputAttachOld(dmxInput, id); - } - } - - /* No match found */ - dmxInput = dmxConfigAddInput(xstrdup(name), isCore); - dmxInput->freename = TRUE; - dmxLogInput(dmxInput, "Attaching new console input\n"); - return dmxInputAttachNew(dmxInput, id); -} - -int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) -{ - DMXInputInfo *dmxInput; - DMXScreenInfo *dmxScreen; - int i; - - if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue; - for (i = 0; i < dmxNumInputs; i++) { - dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) { - /* Found match */ - if (!dmxInput->detached) return BadAccess; /* Already attached */ - dmxScreen = &dmxScreens[physicalScreen]; - if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ - dmxLogInput(dmxInput, "Reattaching detached backend input\n"); - return dmxInputAttachOld(dmxInput, id); - } - } - /* No match found */ - dmxScreen = &dmxScreens[physicalScreen]; - if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ - dmxInput = dmxConfigAddInput(dmxScreen->name, isCore); - dmxLogInput(dmxInput, "Attaching new backend input\n"); - return dmxInputAttachNew(dmxInput, id); -} +/*
+ * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides generic input support. Functions here set up
+ * input and lead to the calling of low-level device drivers for
+ * input. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#define DMX_WINDOW_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxextension.h" /* For dmxInputCount */
+
+#include "dmxdummy.h"
+#include "dmxbackend.h"
+#include "dmxconsole.h"
+#include "dmxcommon.h"
+#include "dmxevents.h"
+#include "dmxmotion.h"
+#include "dmxprop.h"
+#include "config/dmxconfig.h"
+#include "dmxcursor.h"
+
+#include "lnx-keyboard.h"
+#include "lnx-ms.h"
+#include "lnx-ps2.h"
+#include "usb-keyboard.h"
+#include "usb-mouse.h"
+#include "usb-other.h"
+#include "usb-common.h"
+
+#include "dmxsigio.h"
+#include "dmxarg.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include "mipointer.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "xkbsrv.h"
+
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "exevents.h"
+#include "extinit.h"
+
+DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;
+
+static DMXLocalInputInfoRec DMXDummyMou = {
+ "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
+};
+
+static DMXLocalInputInfoRec DMXDummyKbd = {
+ "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
+};
+
+static DMXLocalInputInfoRec DMXBackendMou = {
+ "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2,
+ dmxBackendCreatePrivate, dmxBackendDestroyPrivate,
+ dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo,
+ dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition,
+ NULL, NULL, NULL,
+ dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL,
+ dmxCommonMouCtrl
+};
+
+static DMXLocalInputInfoRec DMXBackendKbd = {
+ "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND,
+ 1, /* With backend-mou or console-mou */
+ dmxCommonCopyPrivate, NULL,
+ dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo,
+ dmxCommonKbdOn, dmxCommonKbdOff, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
+};
+
+static DMXLocalInputInfoRec DMXConsoleMou = {
+ "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2,
+ dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate,
+ dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo,
+ dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition,
+ NULL, NULL, NULL,
+ dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo,
+ dmxCommonMouCtrl
+};
+
+static DMXLocalInputInfoRec DMXConsoleKbd = {
+ "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE,
+ 1, /* With backend-mou or console-mou */
+ dmxCommonCopyPrivate, NULL,
+ dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo,
+ dmxCommonKbdOn, dmxCommonKbdOff, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
+};
+
+static DMXLocalInputInfoRec DMXCommonOth = {
+ "common-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_COMMON, 1,
+ dmxCommonCopyPrivate, NULL,
+ NULL, NULL, NULL, dmxCommonOthGetInfo,
+ dmxCommonOthOn, dmxCommonOthOff
+};
+
+
+static DMXLocalInputInfoRec DMXLocalDevices[] = {
+ /* Dummy drivers that can compile on any OS */
+#ifdef __linux__
+ /* Linux-specific drivers */
+ {
+ "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate,
+ kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo,
+ kbdLinuxOn, kbdLinuxOff, NULL,
+ kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch,
+ kbdLinuxRead, NULL, NULL, NULL,
+ NULL, kbdLinuxCtrl, kbdLinuxBell
+ },
+ {
+ "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ msLinuxCreatePrivate, msLinuxDestroyPrivate,
+ msLinuxInit, NULL, NULL, msLinuxGetInfo,
+ msLinuxOn, msLinuxOff, NULL,
+ msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL,
+ msLinuxRead
+ },
+ {
+ "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate,
+ ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo,
+ ps2LinuxOn, ps2LinuxOff, NULL,
+ ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL,
+ ps2LinuxRead
+ },
+#endif
+#ifdef __linux__
+ /* USB drivers, currently only for
+ Linux, but relatively easy to port to
+ other OSs */
+ {
+ "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ usbCreatePrivate, usbDestroyPrivate,
+ kbdUSBInit, NULL, NULL, kbdUSBGetInfo,
+ kbdUSBOn, usbOff, NULL,
+ NULL, NULL, NULL,
+ kbdUSBRead, NULL, NULL, NULL,
+ NULL, kbdUSBCtrl
+ },
+ {
+ "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ usbCreatePrivate, usbDestroyPrivate,
+ mouUSBInit, NULL, NULL, mouUSBGetInfo,
+ mouUSBOn, usbOff, NULL,
+ NULL, NULL, NULL,
+ mouUSBRead
+ },
+ {
+ "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1,
+ usbCreatePrivate, usbDestroyPrivate,
+ othUSBInit, NULL, NULL, othUSBGetInfo,
+ othUSBOn, usbOff, NULL,
+ NULL, NULL, NULL,
+ othUSBRead
+ },
+#endif
+ {
+ "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
+ },
+ {
+ "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
+ },
+ { NULL } /* Must be last */
+};
+
+
+#if 11 /*BP*/
+void
+DDXRingBell(int volume, int pitch, int duration)
+{
+ /* NO-OP */
+}
+
+/* taken from kdrive/src/kinput.c: */
+static void
+dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+#if 0
+ KdKeyboardInfo *ki;
+
+ for (ki = kdKeyboards; ki; ki = ki->next) {
+ if (ki->dixdev && ki->dixdev->id == pDevice->id)
+ break;
+ }
+
+ if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
+ return;
+
+ KdSetLeds(ki, ctrl->leds);
+ ki->bellPitch = ctrl->bell_pitch;
+ ki->bellDuration = ctrl->bell_duration;
+#endif
+}
+
+/* taken from kdrive/src/kinput.c: */
+static void
+dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
+{
+#if 0
+ KeybdCtrl *ctrl = arg;
+ KdKeyboardInfo *ki = NULL;
+
+ for (ki = kdKeyboards; ki; ki = ki->next) {
+ if (ki->dixdev && ki->dixdev->id == pDev->id)
+ break;
+ }
+
+ if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
+ return;
+
+ KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
+#endif
+}
+
+#endif /*BP*/
+
+static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal,
+ PtrCtrl *ctrl)
+{
+ if (!dmxLocal) return;
+ dmxLocal->mctrl = *ctrl;
+ if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl);
+}
+
+/** Change the pointer control information for the \a pDevice. If the
+ * device sends core events, then also change the control information
+ * for all of the pointer devices that send core events. */
+void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int i, j;
+
+ if (dmxLocal->sendsCore) { /* Do for all core devices */
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->detached) continue;
+ for (j = 0; j < dmxInput->numDevs; j++)
+ if (dmxInput->devs[j]->sendsCore)
+ _dmxChangePointerControl(dmxInput->devs[j], ctrl);
+ }
+ } else { /* Do for this device only */
+ _dmxChangePointerControl(dmxLocal, ctrl);
+ }
+}
+
+static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal,
+ KeybdCtrl *ctrl)
+{
+ dmxLocal->kctrl = *ctrl;
+ if (dmxLocal->kCtrl) {
+ dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl);
+ if (dmxLocal->pDevice->kbdfeed) {
+ XkbEventCauseRec cause;
+ XkbSetCauseUnknown(&cause);
+ /* Generate XKB events, as necessary */
+ XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False,
+ NULL, &cause);
+ }
+ }
+}
+
+
+/** Change the keyboard control information for the \a pDevice. If the
+ * device sends core events, then also change the control information
+ * for all of the keyboard devices that send core events. */
+void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int i, j;
+
+ if (dmxLocal->sendsCore) { /* Do for all core devices */
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->detached) continue;
+ for (j = 0; j < dmxInput->numDevs; j++)
+ if (dmxInput->devs[j]->sendsCore)
+ _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl);
+ }
+ } else { /* Do for this device only */
+ _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl);
+ }
+}
+
+static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent)
+{
+ if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public,
+ percent,
+ dmxLocal->kctrl.bell,
+ dmxLocal->kctrl.bell_pitch,
+ dmxLocal->kctrl.bell_duration);
+}
+
+/** Sound the bell on the device. If the device send core events, then
+ * sound the bell on all of the devices that send core events. */
+void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice,
+ pointer ctrl, int unknown)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int i, j;
+
+ if (dmxLocal->sendsCore) { /* Do for all core devices */
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->detached) continue;
+ for (j = 0; j < dmxInput->numDevs; j++)
+ if (dmxInput->devs[j]->sendsCore)
+ _dmxKeyboardBellProc(dmxInput->devs[j], percent);
+ }
+ } else { /* Do for this device only */
+ _dmxKeyboardBellProc(dmxLocal, percent);
+ }
+}
+
+static void dmxKeyboardFreeNames(XkbComponentNamesPtr names)
+{
+ if (names->keycodes) XFree(names->keycodes);
+ if (names->types) XFree(names->types);
+ if (names->compat) XFree(names->compat);
+ if (names->symbols) XFree(names->symbols);
+ if (names->geometry) XFree(names->geometry);
+}
+
+
+static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info)
+{
+ GETDMXINPUTFROMPDEVICE;
+ XkbRMLVOSet rmlvo;
+
+ rmlvo.rules = dmxConfigGetXkbRules();
+ rmlvo.model = dmxConfigGetXkbModel();
+ rmlvo.layout = dmxConfigGetXkbLayout();
+ rmlvo.variant = dmxConfigGetXkbVariant();
+ rmlvo.options = dmxConfigGetXkbOptions();
+
+ XkbSetRulesDflts(&rmlvo);
+ if (!info->force && (dmxInput->keycodes
+ || dmxInput->symbols
+ || dmxInput->geometry)) {
+ if (info->freenames) dmxKeyboardFreeNames(&info->names);
+ info->freenames = 0;
+ info->names.keycodes = dmxInput->keycodes;
+ info->names.types = NULL;
+ info->names.compat = NULL;
+ info->names.symbols = dmxInput->symbols;
+ info->names.geometry = dmxInput->geometry;
+
+ dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s",
+ info->names.keycodes);
+ if (info->names.symbols && *info->names.symbols)
+ dmxLogInputCont(dmxInput, " %s", info->names.symbols);
+ if (info->names.geometry && *info->names.geometry)
+ dmxLogInputCont(dmxInput, " %s", info->names.geometry);
+ dmxLogInputCont(dmxInput, "\n");
+ } else if (info->names.keycodes) {
+ dmxLogInput(dmxInput, "XKEYBOARD: From device: %s",
+ info->names.keycodes);
+ if (info->names.symbols && *info->names.symbols)
+ dmxLogInputCont(dmxInput, " %s", info->names.symbols);
+ if (info->names.geometry && *info->names.geometry)
+ dmxLogInputCont(dmxInput, " %s", info->names.geometry);
+ dmxLogInputCont(dmxInput, "\n");
+ } else {
+ dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n",
+ dmxConfigGetXkbRules(),
+ dmxConfigGetXkbLayout(),
+ dmxConfigGetXkbModel(),
+ dmxConfigGetXkbVariant()
+ ? dmxConfigGetXkbVariant() : "",
+ dmxConfigGetXkbOptions()
+ ? dmxConfigGetXkbOptions() : "");
+ }
+ InitKeyboardDeviceStruct(pDevice, &rmlvo,
+ dmxKeyboardBellProc,
+ dmxKeyboardKbdCtrlProc);
+
+ if (info->freenames) dmxKeyboardFreeNames(&info->names);
+
+ return Success;
+}
+
+
+static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
+{
+ GETDMXINPUTFROMPDEVICE;
+ int fd;
+ DMXLocalInitInfo info;
+ int i;
+ Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */
+ Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */
+
+ if (dmxInput->detached) return Success;
+
+ memset(&info, 0, sizeof(info));
+ switch (what) {
+ case DEVICE_INIT:
+ if (dmxLocal->init)
+ dmxLocal->init(pDev);
+ if (dmxLocal->get_info)
+ dmxLocal->get_info(pDev, &info);
+ if (info.keyboard) { /* XKEYBOARD makes this a special case */
+ dmxKeyboardOn(pDevice, &info);
+ break;
+ }
+ if (info.keyClass) {
+ XkbRMLVOSet rmlvo;
+
+ rmlvo.rules = dmxConfigGetXkbRules();
+ rmlvo.model = dmxConfigGetXkbModel();
+ rmlvo.layout = dmxConfigGetXkbLayout();
+ rmlvo.variant = dmxConfigGetXkbVariant();
+ rmlvo.options = dmxConfigGetXkbOptions();
+
+ InitKeyboardDeviceStruct(pDevice,
+ &rmlvo,
+ dmxBell, dmxKbdCtrl);
+ }
+ if (info.buttonClass) {
+ InitButtonClassDeviceStruct(pDevice, info.numButtons,
+ btn_labels, info.map);
+ }
+ if (info.valuatorClass) {
+ if (info.numRelAxes && dmxLocal->sendsCore) {
+ InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
+ axis_labels,
+ GetMaximumEventsNum(),
+ Relative);
+ for (i = 0; i < info.numRelAxes; i++)
+ InitValuatorAxisStruct(pDevice, i, axis_labels[i],
+ info.minval[i], info.maxval[i],
+ info.res[i],
+ info.minres[i], info.maxres[i]);
+ } else if (info.numRelAxes) {
+ InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
+ axis_labels,
+ dmxPointerGetMotionBufferSize(),
+ Relative);
+ for (i = 0; i < info.numRelAxes; i++)
+ InitValuatorAxisStruct(pDevice, i, axis_labels[i],
+ info.minval[i],
+ info.maxval[i], info.res[i],
+ info.minres[i], info.maxres[i]);
+ } else if (info.numAbsAxes) {
+ InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes,
+ axis_labels,
+ dmxPointerGetMotionBufferSize(),
+ Absolute);
+ for (i = 0; i < info.numAbsAxes; i++)
+ InitValuatorAxisStruct(pDevice, i,
+ axis_labels[i],
+ info.minval[i], info.maxval[i],
+ info.res[i], info.minres[i],
+ info.maxres[i]);
+ }
+ }
+ if (info.focusClass) InitFocusClassDeviceStruct(pDevice);
+ if (info.proximityClass) InitProximityClassDeviceStruct(pDevice);
+ if (info.ptrFeedbackClass)
+ InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl);
+ if (info.intFeedbackClass || info.strFeedbackClass)
+ dmxLog(dmxWarning,
+ "Integer and string feedback not supported for %s\n",
+ pDevice->name);
+ if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass))
+ dmxLog(dmxWarning,
+ "Led and bel feedback not supported for non-keyboard %s\n",
+ pDevice->name);
+ break;
+ case DEVICE_ON:
+ if (!pDev->on) {
+ if (dmxLocal->on && (fd = dmxLocal->on(pDev)) >= 0)
+ dmxSigioRegister(dmxInput, fd);
+ pDev->on = TRUE;
+ }
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ /* This can get called twice consecutively: once for a
+ * detached screen (DEVICE_OFF), and then again at server
+ * generation time (DEVICE_CLOSE). */
+ if (pDev->on) {
+ dmxSigioUnregister(dmxInput);
+ if (dmxLocal->off) dmxLocal->off(pDev);
+ pDev->on = FALSE;
+ }
+ break;
+ }
+ if (info.keySyms.map && info.freemap) {
+ XFree(info.keySyms.map);
+ info.keySyms.map = NULL;
+ }
+ if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True);
+ return Success;
+}
+
+static void dmxProcessInputEvents(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ mieqProcessInputEvents();
+#if 00 /*BP*/
+ miPointerUpdate();
+#endif
+ if (dmxInput->detached)
+ return;
+ for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->process_input) {
+#if 11 /*BP*/
+ miPointerUpdateSprite(dmxInput->devs[i]->pDevice);
+#endif
+ dmxInput->devs[i]->process_input(dmxInput->devs[i]->private);
+ }
+
+#if 11 /*BP*/
+ mieqProcessInputEvents();
+#endif
+}
+
+static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput,
+ DMXUpdateType type,
+ WindowPtr pWindow)
+{
+ int i;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension && pWindow && pWindow->parent != WindowTable[0])
+ return;
+#endif
+#if DMX_WINDOW_DEBUG
+ {
+ const char *name = "Unknown";
+ switch (type) {
+ case DMX_UPDATE_REALIZE: name = "Realize"; break;
+ case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break;
+ case DMX_UPDATE_RESTACK: name = "Restack"; break;
+ case DMX_UPDATE_COPY: name = "Copy"; break;
+ case DMX_UPDATE_RESIZE: name = "Resize"; break;
+ case DMX_UPDATE_REPARENT: name = "Repaint"; break;
+ }
+ dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name);
+ }
+#endif
+
+ if (dmxInput->detached)
+ return;
+ for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->update_info)
+ dmxInput->devs[i]->update_info(dmxInput->devs[i]->private,
+ type, pWindow);
+}
+
+static void dmxCollectAll(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ if (dmxInput->detached)
+ return;
+ for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->collect_events)
+ dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public,
+ dmxMotion,
+ dmxEnqueue,
+ dmxCheckSpecialKeys, DMX_BLOCK);
+}
+
+static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout,
+ pointer pReadMask)
+{
+ DMXInputInfo *dmxInput = &dmxInputs[(int)blockData];
+ static unsigned long generation = 0;
+
+ if (generation != serverGeneration) {
+ generation = serverGeneration;
+ dmxCollectAll(dmxInput);
+ }
+}
+
+static void dmxSwitchReturn(pointer p)
+{
+ DMXInputInfo *dmxInput = p;
+ int i;
+
+ dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched);
+
+ if (!dmxInput->vt_switched)
+ dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n");
+ dmxSigioEnableInput();
+ for (i = 0; i < dmxInput->numDevs; i++)
+ if (dmxInput->devs[i]->vt_post_switch)
+ dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private);
+ dmxInput->vt_switched = 0;
+}
+
+static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask)
+{
+ DMXInputInfo *dmxInput = &dmxInputs[(int)blockData];
+ int i;
+
+ if (dmxInput->vt_switch_pending) {
+ dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending);
+ for (i = 0; i < dmxInput->numDevs; i++)
+ if (dmxInput->devs[i]->vt_pre_switch)
+ dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private);
+ dmxInput->vt_switched = dmxInput->vt_switch_pending;
+ dmxInput->vt_switch_pending = 0;
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ if (dmxInput->devs[i]->vt_switch) {
+ dmxSigioDisableInput();
+ if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private,
+ dmxInput->vt_switched,
+ dmxSwitchReturn,
+ dmxInput))
+ dmxSwitchReturn(dmxInput);
+ break; /* Only call one vt_switch routine */
+ }
+ }
+ }
+ dmxCollectAll(dmxInput);
+}
+
+static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal)
+{
+ static int k = 0;
+ static int m = 0;
+ static int o = 0;
+ static unsigned long dmxGeneration = 0;
+#define LEN 32
+ char * buf = malloc(LEN);
+
+ if (dmxGeneration != serverGeneration) {
+ k = m = o = 0;
+ dmxGeneration = serverGeneration;
+ }
+
+ switch (dmxLocal->type) {
+ case DMX_LOCAL_KEYBOARD: XmuSnprintf(buf, LEN, "Keyboard%d", k++); break;
+ case DMX_LOCAL_MOUSE: XmuSnprintf(buf, LEN, "Mouse%d", m++); break;
+ default: XmuSnprintf(buf, LEN, "Other%d", o++); break;
+ }
+
+ return buf;
+}
+
+static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)
+{
+ DeviceIntPtr pDevice;
+ Atom atom;
+ const char *name = NULL;
+ void (*registerProcPtr)(DeviceIntPtr) = NULL;
+ char *devname;
+ DMXInputInfo *dmxInput;
+
+ if (!dmxLocal)
+ return NULL;
+ dmxInput = &dmxInputs[dmxLocal->inputIdx];
+
+ if (dmxLocal->sendsCore) {
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) {
+ dmxLocal->isCore = 1;
+ dmxLocalCoreKeyboard = dmxLocal;
+ name = "keyboard";
+ registerProcPtr = RegisterKeyboardDevice;
+ }
+ if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) {
+ dmxLocal->isCore = 1;
+ dmxLocalCorePointer = dmxLocal;
+ name = "pointer";
+ registerProcPtr = RegisterPointerDevice;
+ }
+ }
+
+ if (!name) {
+ name = "extension";
+ registerProcPtr = RegisterOtherDevice;
+ }
+
+ if (!name || !registerProcPtr)
+ dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name);
+
+ pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE);
+ if (!pDevice) {
+ dmxLog(dmxError, "Too many devices -- cannot add device %s\n",
+ dmxLocal->name);
+ return NULL;
+ }
+ pDevice->public.devicePrivate = dmxLocal;
+ dmxLocal->pDevice = pDevice;
+
+ devname = dmxMakeUniqueDeviceName(dmxLocal);
+ atom = MakeAtom((char *)devname, strlen(devname), TRUE);
+ pDevice->type = atom;
+ pDevice->name = devname;
+
+ registerProcPtr(pDevice);
+
+ if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) {
+#if 00 /*BP*/
+ miRegisterPointerDevice(screenInfo.screens[0], pDevice);
+#else
+ /* Nothing? dmxDeviceOnOff() should get called to init, right? */
+#endif
+ }
+
+ if (dmxLocal->create_private)
+ dmxLocal->private = dmxLocal->create_private(pDevice);
+
+ dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n",
+ dmxLocal->name, name, devname,
+ dmxLocal->isCore
+ ? " [core]"
+ : (dmxLocal->sendsCore
+ ? " [sends core events]"
+ : ""));
+
+ return pDevice;
+}
+
+static DMXLocalInputInfoPtr dmxLookupLocal(const char *name)
+{
+ DMXLocalInputInfoPtr pt;
+
+ for (pt = &DMXLocalDevices[0]; pt->name; ++pt)
+ if (!strcmp(pt->name, name)) return pt; /* search for device name */
+ return NULL;
+}
+
+/** Copy the local input information from \a s into a new \a devs slot
+ * in \a dmxInput. */
+DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput,
+ DMXLocalInputInfoPtr s)
+{
+ DMXLocalInputInfoPtr dmxLocal = malloc(sizeof(*dmxLocal));
+
+ if (!dmxLocal)
+ dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n");
+
+ memcpy(dmxLocal, s, sizeof(*dmxLocal));
+ dmxLocal->inputIdx = dmxInput->inputIdx;
+ dmxLocal->sendsCore = dmxInput->core;
+ dmxLocal->savedSendsCore = dmxInput->core;
+ dmxLocal->deviceId = -1;
+
+ ++dmxInput->numDevs;
+ dmxInput->devs = realloc(dmxInput->devs,
+ dmxInput->numDevs * sizeof(*dmxInput->devs));
+ dmxInput->devs[dmxInput->numDevs-1] = dmxLocal;
+
+ return dmxLocal;
+}
+
+static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a)
+{
+ int i;
+ int help = 0;
+ DMXLocalInputInfoRec *pt;
+
+ for (i = 1; i < dmxArgC(a); i++) {
+ const char *name = dmxArgV(a, i);
+ if ((pt = dmxLookupLocal(name))) {
+ dmxInputCopyLocal(dmxInput, pt);
+ } else {
+ if (strlen(name))
+ dmxLog(dmxWarning,
+ "Could not find a driver called %s\n", name);
+ ++help;
+ }
+ }
+ if (help) {
+ dmxLog(dmxInfo, "Available local device drivers:\n");
+ for (pt = &DMXLocalDevices[0]; pt->name; ++pt) {
+ const char *type;
+ switch (pt->type) {
+ case DMX_LOCAL_KEYBOARD: type = "keyboard"; break;
+ case DMX_LOCAL_MOUSE: type = "pointer"; break;
+ default: type = "unknown"; break;
+ }
+ dmxLog(dmxInfo, " %s (%s)\n", pt->name, type);
+ }
+ dmxLog(dmxFatal, "Must have valid local device driver\n");
+ }
+}
+
+int dmxInputExtensionErrorHandler(Display *dsp, char *name, char *reason)
+{
+ return 0;
+}
+
+static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI)
+{
+ XExtensionVersion *ext;
+ XDeviceInfo *devices;
+ Display *display;
+ int num;
+ int i, j;
+ DMXLocalInputInfoPtr dmxLocal;
+ int (*handler)(Display *, char *, char *);
+
+ if (!(display = XOpenDisplay(dmxInput->name))) return;
+
+ /* Print out information about the XInput Extension. */
+ handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler);
+ ext = XGetExtensionVersion(display, INAME);
+ XSetExtensionErrorHandler(handler);
+
+ if (!ext || ext == (XExtensionVersion *)NoSuchExtension) {
+ dmxLogInput(dmxInput, "%s is not available\n", INAME);
+ } else {
+ dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n",
+ dmxInput->name, INAME,
+ ext->major_version, ext->minor_version);
+ devices = XListInputDevices(display, &num);
+
+ XFree(ext);
+ ext = NULL;
+
+ /* Print a list of all devices */
+ for (i = 0; i < num; i++) {
+ const char *use = "Unknown";
+ switch (devices[i].use) {
+ case IsXPointer: use = "XPointer"; break;
+ case IsXKeyboard: use = "XKeyboard"; break;
+ case IsXExtensionDevice: use = "XExtensionDevice"; break;
+ case IsXExtensionPointer: use = "XExtensionPointer"; break;
+ case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break;
+ }
+ dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n",
+ devices[i].id,
+ devices[i].name ? devices[i].name : "",
+ use);
+ }
+
+ /* Search for extensions */
+ for (i = 0; i < num; i++) {
+ switch (devices[i].use) {
+ case IsXKeyboard:
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
+ if (dmxL->type == DMX_LOCAL_KEYBOARD
+ && dmxL->deviceId < 0) {
+ dmxL->deviceId = devices[i].id;
+ dmxL->deviceName = (devices[i].name
+ ? xstrdup(devices[i].name)
+ : NULL);
+ }
+ }
+ break;
+ case IsXPointer:
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
+ if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) {
+ dmxL->deviceId = devices[i].id;
+ dmxL->deviceName = (devices[i].name
+ ? xstrdup(devices[i].name)
+ : NULL);
+ }
+ }
+ break;
+#if 0
+ case IsXExtensionDevice:
+ case IsXExtensionKeyboard:
+ case IsXExtensionPointer:
+ if (doXI) {
+ if (!dmxInput->numDevs) {
+ dmxLog(dmxWarning,
+ "Cannot use remote (%s) XInput devices if"
+ " not also using core devices\n",
+ dmxInput->name);
+ } else {
+ dmxLocal = dmxInputCopyLocal(dmxInput,
+ &DMXCommonOth);
+ dmxLocal->isCore = FALSE;
+ dmxLocal->sendsCore = FALSE;
+ dmxLocal->deviceId = devices[i].id;
+ dmxLocal->deviceName = (devices[i].name
+ ? xstrdup(devices[i].name)
+ : NULL);
+ }
+ }
+ break;
+#endif
+ }
+ }
+ XFreeDeviceList(devices);
+ }
+ XCloseDisplay(display);
+}
+
+/** Re-initialize all the devices described in \a dmxInput. Called from
+ #dmxAdjustCursorBoundaries before the cursor is redisplayed. */
+void dmxInputReInit(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ if (dmxLocal->reinit)
+ dmxLocal->reinit(&dmxLocal->pDevice->public);
+ }
+}
+
+/** Re-initialize all the devices described in \a dmxInput. Called from
+ #dmxAdjustCursorBoundaries after the cursor is redisplayed. */
+void dmxInputLateReInit(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ if (dmxLocal->latereinit)
+ dmxLocal->latereinit(&dmxLocal->pDevice->public);
+ }
+}
+
+/** Initialize all of the devices described in \a dmxInput. */
+void dmxInputInit(DMXInputInfo *dmxInput)
+{
+ DeviceIntPtr pPointer = NULL, pKeyboard = NULL;
+ dmxArg a;
+ const char *name;
+ int i;
+ int doXI = 1; /* Include by default */
+ int forceConsole = 0;
+ int doWindows = 1; /* On by default */
+ int hasXkb = 0;
+
+ a = dmxArgParse(dmxInput->name);
+
+ for (i = 1; i < dmxArgC(a); i++) {
+ switch (hasXkb) {
+ case 1:
+ dmxInput->keycodes = xstrdup(dmxArgV(a, i));
+ ++hasXkb;
+ break;
+ case 2:
+ dmxInput->symbols = xstrdup(dmxArgV(a, i));
+ ++hasXkb;
+ break;
+ case 3:
+ dmxInput->geometry = xstrdup(dmxArgV(a, i));
+ hasXkb = 0;
+ break;
+ case 0:
+ if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0;
+ else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1;
+ else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1;
+ else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0;
+ else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1;
+ else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0;
+ else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1;
+ else {
+ dmxLog(dmxFatal,
+ "Unknown input argument: %s\n", dmxArgV(a, i));
+ }
+ }
+ }
+
+ name = dmxArgV(a, 0);
+
+ if (!strcmp(name, "local")) {
+ dmxPopulateLocal(dmxInput, a);
+ } else if (!strcmp(name, "dummy")) {
+ dmxInputCopyLocal(dmxInput, &DMXDummyMou);
+ dmxInputCopyLocal(dmxInput, &DMXDummyKbd);
+ dmxLogInput(dmxInput, "Using dummy input\n");
+ } else {
+ int found;
+
+ for (found = 0, i = 0; i < dmxNumScreens; i++) {
+ if (dmxPropertySameDisplay(&dmxScreens[i], name)) {
+ if (dmxScreens[i].shared)
+ dmxLog(dmxFatal,
+ "Cannot take input from shared backend (%s)\n",
+ name);
+ if (!dmxInput->core) {
+ dmxLog(dmxWarning,
+ "Cannot use core devices on a backend (%s)"
+ " as XInput devices\n", name);
+ } else {
+ char *pt;
+ for (pt = (char *)dmxInput->name; pt && *pt; pt++)
+ if (*pt == ',') *pt = '\0';
+ dmxInputCopyLocal(dmxInput, &DMXBackendMou);
+ dmxInputCopyLocal(dmxInput, &DMXBackendKbd);
+ dmxInput->scrnIdx = i;
+ dmxLogInput(dmxInput,
+ "Using backend input from %s\n", name);
+ }
+ ++found;
+ break;
+ }
+ }
+ if (!found || forceConsole) {
+ char *pt;
+ if (found) dmxInput->console = TRUE;
+ for (pt = (char *)dmxInput->name; pt && *pt; pt++)
+ if (*pt == ',') *pt = '\0';
+ dmxInputCopyLocal(dmxInput, &DMXConsoleMou);
+ dmxInputCopyLocal(dmxInput, &DMXConsoleKbd);
+ if (doWindows) {
+ dmxInput->windows = TRUE;
+ dmxInput->updateWindowInfo = dmxUpdateWindowInformation;
+ }
+ dmxLogInput(dmxInput,
+ "Using console input from %s (%s windows)\n",
+ name, doWindows ? "with" : "without");
+ }
+ }
+
+ dmxArgFree(a);
+
+ /* Locate extensions we may be interested in */
+ dmxInputScanForExtensions(dmxInput, doXI);
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ dmxLocal->pDevice = dmxAddDevice(dmxLocal);
+ if (dmxLocal->isCore) {
+ if (dmxLocal->type == DMX_LOCAL_MOUSE)
+ pPointer = dmxLocal->pDevice;
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD)
+ pKeyboard = dmxLocal->pDevice;
+ }
+ }
+
+ dmxInput->processInputEvents = dmxProcessInputEvents;
+ dmxInput->detached = False;
+
+ RegisterBlockAndWakeupHandlers(dmxBlockHandler,
+ dmxWakeupHandler,
+ (void *)dmxInput->inputIdx);
+}
+
+static void dmxInputFreeLocal(DMXLocalInputInfoRec *local)
+{
+ if (!local) return;
+ if (local->isCore && local->type == DMX_LOCAL_MOUSE)
+ dmxLocalCorePointer = NULL;
+ if (local->isCore && local->type == DMX_LOCAL_KEYBOARD)
+ dmxLocalCoreKeyboard = NULL;
+ if (local->destroy_private) local->destroy_private(local->private);
+ if (local->history) free(local->history);
+ if (local->valuators) free(local->valuators);
+ if (local->deviceName) free(local->deviceName);
+ local->private = NULL;
+ local->history = NULL;
+ local->deviceName = NULL;
+ free(local);
+}
+
+/** Free all of the memory associated with \a dmxInput */
+void dmxInputFree(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ if (!dmxInput) return;
+
+ if (dmxInput->keycodes) free(dmxInput->keycodes);
+ if (dmxInput->symbols) free(dmxInput->symbols);
+ if (dmxInput->geometry) free(dmxInput->geometry);
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ dmxInputFreeLocal(dmxInput->devs[i]);
+ dmxInput->devs[i] = NULL;
+ }
+ free(dmxInput->devs);
+ dmxInput->devs = NULL;
+ dmxInput->numDevs = 0;
+ if (dmxInput->freename) free(dmxInput->name);
+ dmxInput->name = NULL;
+}
+
+/** Log information about all of the known devices using #dmxLog(). */
+void dmxInputLogDevices(void)
+{
+ int i, j;
+
+ dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount());
+ dmxLog(dmxInfo, " Id Name Classes\n");
+ for (j = 0; j < dmxNumInputs; j++) {
+ DMXInputInfo *dmxInput = &dmxInputs[j];
+ const char *pt = strchr(dmxInput->name, ',');
+ int len = (pt
+ ? (size_t)(pt-dmxInput->name)
+ : strlen(dmxInput->name));
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice;
+ if (pDevice) {
+ dmxLog(dmxInfo, " %2d%c %-20.20s",
+ pDevice->id,
+ dmxInput->detached ? 'D' : ' ',
+ pDevice->name);
+ if (pDevice->key) dmxLogCont(dmxInfo, " key");
+ if (pDevice->valuator) dmxLogCont(dmxInfo, " val");
+ if (pDevice->button) dmxLogCont(dmxInfo, " btn");
+ if (pDevice->focus) dmxLogCont(dmxInfo, " foc");
+ if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd");
+ if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr");
+ if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int");
+ if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str");
+ if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel");
+ if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led");
+ if (!pDevice->key && !pDevice->valuator && !pDevice->button
+ && !pDevice->focus && !pDevice->kbdfeed
+ && !pDevice->ptrfeed && !pDevice->intfeed
+ && !pDevice->stringfeed && !pDevice->bell
+ && !pDevice->leds) dmxLogCont(dmxInfo, " (none)");
+
+ dmxLogCont(dmxInfo, "\t[i%d/%*.*s",
+ dmxInput->inputIdx, len, len, dmxInput->name);
+ if (dmxInput->devs[i]->deviceId >= 0)
+ dmxLogCont(dmxInfo, "/id%d", dmxInput->devs[i]->deviceId);
+ if (dmxInput->devs[i]->deviceName)
+ dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName);
+ dmxLogCont(dmxInfo, "] %s\n",
+ dmxInput->devs[i]->isCore
+ ? "core"
+ : (dmxInput->devs[i]->sendsCore
+ ? "extension (sends core events)"
+ : "extension"));
+ }
+ }
+ }
+}
+
+/** Detach an input */
+int dmxInputDetach(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ if (dmxInput->detached) return BadAccess;
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n",
+ dmxLocal->pDevice->id,
+ dmxLocal->pDevice->name,
+ dmxLocal->isCore
+ ? " [core]"
+ : (dmxLocal->sendsCore
+ ? " [sends core events]"
+ : ""));
+ DisableDevice(dmxLocal->pDevice, TRUE);
+ }
+ dmxInput->detached = True;
+ dmxInputLogDevices();
+ return 0;
+}
+
+/** Search for input associated with \a dmxScreen, and detach. */
+void dmxInputDetachAll(DMXScreenInfo *dmxScreen)
+{
+ int i;
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput);
+ }
+}
+
+/** Search for input associated with \a deviceId, and detach. */
+int dmxInputDetachId(int id)
+{
+ DMXInputInfo *dmxInput = dmxInputLocateId(id);
+
+ if (!dmxInput) return BadValue;
+
+ return dmxInputDetach(dmxInput);
+}
+
+DMXInputInfo *dmxInputLocateId(int id)
+{
+ int i, j;
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ if (dmxLocal->pDevice->id == id) return dmxInput;
+ }
+ }
+ return NULL;
+}
+
+static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id)
+{
+ dmxInputInit(dmxInput);
+ InitAndStartDevices();
+ if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id;
+ dmxInputLogDevices();
+ return 0;
+}
+
+static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id)
+{
+ int i;
+
+ dmxInput->detached = False;
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ if (id) *id = dmxLocal->pDevice->id;
+ dmxLogInput(dmxInput,
+ "Attaching device id %d: %s%s\n",
+ dmxLocal->pDevice->id,
+ dmxLocal->pDevice->name,
+ dmxLocal->isCore
+ ? " [core]"
+ : (dmxLocal->sendsCore
+ ? " [sends core events]"
+ : ""));
+ EnableDevice(dmxLocal->pDevice, TRUE);
+ }
+ dmxInputLogDevices();
+ return 0;
+}
+
+int dmxInputAttachConsole(const char *name, int isCore, int *id)
+{
+ DMXInputInfo *dmxInput;
+ int i;
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ if (dmxInput->scrnIdx == -1
+ && dmxInput->detached
+ && !strcmp(dmxInput->name, name)) {
+ /* Found match */
+ dmxLogInput(dmxInput, "Reattaching detached console input\n");
+ return dmxInputAttachOld(dmxInput, id);
+ }
+ }
+
+ /* No match found */
+ dmxInput = dmxConfigAddInput(xstrdup(name), isCore);
+ dmxInput->freename = TRUE;
+ dmxLogInput(dmxInput, "Attaching new console input\n");
+ return dmxInputAttachNew(dmxInput, id);
+}
+
+int dmxInputAttachBackend(int physicalScreen, int isCore, int *id)
+{
+ DMXInputInfo *dmxInput;
+ DMXScreenInfo *dmxScreen;
+ int i;
+
+ if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue;
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) {
+ /* Found match */
+ if (!dmxInput->detached) return BadAccess; /* Already attached */
+ dmxScreen = &dmxScreens[physicalScreen];
+ if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */
+ dmxLogInput(dmxInput, "Reattaching detached backend input\n");
+ return dmxInputAttachOld(dmxInput, id);
+ }
+ }
+ /* No match found */
+ dmxScreen = &dmxScreens[physicalScreen];
+ if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */
+ dmxInput = dmxConfigAddInput(dmxScreen->name, isCore);
+ dmxLogInput(dmxInput, "Attaching new backend input\n");
+ return dmxInputAttachNew(dmxInput, id);
+}
diff --git a/xorg-server/hw/dmx/input/dmxmotion.c b/xorg-server/hw/dmx/input/dmxmotion.c index 73580a215..d1c79f126 100644 --- a/xorg-server/hw/dmx/input/dmxmotion.c +++ b/xorg-server/hw/dmx/input/dmxmotion.c @@ -1,142 +1,142 @@ -/* - * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * Authors: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * This file provides functions similar to miPointerGetMotionEvents and - * miPointerPutMotionEvents, with the exception that devices with more - * than two axes are fully supported. These routines may be used only - * for motion buffers for extension devices, and are \a not compatible - * replacements for the mi routines. */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "inputstr.h" -#include "dmxinputinit.h" -#include "dmxcommon.h" -#include "dmxmotion.h" - -#define OFFSET(offset,element) ((offset) * (numAxes + 1) + (element)) - -/** Return size of motion buffer. \see DMX_MOTION_SIZE */ -int dmxPointerGetMotionBufferSize(void) -{ - return DMX_MOTION_SIZE; -} - -/** This routine performs the same function as \a miPointerGetMotionEvents: - * the events in the motion history that are between the start and stop - * times (in mS) are placed in the coords vector, and the count of the - * number of items so placed is returned. This routine is called from - * dix/devices.c so that coords can hold valuator->numMotionEvents - * events. This routine is called from \a Xi/gtmotion.c with coords large - * enough to hold the same number of events in a variable-length - * extended \a xTimecoord structure. This provides sufficient data for the - * \a XGetDeviceMotionEvents library call, and would be identical to - * \a miPointerGetMotionEvents for devices with only 2 axes (i.e., core - * pointers) if \a xTimecoord used 32bit integers. - * - * Because DMX uses the mi* routines for all core devices, this routine - * only has to support extension devices using the polymorphic coords. - * Because compatibility with miPointerGetMotionEvents is not possible, - * it is not provided. */ -int dmxPointerGetMotionEvents(DeviceIntPtr pDevice, - xTimecoord *coords, - unsigned long start, - unsigned long stop, - ScreenPtr pScreen) -{ - GETDMXLOCALFROMPDEVICE; - int numAxes = pDevice->valuator->numAxes; - unsigned long *c = (unsigned long *)coords; - int count = 0; - int i, j; - - if (!dmxLocal->history) return 0; - for (i = dmxLocal->head; i != dmxLocal->tail;) { - if (dmxLocal->history[OFFSET(i,0)] >= stop) break; - if (dmxLocal->history[OFFSET(i,0)] >= start) { - for (j = 0; j < numAxes + 1; j++) - c[OFFSET(count,j)] = dmxLocal->history[OFFSET(i,j)]; - ++count; - } - if (++i >= DMX_MOTION_SIZE) i = 0; - } - return count; -} - -/** This routine adds an event to the motion history. A similar - * function is performed by miPointerMove for the mi versions of these - * routines. */ -void dmxPointerPutMotionEvent(DeviceIntPtr pDevice, - int firstAxis, int axesCount, int *v, - unsigned long time) -{ - GETDMXLOCALFROMPDEVICE; - int numAxes = pDevice->valuator->numAxes; - int i; - - if (!dmxLocal->history) { - dmxLocal->history = xalloc(sizeof(*dmxLocal->history) - * (numAxes + 1) - * DMX_MOTION_SIZE); - dmxLocal->head = 0; - dmxLocal->tail = 0; - dmxLocal->valuators = calloc(sizeof(*dmxLocal->valuators), numAxes); - } else { - if (++dmxLocal->tail >= DMX_MOTION_SIZE) dmxLocal->tail = 0; - if (dmxLocal->head == dmxLocal->tail) - if (++dmxLocal->head >= DMX_MOTION_SIZE) dmxLocal->head = 0; - } - - dmxLocal->history[OFFSET(dmxLocal->tail,0)] = time; - - /* Initialize the data from the known - * values (if Absolute) or to zero (if - * Relative) */ - if (pDevice->valuator->mode == Absolute) { - for (i = 0; i < numAxes; i++) - dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] - = dmxLocal->valuators[i]; - } else { - for (i = 0; i < numAxes; i++) - dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0; - } - - for (i = firstAxis; i < axesCount; i++) { - dmxLocal->history[OFFSET(dmxLocal->tail,i+i)] - = (unsigned long)v[i-firstAxis]; - dmxLocal->valuators[i] = v[i-firstAxis]; - } -} +/*
+ * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides functions similar to miPointerGetMotionEvents and
+ * miPointerPutMotionEvents, with the exception that devices with more
+ * than two axes are fully supported. These routines may be used only
+ * for motion buffers for extension devices, and are \a not compatible
+ * replacements for the mi routines. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "inputstr.h"
+#include "dmxinputinit.h"
+#include "dmxcommon.h"
+#include "dmxmotion.h"
+
+#define OFFSET(offset,element) ((offset) * (numAxes + 1) + (element))
+
+/** Return size of motion buffer. \see DMX_MOTION_SIZE */
+int dmxPointerGetMotionBufferSize(void)
+{
+ return DMX_MOTION_SIZE;
+}
+
+/** This routine performs the same function as \a miPointerGetMotionEvents:
+ * the events in the motion history that are between the start and stop
+ * times (in mS) are placed in the coords vector, and the count of the
+ * number of items so placed is returned. This routine is called from
+ * dix/devices.c so that coords can hold valuator->numMotionEvents
+ * events. This routine is called from \a Xi/gtmotion.c with coords large
+ * enough to hold the same number of events in a variable-length
+ * extended \a xTimecoord structure. This provides sufficient data for the
+ * \a XGetDeviceMotionEvents library call, and would be identical to
+ * \a miPointerGetMotionEvents for devices with only 2 axes (i.e., core
+ * pointers) if \a xTimecoord used 32bit integers.
+ *
+ * Because DMX uses the mi* routines for all core devices, this routine
+ * only has to support extension devices using the polymorphic coords.
+ * Because compatibility with miPointerGetMotionEvents is not possible,
+ * it is not provided. */
+int dmxPointerGetMotionEvents(DeviceIntPtr pDevice,
+ xTimecoord *coords,
+ unsigned long start,
+ unsigned long stop,
+ ScreenPtr pScreen)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int numAxes = pDevice->valuator->numAxes;
+ unsigned long *c = (unsigned long *)coords;
+ int count = 0;
+ int i, j;
+
+ if (!dmxLocal->history) return 0;
+ for (i = dmxLocal->head; i != dmxLocal->tail;) {
+ if (dmxLocal->history[OFFSET(i,0)] >= stop) break;
+ if (dmxLocal->history[OFFSET(i,0)] >= start) {
+ for (j = 0; j < numAxes + 1; j++)
+ c[OFFSET(count,j)] = dmxLocal->history[OFFSET(i,j)];
+ ++count;
+ }
+ if (++i >= DMX_MOTION_SIZE) i = 0;
+ }
+ return count;
+}
+
+/** This routine adds an event to the motion history. A similar
+ * function is performed by miPointerMove for the mi versions of these
+ * routines. */
+void dmxPointerPutMotionEvent(DeviceIntPtr pDevice,
+ int firstAxis, int axesCount, int *v,
+ unsigned long time)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int numAxes = pDevice->valuator->numAxes;
+ int i;
+
+ if (!dmxLocal->history) {
+ dmxLocal->history = malloc(sizeof(*dmxLocal->history)
+ * (numAxes + 1)
+ * DMX_MOTION_SIZE);
+ dmxLocal->head = 0;
+ dmxLocal->tail = 0;
+ dmxLocal->valuators = calloc(sizeof(*dmxLocal->valuators), numAxes);
+ } else {
+ if (++dmxLocal->tail >= DMX_MOTION_SIZE) dmxLocal->tail = 0;
+ if (dmxLocal->head == dmxLocal->tail)
+ if (++dmxLocal->head >= DMX_MOTION_SIZE) dmxLocal->head = 0;
+ }
+
+ dmxLocal->history[OFFSET(dmxLocal->tail,0)] = time;
+
+ /* Initialize the data from the known
+ * values (if Absolute) or to zero (if
+ * Relative) */
+ if (pDevice->valuator->mode == Absolute) {
+ for (i = 0; i < numAxes; i++)
+ dmxLocal->history[OFFSET(dmxLocal->tail,i+1)]
+ = dmxLocal->valuators[i];
+ } else {
+ for (i = 0; i < numAxes; i++)
+ dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0;
+ }
+
+ for (i = firstAxis; i < axesCount; i++) {
+ dmxLocal->history[OFFSET(dmxLocal->tail,i+i)]
+ = (unsigned long)v[i-firstAxis];
+ dmxLocal->valuators[i] = v[i-firstAxis];
+ }
+}
diff --git a/xorg-server/hw/dmx/input/lnx-keyboard.c b/xorg-server/hw/dmx/input/lnx-keyboard.c index 939a32f07..11f21e25c 100644 --- a/xorg-server/hw/dmx/input/lnx-keyboard.c +++ b/xorg-server/hw/dmx/input/lnx-keyboard.c @@ -1,990 +1,990 @@ -/* Portions of this file were derived from the following files: - * - ********************************************************************** - * - * xfree86/common/{xf86Io.c,xf86Kbd.c,xf86Events.c} - * - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - * - * 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 Thomas Roell not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Thomas Roell makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THOMAS ROELL 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. - * - ********************************************************************** - * - * xfree86/common/xf86KbdLnx.c - * - * Linux version of keymapping setup. The kernel (since 0.99.14) has support - * for fully remapping the keyboard, but there are some differences between - * the Linux map and the SVR4 map (esp. in the extended keycodes). We also - * remove the restriction on what keycodes can be remapped. - * Orest Zborowski. - * - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - * - * 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 Thomas Roell not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Thomas Roell makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THOMAS ROELL 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. - * - ********************************************************************** - * - * xfree86/os-support/linux/lnx_io.c - * - * Copyright 1992 by Orest Zborowski <obz@Kodak.com> - * Copyright 1993 by David Dawes <dawes@xfree86.org> - * - * 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 names of Orest Zborowski and David Dawes - * not be used in advertising or publicity pertaining to distribution of - * the software without specific, written prior permission. Orest Zborowski - * and David Dawes make no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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. - * - */ - -/* - * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * Authors: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * - * This code implements a low-level device driver for the Linux - * keyboard. The code is derived from code by Thomas Roell, Orest - * Zborowski, and David Dawes (see the source code for complete - * references). */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -/*****************************************************************************/ -/* Define some macros to make it easier to move this file to another - * part of the Xserver tree. All calls to the dmx* layer are #defined - * here for the .c file. The .h file will also have to be edited. */ -#include "dmxinputinit.h" -#include "lnx-keyboard.h" - -#define GETPRIV myPrivate *priv \ - = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private - -#define LOG0(f) dmxLog(dmxDebug,f) -#define LOG1(f,a) dmxLog(dmxDebug,f,a) -#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) -#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) -#define FATAL0(f) dmxLog(dmxFatal,f) -#define FATAL1(f,a) dmxLog(dmxFatal,f,a) -#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) -#define MOTIONPROC dmxMotionProcPtr -#define ENQUEUEPROC dmxEnqueueProcPtr -#define CHECKPROC dmxCheckSpecialProcPtr -#define SWITCHRETPROC dmxVTSwitchReturnProcPtr -#define BLOCK DMXBlockType -#define MESSAGE "\033c\n\n\nDMX taking input from this console..." -#define FINALMESSAGE "\033cDMX terminated." - -/* End of interface definitions. */ -/*****************************************************************************/ - -#include "inputstr.h" -#include <X11/Xos.h> -#include <sys/ioctl.h> -#include <errno.h> -#include <signal.h> -#include <sys/vt.h> -#include <sys/kd.h> -#include <termios.h> -#include "atKeynames.h" -#if 00 -#include "xf86Keymap.h" -#endif -#include <linux/keyboard.h> -#include <xkbsrv.h> - -#define NUM_AT2LNX (sizeof(at2lnx) / sizeof(at2lnx[0])) -#define NUM_STATE_ENTRIES (256/32) - - -/* Private area for Linux-style keyboards. */ -typedef struct _myPrivate { - int fd; - int vtno; - int vtcurrent; - int kbdtrans; - struct termios kbdtty; - int kbdType; - CARD32 kbdState[NUM_STATE_ENTRIES]; - DeviceIntPtr pKeyboard; - unsigned char prefix; - - int switched; - SWITCHRETPROC switch_return; - void *switch_return_data; - - /* For bell */ - int pitch; - unsigned long duration; -} myPrivate; - -static myPrivate *PRIV = NULL; - -#undef SYSCALL -#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) - -static int kbdLinuxKeyDown(myPrivate *priv, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return 0; - return priv->kbdState[byte] & bit; -} - -static void kbdLinuxKeyState(myPrivate *priv, int type, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return; - if (type == KeyPress) priv->kbdState[byte] |= bit; - else priv->kbdState[byte] &= ~bit; -} - -static 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_BackSpace, - 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 -}; - -/* - * Maps the AT keycodes to Linux keycodes - */ -static unsigned char at2lnx[NUM_KEYCODES] = -{ - 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ - 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ - 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ - 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ - 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ - 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ - 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ - 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ - 0x11, /* KEY_W */ 0x12, /* KEY_E */ - 0x13, /* KEY_R */ 0x14, /* KEY_T */ - 0x15, /* KEY_Y */ 0x16, /* KEY_U */ - 0x17, /* KEY_I */ 0x18, /* KEY_O */ - 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ - 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ - 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ - 0x1f, /* KEY_S */ 0x20, /* KEY_D */ - 0x21, /* KEY_F */ 0x22, /* KEY_G */ - 0x23, /* KEY_H */ 0x24, /* KEY_J */ - 0x25, /* KEY_K */ 0x26, /* KEY_L */ - 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ - 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ - 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ - 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ - 0x2f, /* KEY_V */ 0x30, /* KEY_B */ - 0x31, /* KEY_N */ 0x32, /* KEY_M */ - 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ - 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ - 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ - 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ - 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ - 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ - 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ - 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ - 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ - 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ - 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ - 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ - 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ - 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ - 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ - 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ - 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ - 0x00, /* 0x55 */ 0x56, /* KEY_Less */ - 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ - 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ - 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ - 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ - 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ - 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ - 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ - 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ - 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ - 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ - 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ - 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ - 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ - 0x00, /* 0x71 */ 0x00, /* 0x72 */ - 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ - 0x00, /* 0x75 */ 0x00, /* 0x76 */ - 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ - 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ - 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ - 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ - 0x00, /* 0x7f */ -}; - -/** Create a private structure for use within this file. */ -pointer kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard) -{ - myPrivate *priv = calloc(1, sizeof(*priv)); - priv->fd = -1; - priv->pKeyboard = pKeyboard; - return priv; -} - -/** Destroy a private structure. */ -void kbdLinuxDestroyPrivate(pointer priv) -{ - if (priv) free(priv); -} - -/** Ring the bell. - * - * Note: we completely ignore the \a volume, since Linux's ioctl() - * interface does not provide a way to control it. If it did, the XBell - * manpage tells how the actual volume is a function of the percent and - * the (base) volume. - * - * Note that most of the other PC-based bell drivers compute the - * duration for KDMKTONE as a function of the volume and the duration. - * For some drivers, the duration is only measured in mS if the volume - * is 50, and is scaled by the volume for other values. This seems - * confusing and possibly incorrect (the xset man page says that the - * bell will be "as closely as it can to the user's specifications" -- - * if we ignore the volume and set the duration correctly, then we'll - * get one parameter "wrong" -- but if we use the volume to scale the - * duration, then we'll get both parameters "wrong"). */ -void kbdLinuxBell(DevicePtr pDev, int percent, - int volume, int pitch, int duration) -{ - GETPRIV; - - if (duration && pitch) { - ioctl(priv->fd, - KDMKTONE, - ((1193190 / pitch) & 0xffff) /* Low bits specify cycle time */ - | (duration << 16)); /* High bits are duration in msec */ - } -} - -/** Set the LEDs. */ -void kbdLinuxCtrl(DevicePtr pDev, KeybdCtrl *ctrl) -{ - GETPRIV; - - ioctl(priv->fd, KDSETLED, ctrl->leds & 0x07); -} - -static int kbdLinuxGetFreeVTNumber(void) -{ - int fd = -1; - int vtno; - int i; - const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; - - for (i = 0; tty0[i]; i++) - if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break; - if (fd < 0) - FATAL1("kbdLinuxGetFreeVTNumber: Cannot open tty0 (%s)\n", - strerror(errno)); - if (ioctl(fd, VT_OPENQRY, &vtno) < 0 || vtno < 0) - FATAL0("kbdLinuxGetFreeVTNumber: Cannot find a free VT\n"); - return vtno; -} - -static int kbdLinuxOpenVT(int vtno) -{ - int fd = -1; - int i; - const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; - char name[64]; /* RATS: Only used in XmuSnprintf */ - - for (i = 0; vcs[i]; i++) { - XmuSnprintf(name, sizeof(name), vcs[i], vtno); - if ((fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) break; - } - if (fd < 0) - FATAL2("kbdLinuxOpenVT: Cannot open VT %d (%s)\n", - vtno, strerror(errno)); - return fd; -} - -static int kbdLinuxGetCurrentVTNumber(int fd) -{ - struct vt_stat vts; - - if (!ioctl(fd, VT_GETSTATE, &vts)) return vts.v_active; - return -1; -} - -static int kbdLinuxActivate(int fd, int vtno, int setSig); - -/** Currently unused hook called prior to an VT switch. */ -void kbdLinuxVTPreSwitch(pointer p) -{ -} - -/** Currently unused hook called after returning from a VT switch. */ -void kbdLinuxVTPostSwitch(pointer p) -{ -} - -/** Tell the operating system to switch to \a vt. The \a switch_return - * function is called with the \a switch_return_data when the VT is - * switched back to the pre-switch VT (i.e., the user returns to the DMX - * session). */ -int kbdLinuxVTSwitch(pointer p, int vt, - void (*switch_return)(pointer), - pointer switch_return_data) -{ - myPrivate *priv = p; - - if (priv->switched) FATAL0("kbdLinuxVTSwitch: already switched...\n"); - if (priv->vtno == vt) return 0; - - PRIV = priv; - priv->switched = 0; /* Will switch to 1 in handler */ - priv->switch_return = switch_return; - priv->switch_return_data = switch_return_data; - kbdLinuxActivate(priv->fd, vt, 0); - return 1; -} - -/* RATS: This function is only ever used to handle SIGUSR1. */ -static void kbdLinuxVTSignalHandler(int sig) -{ - myPrivate *priv = PRIV; - - signal(sig, kbdLinuxVTSignalHandler); - if (priv) { - ioctl(priv->fd, VT_RELDISP, VT_ACKACQ); - priv->switched = !priv->switched; - LOG2("kbdLinuxVTSignalHandler: got signal %d, switched = %d\n", - sig, priv->switched); - if (!priv->switched && priv->switch_return) - priv->switch_return(priv->switch_return_data); - } -} - -static int kbdLinuxActivate(int fd, int vtno, int setSig) -{ - int result; - struct vt_mode VT; - - SYSCALL(result = ioctl(fd, VT_ACTIVATE, vtno)); - if (result) FATAL0("kbdLinuxActivate: VT_ACTIVATE failed\n"); - SYSCALL(result = ioctl(fd, VT_WAITACTIVE, vtno)); - if (result) FATAL0("kbdLinuxActivate: VT_WAITACTIVE failed\n"); - if (setSig) { - SYSCALL(result = ioctl(fd, VT_GETMODE, &VT)); - if (result < 0) FATAL0("kbdLinuxActivate: VT_GETMODE failed\n"); - VT.mode = VT_PROCESS; - VT.relsig = SIGUSR1; - VT.acqsig = SIGUSR1; - if (ioctl(fd, VT_SETMODE, &VT)) - FATAL0("kbdLinuxActivate: VT_SETMODE VT_PROCESS failed\n"); - signal(SIGUSR1, kbdLinuxVTSignalHandler); - } - return Success; -} - -static void kbdLinuxOpenConsole(DevicePtr pDev) -{ - GETPRIV; - const char *msg = MESSAGE; - - if (priv->fd >= 0) return; - priv->vtno = kbdLinuxGetFreeVTNumber(); - priv->fd = kbdLinuxOpenVT(priv->vtno); - priv->vtcurrent = kbdLinuxGetCurrentVTNumber(priv->fd); - LOG2("kbdLinuxOpenConsole: current VT %d; using free VT %d\n", - priv->vtcurrent, priv->vtno); - kbdLinuxActivate(priv->fd, priv->vtno, 1); - ioctl(priv->fd, KDSETMODE, KD_GRAPHICS); /* To turn off gpm */ - if (msg) write(priv->fd, msg, strlen(msg)); -} - -static void kbdLinuxCloseConsole(DevicePtr pDev) -{ - GETPRIV; - struct vt_mode VT; - const char *msg = FINALMESSAGE; - - if (priv->fd < 0) return; - - ioctl(priv->fd, KDSETMODE, KD_TEXT); - if (msg) write(priv->fd, msg, strlen(msg)); - if (ioctl(priv->fd, VT_GETMODE, &VT) != -1) { - VT.mode = VT_AUTO; - ioctl(priv->fd, VT_SETMODE, &VT); - } - - LOG1("kbdLinuxCloseConsole: switching to VT %d\n", priv->vtcurrent); - if (priv->vtcurrent >= 0) kbdLinuxActivate(priv->fd, priv->vtcurrent, 0); - - close(priv->fd); - priv->fd = -1; -} - -/** Initialize the \a pDev as a Linux keyboard. */ -void kbdLinuxInit(DevicePtr pDev) -{ - GETPRIV; - - if (priv->fd <= 0) kbdLinuxOpenConsole(pDev); - - ioctl(priv->fd, KDGKBMODE, &priv->kbdtrans); - if (tcgetattr(priv->fd, &priv->kbdtty) < 0) - FATAL1("kbdLinuxInit: tcgetattr failed (%s)\n", strerror(errno)); -} - -static int kbdLinuxPrefix0Mapping(unsigned char *scanCode) -{ - /* Table from xfree86/common/xf86Events.c */ - switch (*scanCode) { - case KEY_KP_7: *scanCode = KEY_Home; break; /* curs home */ - case KEY_KP_8: *scanCode = KEY_Up; break; /* curs up */ - case KEY_KP_9: *scanCode = KEY_PgUp; break; /* curs pgup */ - case KEY_KP_4: *scanCode = KEY_Left; break; /* curs left */ - case KEY_KP_5: *scanCode = KEY_Begin; break; /* curs begin */ - case KEY_KP_6: *scanCode = KEY_Right; break; /* curs right */ - case KEY_KP_1: *scanCode = KEY_End; break; /* curs end */ - case KEY_KP_2: *scanCode = KEY_Down; break; /* curs down */ - case KEY_KP_3: *scanCode = KEY_PgDown; break; /* curs pgdown */ - case KEY_KP_0: *scanCode = KEY_Insert; break; /* curs insert */ - case KEY_KP_Decimal: *scanCode = KEY_Delete; break; /* curs delete */ - case KEY_Enter: *scanCode = KEY_KP_Enter; break; /* keypad enter */ - case KEY_LCtrl: *scanCode = KEY_RCtrl; break; /* right ctrl */ - case KEY_KP_Multiply: *scanCode = KEY_Print; break; /* print */ - case KEY_Slash: *scanCode = KEY_KP_Divide; break; /* keyp divide */ - case KEY_Alt: *scanCode = KEY_AltLang; break; /* right alt */ - case KEY_ScrollLock: *scanCode = KEY_Break; break; /* curs break */ - case 0x5b: *scanCode = KEY_LMeta; break; - case 0x5c: *scanCode = KEY_RMeta; break; - case 0x5d: *scanCode = KEY_Menu; break; - case KEY_F3: *scanCode = KEY_F13; break; - case KEY_F4: *scanCode = KEY_F14; break; - case KEY_F5: *scanCode = KEY_F15; break; - case KEY_F6: *scanCode = KEY_F16; break; - case KEY_F7: *scanCode = KEY_F17; break; - case KEY_KP_Plus: *scanCode = KEY_KP_DEC; break; - /* - * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) - */ - case 0x2A: - case 0x36: - return 1; - default: - /* - * "Internet" keyboards are generating lots of new codes. - * Let them pass. There is little consistency between them, - * so don't bother with symbolic names at this level. - */ - scanCode += 0x78; - } - return 0; -} - -static int kbdLinuxPrefixMapping(myPrivate *priv, unsigned char *scanCode) -{ - int pressed = *scanCode & 0x80; - unsigned char code = *scanCode & 0x7f; - - /* If we don't have a prefix, check for one */ - if (!priv->prefix) { - switch (code) { - case KEY_Prefix0: - case KEY_Prefix1: - priv->prefix = code; - return 1; - } - return 0; /* No change */ - } - - /* We have a prefix from the last scanCode */ - switch (priv->prefix) { - case KEY_Prefix0: - priv->prefix = 0; - if (kbdLinuxPrefix0Mapping(&code)) return 1; /* Skip sequence */ - break; - case KEY_Prefix1: - priv->prefix = (code = KEY_LCtrl) ? KEY_LCtrl : 0; - return 1; /* Use new prefix */ - case KEY_LCtrl: - priv->prefix = 0; - if (code != KEY_NumLock) return 1; /* Skip sequence*/ - code = KEY_Pause; - break; - } - - *scanCode = code | (pressed ? 0x80 : 0x00); - return 0; /* Use old scanCode */ -} - -static void kbdLinuxConvert(DevicePtr pDev, - unsigned char scanCode, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; - int type; - KeySym keySym = NoSymbol; - int keyCode; - int switching; - - /* Do special PC/AT prefix mapping -- may change scanCode! */ - if (kbdLinuxPrefixMapping(priv, &scanCode)) return; - - type = (scanCode & 0x80) ? KeyRelease : KeyPress; - keyCode = (scanCode & 0x7f) + MIN_KEYCODE; - - /* Handle repeats */ - - if (keyCode >= xkbi->desc->min_key_code && - keyCode <= xkbi->desc->max_key_code) { - - int effectiveGroup = XkbGetEffectiveGroup(xkbi, - &xkbi->state, - scanCode); - keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); -#if 0 - switch (keySym) { - case XK_Num_Lock: - case XK_Scroll_Lock: - case XK_Shift_Lock: - case XK_Caps_Lock: - /* Ignore releases and all but first press */ - if (kbdLinuxModIgnore(priv, &xE, keySym)) return; - if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; - else xE.u.u.type = KeyPress; - break; - } -#endif - - /* If key is already down, ignore or autorepeat */ - if (type == KeyPress && kbdLinuxKeyDown(priv, keyCode)) { - KbdFeedbackClassRec *feed = priv->pKeyboard->kbdfeed; - - /* No auto-repeat? */ - if ((feed && !feed->ctrl.autoRepeat) - || priv->pKeyboard->key->xkbInfo->desc->map->modmap[keyCode] - || (feed - && !(feed->ctrl.autoRepeats[keyCode >> 3] - & (1 << (keyCode & 7))))) return; /* Ignore */ - - /* Do auto-repeat */ - enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); - type = KeyPress; - } - - /* If key is already up, ignore */ - if (type == KeyRelease && !kbdLinuxKeyDown(priv, keyCode)) return; - } - - switching = 0; - if (checkspecial && type == KeyPress) - switching = checkspecial(pDev, keySym); - if (!switching) { - if (enqueue) - enqueue(pDev, type, keyCode, keySym, NULL, block); - kbdLinuxKeyState(priv, type, keyCode); /* Update our state bitmap */ - } -} - -/** Read an event from the \a pDev device. If the event is a motion - * event, enqueue it with the \a motion function. Otherwise, check for - * special keys with the \a checkspecial function and enqueue the event - * with the \a enqueue function. The \a block type is passed to the - * functions so that they may block SIGIO handling as appropriate to the - * caller of this function. */ -void kbdLinuxRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - unsigned char buf[256]; /* RATS: Only used in length-limited call */ - unsigned char *pt; - int n; - - while ((n = read(priv->fd, buf, sizeof(buf))) > 0) - for (pt = buf; n; --n, ++pt) - kbdLinuxConvert(pDev, *pt, enqueue, checkspecial, block); -} - -/** Turn \a pDev on (i.e., take input from \a pDev). */ -int kbdLinuxOn(DevicePtr pDev) -{ - GETPRIV; - struct termios nTty; - - ioctl(priv->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, B9600); - cfsetospeed(&nTty, B9600); - if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0) - FATAL1("kbdLinuxOn: tcsetattr failed (%s)\n", strerror(errno)); - return priv->fd; -} - -/** Turn \a pDev off (i.e., stop taking input from \a pDev). */ -void kbdLinuxOff(DevicePtr pDev) -{ - GETPRIV; - - ioctl(priv->fd, KDSKBMODE, priv->kbdtrans); - tcsetattr(priv->fd, TCSANOW, &priv->kbdtty); - kbdLinuxCloseConsole(pDev); -} - - -static void kbdLinuxReadKernelMapping(int fd, KeySymsPtr pKeySyms) -{ - KeySym *k; - int i; - int maxkey; - static unsigned char tbl[GLYPHS_PER_KEY] = { /* RATS: Use ok */ - 0, /* unshifted */ - 1, /* shifted */ - 0, /* modeswitch unshifted */ - 0 /* modeswitch shifted */ - }; - - /* - * Read the mapping from the kernel. - * Since we're still using the XFree86 scancode->AT keycode mapping - * routines, we need to convert the AT keycodes to Linux keycodes, - * then translate the Linux keysyms into X keysyms. - * - * First, figure out which tables to use for the modeswitch columns - * above, from the XF86Config fields. - */ - tbl[2] = 8; /* alt */ - tbl[3] = tbl[2] | 1; - -#if 00/*BP*/ - k = map+GLYPHS_PER_KEY; -#else - ErrorF("kbdLinuxReadKernelMapping() is broken/no-op'd\n"); - return; -#endif - maxkey = NUM_AT2LNX; - - for (i = 0; i < maxkey; ++i) { - struct kbentry kbe; - int j; - - kbe.kb_index = at2lnx[i]; - - for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) { - unsigned short kval; - - *k = NoSymbol; - - kbe.kb_table = tbl[j]; - if (kbe.kb_index == 0 || ioctl(fd, KDGKBENT, &kbe)) continue; - - kval = KVAL(kbe.kb_value); - switch (KTYP(kbe.kb_value)) { - case KT_LATIN: - case KT_LETTER: *k = linux_to_x[kval]; break; - case KT_FN: - if (kval <= 19) *k = XK_F1 + kval; - else switch (kbe.kb_value) { - case K_FIND: *k = XK_Home; /* or XK_Find */ break; - case K_INSERT: *k = XK_Insert; break; - case K_REMOVE: *k = XK_Delete; break; - case K_SELECT: *k = XK_End; /* or XK_Select */ break; - case K_PGUP: *k = XK_Prior; break; - case K_PGDN: *k = XK_Next; break; - case K_HELP: *k = XK_Help; break; - case K_DO: *k = XK_Execute; break; - case K_PAUSE: *k = XK_Pause; break; - case K_MACRO: *k = XK_Menu; break; - default: break; - } - break; - case KT_SPEC: - switch (kbe.kb_value) { - case K_ENTER: *k = XK_Return; break; - case K_BREAK: *k = XK_Break; break; - case K_CAPS: *k = XK_Caps_Lock; break; - case K_NUM: *k = XK_Num_Lock; break; - case K_HOLD: *k = XK_Scroll_Lock; break; - case K_COMPOSE: *k = XK_Multi_key; break; - default: break; - } - break; - case KT_PAD: - switch (kbe.kb_value) { - case K_PPLUS: *k = XK_KP_Add; break; - case K_PMINUS: *k = XK_KP_Subtract; break; - case K_PSTAR: *k = XK_KP_Multiply; break; - case K_PSLASH: *k = XK_KP_Divide; break; - case K_PENTER: *k = XK_KP_Enter; break; - case K_PCOMMA: *k = XK_KP_Separator; break; - case K_PDOT: *k = XK_KP_Decimal; break; - case K_PPLUSMINUS: *k = XK_KP_Subtract; break; - default: if (kval <= 9) *k = XK_KP_0 + kval; break; - } - break; - case KT_DEAD: - /* KT_DEAD keys are for accelerated diacritical creation. */ - switch (kbe.kb_value) { - case K_DGRAVE: *k = XK_dead_grave; break; - case K_DACUTE: *k = XK_dead_acute; break; - case K_DCIRCM: *k = XK_dead_circumflex; break; - case K_DTILDE: *k = XK_dead_tilde; break; - case K_DDIERE: *k = XK_dead_diaeresis; break; - } - break; - case KT_CUR: - switch (kbe.kb_value) { - case K_DOWN: *k = XK_Down; break; - case K_LEFT: *k = XK_Left; break; - case K_RIGHT: *k = XK_Right; break; - case K_UP: *k = XK_Up; break; - } - break; - case KT_SHIFT: - switch (kbe.kb_value) { - case K_ALTGR: *k = XK_Alt_R; break; - case K_ALT: - *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L); - break; - case K_CTRL: - *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L); - break; - case K_CTRLL: *k = XK_Control_L; break; - case K_CTRLR: *k = XK_Control_R; break; - case K_SHIFT: - *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L); - break; - case K_SHIFTL: *k = XK_Shift_L; break; - case K_SHIFTR: *k = XK_Shift_R; break; - default: break; - } - break; - case KT_ASCII: - /* KT_ASCII keys accumulate a 3 digit decimal number that - * gets emitted when the shift state changes. We can't - * emulate that. - */ - break; - case KT_LOCK: - if (kbe.kb_value == K_SHIFTLOCK) *k = XK_Shift_Lock; - break; - default: break; - } - } - - if (k[-1] == k[-2]) k[-1] = NoSymbol; - if (k[-2] == k[-3]) k[-2] = NoSymbol; - if (k[-3] == k[-4]) k[-3] = NoSymbol; - if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol; - if (k[-1] == k[-4] && k[-2] == k[-3] - && k[-2] == NoSymbol) k[-1] = NoSymbol; - } -} - -static void kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) -{ - GETPRIV; - KeySym *k, *mapCopy; - char type; - int i; - -#if 00/*BP*/ - mapCopy = xalloc(sizeof(map)); - memcpy(mapCopy, map, sizeof(map)); -#else - ErrorF("kbdLinuxGetMap() is broken/no-op'd\n"); - return; -#endif - - kbdLinuxReadKernelMapping(priv->fd, pKeySyms); - - /* compute the modifier map */ - for (i = 0; i < MAP_LENGTH; i++) - pModMap[i] = NoSymbol; /* make sure it is restored */ - - for (k = mapCopy, i = MIN_KEYCODE; - i < NUM_KEYCODES + MIN_KEYCODE; - i++, k += 4) { - switch(*k) { - case XK_Shift_L: - case XK_Shift_R: pModMap[i] = ShiftMask; break; - case XK_Control_L: - case XK_Control_R: pModMap[i] = ControlMask; break; - case XK_Caps_Lock: pModMap[i] = LockMask; break; - case XK_Alt_L: - case XK_Alt_R: pModMap[i] = AltMask; break; - case XK_Num_Lock: pModMap[i] = NumLockMask; break; - case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; - case XK_Kana_Lock: - case XK_Kana_Shift: pModMap[i] = KanaMask; break; - case XK_Mode_switch: pModMap[i] = AltLangMask; break; - } - } - - priv->kbdType = (ioctl(priv->fd, KDGKBTYPE, &type) < 0) ? KB_101 : type; - - pKeySyms->map = mapCopy; /* Must be XFree'able */ - pKeySyms->mapWidth = GLYPHS_PER_KEY; - pKeySyms->minKeyCode = MIN_KEYCODE; - pKeySyms->maxKeyCode = MAX_KEYCODE; -} - -/** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void kbdLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) -{ - info->keyboard = 1; - info->keyClass = 1; - kbdLinuxGetMap(pDev, &info->keySyms, info->modMap); - info->focusClass = 1; - info->kbdFeedbackClass = 1; -} +/* Portions of this file were derived from the following files:
+ *
+ **********************************************************************
+ *
+ * xfree86/common/{xf86Io.c,xf86Kbd.c,xf86Events.c}
+ *
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ *
+ * 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 Thomas Roell not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Thomas Roell makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THOMAS ROELL 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.
+ *
+ **********************************************************************
+ *
+ * xfree86/common/xf86KbdLnx.c
+ *
+ * Linux version of keymapping setup. The kernel (since 0.99.14) has support
+ * for fully remapping the keyboard, but there are some differences between
+ * the Linux map and the SVR4 map (esp. in the extended keycodes). We also
+ * remove the restriction on what keycodes can be remapped.
+ * Orest Zborowski.
+ *
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ *
+ * 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 Thomas Roell not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Thomas Roell makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THOMAS ROELL 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.
+ *
+ **********************************************************************
+ *
+ * xfree86/os-support/linux/lnx_io.c
+ *
+ * Copyright 1992 by Orest Zborowski <obz@Kodak.com>
+ * Copyright 1993 by David Dawes <dawes@xfree86.org>
+ *
+ * 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 names of Orest Zborowski and David Dawes
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission. Orest Zborowski
+ * and David Dawes make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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.
+ *
+ */
+
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * This code implements a low-level device driver for the Linux
+ * keyboard. The code is derived from code by Thomas Roell, Orest
+ * Zborowski, and David Dawes (see the source code for complete
+ * references). */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+/*****************************************************************************/
+/* Define some macros to make it easier to move this file to another
+ * part of the Xserver tree. All calls to the dmx* layer are #defined
+ * here for the .c file. The .h file will also have to be edited. */
+#include "dmxinputinit.h"
+#include "lnx-keyboard.h"
+
+#define GETPRIV myPrivate *priv \
+ = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
+
+#define LOG0(f) dmxLog(dmxDebug,f)
+#define LOG1(f,a) dmxLog(dmxDebug,f,a)
+#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define FATAL0(f) dmxLog(dmxFatal,f)
+#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
+#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
+#define MOTIONPROC dmxMotionProcPtr
+#define ENQUEUEPROC dmxEnqueueProcPtr
+#define CHECKPROC dmxCheckSpecialProcPtr
+#define SWITCHRETPROC dmxVTSwitchReturnProcPtr
+#define BLOCK DMXBlockType
+#define MESSAGE "\033c\n\n\nDMX taking input from this console..."
+#define FINALMESSAGE "\033cDMX terminated."
+
+/* End of interface definitions. */
+/*****************************************************************************/
+
+#include "inputstr.h"
+#include <X11/Xos.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/vt.h>
+#include <sys/kd.h>
+#include <termios.h>
+#include "atKeynames.h"
+#if 00
+#include "xf86Keymap.h"
+#endif
+#include <linux/keyboard.h>
+#include <xkbsrv.h>
+
+#define NUM_AT2LNX (sizeof(at2lnx) / sizeof(at2lnx[0]))
+#define NUM_STATE_ENTRIES (256/32)
+
+
+/* Private area for Linux-style keyboards. */
+typedef struct _myPrivate {
+ int fd;
+ int vtno;
+ int vtcurrent;
+ int kbdtrans;
+ struct termios kbdtty;
+ int kbdType;
+ CARD32 kbdState[NUM_STATE_ENTRIES];
+ DeviceIntPtr pKeyboard;
+ unsigned char prefix;
+
+ int switched;
+ SWITCHRETPROC switch_return;
+ void *switch_return_data;
+
+ /* For bell */
+ int pitch;
+ unsigned long duration;
+} myPrivate;
+
+static myPrivate *PRIV = NULL;
+
+#undef SYSCALL
+#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
+
+static int kbdLinuxKeyDown(myPrivate *priv, int keyCode)
+{
+ CARD8 byte = keyCode >> 5;
+ CARD32 bit = 1 << (keyCode & 0x1f);
+
+ if (byte > NUM_STATE_ENTRIES) return 0;
+ return priv->kbdState[byte] & bit;
+}
+
+static void kbdLinuxKeyState(myPrivate *priv, int type, int keyCode)
+{
+ CARD8 byte = keyCode >> 5;
+ CARD32 bit = 1 << (keyCode & 0x1f);
+
+ if (byte > NUM_STATE_ENTRIES) return;
+ if (type == KeyPress) priv->kbdState[byte] |= bit;
+ else priv->kbdState[byte] &= ~bit;
+}
+
+static 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_BackSpace,
+ 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
+};
+
+/*
+ * Maps the AT keycodes to Linux keycodes
+ */
+static unsigned char at2lnx[NUM_KEYCODES] =
+{
+ 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */
+ 0x03, /* KEY_2 */ 0x04, /* KEY_3 */
+ 0x05, /* KEY_4 */ 0x06, /* KEY_5 */
+ 0x07, /* KEY_6 */ 0x08, /* KEY_7 */
+ 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */
+ 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */
+ 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */
+ 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */
+ 0x11, /* KEY_W */ 0x12, /* KEY_E */
+ 0x13, /* KEY_R */ 0x14, /* KEY_T */
+ 0x15, /* KEY_Y */ 0x16, /* KEY_U */
+ 0x17, /* KEY_I */ 0x18, /* KEY_O */
+ 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */
+ 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */
+ 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */
+ 0x1f, /* KEY_S */ 0x20, /* KEY_D */
+ 0x21, /* KEY_F */ 0x22, /* KEY_G */
+ 0x23, /* KEY_H */ 0x24, /* KEY_J */
+ 0x25, /* KEY_K */ 0x26, /* KEY_L */
+ 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */
+ 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */
+ 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */
+ 0x2d, /* KEY_X */ 0x2e, /* KEY_C */
+ 0x2f, /* KEY_V */ 0x30, /* KEY_B */
+ 0x31, /* KEY_N */ 0x32, /* KEY_M */
+ 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */
+ 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */
+ 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */
+ 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */
+ 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */
+ 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */
+ 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */
+ 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */
+ 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */
+ 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */
+ 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */
+ 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */
+ 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */
+ 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */
+ 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */
+ 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */
+ 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */
+ 0x00, /* 0x55 */ 0x56, /* KEY_Less */
+ 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */
+ 0x66, /* KEY_Home */ 0x67, /* KEY_Up */
+ 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */
+ 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */
+ 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */
+ 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */
+ 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */
+ 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */
+ 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */
+ 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */
+ 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */
+ 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */
+ 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */
+ 0x00, /* 0x71 */ 0x00, /* 0x72 */
+ 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */
+ 0x00, /* 0x75 */ 0x00, /* 0x76 */
+ 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */
+ 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */
+ 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */
+ 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */
+ 0x00, /* 0x7f */
+};
+
+/** Create a private structure for use within this file. */
+pointer kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard)
+{
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->fd = -1;
+ priv->pKeyboard = pKeyboard;
+ return priv;
+}
+
+/** Destroy a private structure. */
+void kbdLinuxDestroyPrivate(pointer priv)
+{
+ if (priv) free(priv);
+}
+
+/** Ring the bell.
+ *
+ * Note: we completely ignore the \a volume, since Linux's ioctl()
+ * interface does not provide a way to control it. If it did, the XBell
+ * manpage tells how the actual volume is a function of the percent and
+ * the (base) volume.
+ *
+ * Note that most of the other PC-based bell drivers compute the
+ * duration for KDMKTONE as a function of the volume and the duration.
+ * For some drivers, the duration is only measured in mS if the volume
+ * is 50, and is scaled by the volume for other values. This seems
+ * confusing and possibly incorrect (the xset man page says that the
+ * bell will be "as closely as it can to the user's specifications" --
+ * if we ignore the volume and set the duration correctly, then we'll
+ * get one parameter "wrong" -- but if we use the volume to scale the
+ * duration, then we'll get both parameters "wrong"). */
+void kbdLinuxBell(DevicePtr pDev, int percent,
+ int volume, int pitch, int duration)
+{
+ GETPRIV;
+
+ if (duration && pitch) {
+ ioctl(priv->fd,
+ KDMKTONE,
+ ((1193190 / pitch) & 0xffff) /* Low bits specify cycle time */
+ | (duration << 16)); /* High bits are duration in msec */
+ }
+}
+
+/** Set the LEDs. */
+void kbdLinuxCtrl(DevicePtr pDev, KeybdCtrl *ctrl)
+{
+ GETPRIV;
+
+ ioctl(priv->fd, KDSETLED, ctrl->leds & 0x07);
+}
+
+static int kbdLinuxGetFreeVTNumber(void)
+{
+ int fd = -1;
+ int vtno;
+ int i;
+ const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
+
+ for (i = 0; tty0[i]; i++)
+ if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break;
+ if (fd < 0)
+ FATAL1("kbdLinuxGetFreeVTNumber: Cannot open tty0 (%s)\n",
+ strerror(errno));
+ if (ioctl(fd, VT_OPENQRY, &vtno) < 0 || vtno < 0)
+ FATAL0("kbdLinuxGetFreeVTNumber: Cannot find a free VT\n");
+ return vtno;
+}
+
+static int kbdLinuxOpenVT(int vtno)
+{
+ int fd = -1;
+ int i;
+ const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
+ char name[64]; /* RATS: Only used in XmuSnprintf */
+
+ for (i = 0; vcs[i]; i++) {
+ XmuSnprintf(name, sizeof(name), vcs[i], vtno);
+ if ((fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) break;
+ }
+ if (fd < 0)
+ FATAL2("kbdLinuxOpenVT: Cannot open VT %d (%s)\n",
+ vtno, strerror(errno));
+ return fd;
+}
+
+static int kbdLinuxGetCurrentVTNumber(int fd)
+{
+ struct vt_stat vts;
+
+ if (!ioctl(fd, VT_GETSTATE, &vts)) return vts.v_active;
+ return -1;
+}
+
+static int kbdLinuxActivate(int fd, int vtno, int setSig);
+
+/** Currently unused hook called prior to an VT switch. */
+void kbdLinuxVTPreSwitch(pointer p)
+{
+}
+
+/** Currently unused hook called after returning from a VT switch. */
+void kbdLinuxVTPostSwitch(pointer p)
+{
+}
+
+/** Tell the operating system to switch to \a vt. The \a switch_return
+ * function is called with the \a switch_return_data when the VT is
+ * switched back to the pre-switch VT (i.e., the user returns to the DMX
+ * session). */
+int kbdLinuxVTSwitch(pointer p, int vt,
+ void (*switch_return)(pointer),
+ pointer switch_return_data)
+{
+ myPrivate *priv = p;
+
+ if (priv->switched) FATAL0("kbdLinuxVTSwitch: already switched...\n");
+ if (priv->vtno == vt) return 0;
+
+ PRIV = priv;
+ priv->switched = 0; /* Will switch to 1 in handler */
+ priv->switch_return = switch_return;
+ priv->switch_return_data = switch_return_data;
+ kbdLinuxActivate(priv->fd, vt, 0);
+ return 1;
+}
+
+/* RATS: This function is only ever used to handle SIGUSR1. */
+static void kbdLinuxVTSignalHandler(int sig)
+{
+ myPrivate *priv = PRIV;
+
+ signal(sig, kbdLinuxVTSignalHandler);
+ if (priv) {
+ ioctl(priv->fd, VT_RELDISP, VT_ACKACQ);
+ priv->switched = !priv->switched;
+ LOG2("kbdLinuxVTSignalHandler: got signal %d, switched = %d\n",
+ sig, priv->switched);
+ if (!priv->switched && priv->switch_return)
+ priv->switch_return(priv->switch_return_data);
+ }
+}
+
+static int kbdLinuxActivate(int fd, int vtno, int setSig)
+{
+ int result;
+ struct vt_mode VT;
+
+ SYSCALL(result = ioctl(fd, VT_ACTIVATE, vtno));
+ if (result) FATAL0("kbdLinuxActivate: VT_ACTIVATE failed\n");
+ SYSCALL(result = ioctl(fd, VT_WAITACTIVE, vtno));
+ if (result) FATAL0("kbdLinuxActivate: VT_WAITACTIVE failed\n");
+ if (setSig) {
+ SYSCALL(result = ioctl(fd, VT_GETMODE, &VT));
+ if (result < 0) FATAL0("kbdLinuxActivate: VT_GETMODE failed\n");
+ VT.mode = VT_PROCESS;
+ VT.relsig = SIGUSR1;
+ VT.acqsig = SIGUSR1;
+ if (ioctl(fd, VT_SETMODE, &VT))
+ FATAL0("kbdLinuxActivate: VT_SETMODE VT_PROCESS failed\n");
+ signal(SIGUSR1, kbdLinuxVTSignalHandler);
+ }
+ return Success;
+}
+
+static void kbdLinuxOpenConsole(DevicePtr pDev)
+{
+ GETPRIV;
+ const char *msg = MESSAGE;
+
+ if (priv->fd >= 0) return;
+ priv->vtno = kbdLinuxGetFreeVTNumber();
+ priv->fd = kbdLinuxOpenVT(priv->vtno);
+ priv->vtcurrent = kbdLinuxGetCurrentVTNumber(priv->fd);
+ LOG2("kbdLinuxOpenConsole: current VT %d; using free VT %d\n",
+ priv->vtcurrent, priv->vtno);
+ kbdLinuxActivate(priv->fd, priv->vtno, 1);
+ ioctl(priv->fd, KDSETMODE, KD_GRAPHICS); /* To turn off gpm */
+ if (msg) write(priv->fd, msg, strlen(msg));
+}
+
+static void kbdLinuxCloseConsole(DevicePtr pDev)
+{
+ GETPRIV;
+ struct vt_mode VT;
+ const char *msg = FINALMESSAGE;
+
+ if (priv->fd < 0) return;
+
+ ioctl(priv->fd, KDSETMODE, KD_TEXT);
+ if (msg) write(priv->fd, msg, strlen(msg));
+ if (ioctl(priv->fd, VT_GETMODE, &VT) != -1) {
+ VT.mode = VT_AUTO;
+ ioctl(priv->fd, VT_SETMODE, &VT);
+ }
+
+ LOG1("kbdLinuxCloseConsole: switching to VT %d\n", priv->vtcurrent);
+ if (priv->vtcurrent >= 0) kbdLinuxActivate(priv->fd, priv->vtcurrent, 0);
+
+ close(priv->fd);
+ priv->fd = -1;
+}
+
+/** Initialize the \a pDev as a Linux keyboard. */
+void kbdLinuxInit(DevicePtr pDev)
+{
+ GETPRIV;
+
+ if (priv->fd <= 0) kbdLinuxOpenConsole(pDev);
+
+ ioctl(priv->fd, KDGKBMODE, &priv->kbdtrans);
+ if (tcgetattr(priv->fd, &priv->kbdtty) < 0)
+ FATAL1("kbdLinuxInit: tcgetattr failed (%s)\n", strerror(errno));
+}
+
+static int kbdLinuxPrefix0Mapping(unsigned char *scanCode)
+{
+ /* Table from xfree86/common/xf86Events.c */
+ switch (*scanCode) {
+ case KEY_KP_7: *scanCode = KEY_Home; break; /* curs home */
+ case KEY_KP_8: *scanCode = KEY_Up; break; /* curs up */
+ case KEY_KP_9: *scanCode = KEY_PgUp; break; /* curs pgup */
+ case KEY_KP_4: *scanCode = KEY_Left; break; /* curs left */
+ case KEY_KP_5: *scanCode = KEY_Begin; break; /* curs begin */
+ case KEY_KP_6: *scanCode = KEY_Right; break; /* curs right */
+ case KEY_KP_1: *scanCode = KEY_End; break; /* curs end */
+ case KEY_KP_2: *scanCode = KEY_Down; break; /* curs down */
+ case KEY_KP_3: *scanCode = KEY_PgDown; break; /* curs pgdown */
+ case KEY_KP_0: *scanCode = KEY_Insert; break; /* curs insert */
+ case KEY_KP_Decimal: *scanCode = KEY_Delete; break; /* curs delete */
+ case KEY_Enter: *scanCode = KEY_KP_Enter; break; /* keypad enter */
+ case KEY_LCtrl: *scanCode = KEY_RCtrl; break; /* right ctrl */
+ case KEY_KP_Multiply: *scanCode = KEY_Print; break; /* print */
+ case KEY_Slash: *scanCode = KEY_KP_Divide; break; /* keyp divide */
+ case KEY_Alt: *scanCode = KEY_AltLang; break; /* right alt */
+ case KEY_ScrollLock: *scanCode = KEY_Break; break; /* curs break */
+ case 0x5b: *scanCode = KEY_LMeta; break;
+ case 0x5c: *scanCode = KEY_RMeta; break;
+ case 0x5d: *scanCode = KEY_Menu; break;
+ case KEY_F3: *scanCode = KEY_F13; break;
+ case KEY_F4: *scanCode = KEY_F14; break;
+ case KEY_F5: *scanCode = KEY_F15; break;
+ case KEY_F6: *scanCode = KEY_F16; break;
+ case KEY_F7: *scanCode = KEY_F17; break;
+ case KEY_KP_Plus: *scanCode = KEY_KP_DEC; break;
+ /*
+ * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6)
+ */
+ case 0x2A:
+ case 0x36:
+ return 1;
+ default:
+ /*
+ * "Internet" keyboards are generating lots of new codes.
+ * Let them pass. There is little consistency between them,
+ * so don't bother with symbolic names at this level.
+ */
+ scanCode += 0x78;
+ }
+ return 0;
+}
+
+static int kbdLinuxPrefixMapping(myPrivate *priv, unsigned char *scanCode)
+{
+ int pressed = *scanCode & 0x80;
+ unsigned char code = *scanCode & 0x7f;
+
+ /* If we don't have a prefix, check for one */
+ if (!priv->prefix) {
+ switch (code) {
+ case KEY_Prefix0:
+ case KEY_Prefix1:
+ priv->prefix = code;
+ return 1;
+ }
+ return 0; /* No change */
+ }
+
+ /* We have a prefix from the last scanCode */
+ switch (priv->prefix) {
+ case KEY_Prefix0:
+ priv->prefix = 0;
+ if (kbdLinuxPrefix0Mapping(&code)) return 1; /* Skip sequence */
+ break;
+ case KEY_Prefix1:
+ priv->prefix = (code = KEY_LCtrl) ? KEY_LCtrl : 0;
+ return 1; /* Use new prefix */
+ case KEY_LCtrl:
+ priv->prefix = 0;
+ if (code != KEY_NumLock) return 1; /* Skip sequence*/
+ code = KEY_Pause;
+ break;
+ }
+
+ *scanCode = code | (pressed ? 0x80 : 0x00);
+ return 0; /* Use old scanCode */
+}
+
+static void kbdLinuxConvert(DevicePtr pDev,
+ unsigned char scanCode,
+ ENQUEUEPROC enqueue,
+ CHECKPROC checkspecial,
+ BLOCK block)
+{
+ GETPRIV;
+ XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo;
+ int type;
+ KeySym keySym = NoSymbol;
+ int keyCode;
+ int switching;
+
+ /* Do special PC/AT prefix mapping -- may change scanCode! */
+ if (kbdLinuxPrefixMapping(priv, &scanCode)) return;
+
+ type = (scanCode & 0x80) ? KeyRelease : KeyPress;
+ keyCode = (scanCode & 0x7f) + MIN_KEYCODE;
+
+ /* Handle repeats */
+
+ if (keyCode >= xkbi->desc->min_key_code &&
+ keyCode <= xkbi->desc->max_key_code) {
+
+ int effectiveGroup = XkbGetEffectiveGroup(xkbi,
+ &xkbi->state,
+ scanCode);
+ keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup);
+#if 0
+ switch (keySym) {
+ case XK_Num_Lock:
+ case XK_Scroll_Lock:
+ case XK_Shift_Lock:
+ case XK_Caps_Lock:
+ /* Ignore releases and all but first press */
+ if (kbdLinuxModIgnore(priv, &xE, keySym)) return;
+ if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease;
+ else xE.u.u.type = KeyPress;
+ break;
+ }
+#endif
+
+ /* If key is already down, ignore or autorepeat */
+ if (type == KeyPress && kbdLinuxKeyDown(priv, keyCode)) {
+ KbdFeedbackClassRec *feed = priv->pKeyboard->kbdfeed;
+
+ /* No auto-repeat? */
+ if ((feed && !feed->ctrl.autoRepeat)
+ || priv->pKeyboard->key->xkbInfo->desc->map->modmap[keyCode]
+ || (feed
+ && !(feed->ctrl.autoRepeats[keyCode >> 3]
+ & (1 << (keyCode & 7))))) return; /* Ignore */
+
+ /* Do auto-repeat */
+ enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block);
+ type = KeyPress;
+ }
+
+ /* If key is already up, ignore */
+ if (type == KeyRelease && !kbdLinuxKeyDown(priv, keyCode)) return;
+ }
+
+ switching = 0;
+ if (checkspecial && type == KeyPress)
+ switching = checkspecial(pDev, keySym);
+ if (!switching) {
+ if (enqueue)
+ enqueue(pDev, type, keyCode, keySym, NULL, block);
+ kbdLinuxKeyState(priv, type, keyCode); /* Update our state bitmap */
+ }
+}
+
+/** Read an event from the \a pDev device. If the event is a motion
+ * event, enqueue it with the \a motion function. Otherwise, check for
+ * special keys with the \a checkspecial function and enqueue the event
+ * with the \a enqueue function. The \a block type is passed to the
+ * functions so that they may block SIGIO handling as appropriate to the
+ * caller of this function. */
+void kbdLinuxRead(DevicePtr pDev,
+ MOTIONPROC motion,
+ ENQUEUEPROC enqueue,
+ CHECKPROC checkspecial,
+ BLOCK block)
+{
+ GETPRIV;
+ unsigned char buf[256]; /* RATS: Only used in length-limited call */
+ unsigned char *pt;
+ int n;
+
+ while ((n = read(priv->fd, buf, sizeof(buf))) > 0)
+ for (pt = buf; n; --n, ++pt)
+ kbdLinuxConvert(pDev, *pt, enqueue, checkspecial, block);
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int kbdLinuxOn(DevicePtr pDev)
+{
+ GETPRIV;
+ struct termios nTty;
+
+ ioctl(priv->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, B9600);
+ cfsetospeed(&nTty, B9600);
+ if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0)
+ FATAL1("kbdLinuxOn: tcsetattr failed (%s)\n", strerror(errno));
+ return priv->fd;
+}
+
+/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
+void kbdLinuxOff(DevicePtr pDev)
+{
+ GETPRIV;
+
+ ioctl(priv->fd, KDSKBMODE, priv->kbdtrans);
+ tcsetattr(priv->fd, TCSANOW, &priv->kbdtty);
+ kbdLinuxCloseConsole(pDev);
+}
+
+
+static void kbdLinuxReadKernelMapping(int fd, KeySymsPtr pKeySyms)
+{
+ KeySym *k;
+ int i;
+ int maxkey;
+ static unsigned char tbl[GLYPHS_PER_KEY] = { /* RATS: Use ok */
+ 0, /* unshifted */
+ 1, /* shifted */
+ 0, /* modeswitch unshifted */
+ 0 /* modeswitch shifted */
+ };
+
+ /*
+ * Read the mapping from the kernel.
+ * Since we're still using the XFree86 scancode->AT keycode mapping
+ * routines, we need to convert the AT keycodes to Linux keycodes,
+ * then translate the Linux keysyms into X keysyms.
+ *
+ * First, figure out which tables to use for the modeswitch columns
+ * above, from the XF86Config fields.
+ */
+ tbl[2] = 8; /* alt */
+ tbl[3] = tbl[2] | 1;
+
+#if 00/*BP*/
+ k = map+GLYPHS_PER_KEY;
+#else
+ ErrorF("kbdLinuxReadKernelMapping() is broken/no-op'd\n");
+ return;
+#endif
+ maxkey = NUM_AT2LNX;
+
+ for (i = 0; i < maxkey; ++i) {
+ struct kbentry kbe;
+ int j;
+
+ kbe.kb_index = at2lnx[i];
+
+ for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) {
+ unsigned short kval;
+
+ *k = NoSymbol;
+
+ kbe.kb_table = tbl[j];
+ if (kbe.kb_index == 0 || ioctl(fd, KDGKBENT, &kbe)) continue;
+
+ kval = KVAL(kbe.kb_value);
+ switch (KTYP(kbe.kb_value)) {
+ case KT_LATIN:
+ case KT_LETTER: *k = linux_to_x[kval]; break;
+ case KT_FN:
+ if (kval <= 19) *k = XK_F1 + kval;
+ else switch (kbe.kb_value) {
+ case K_FIND: *k = XK_Home; /* or XK_Find */ break;
+ case K_INSERT: *k = XK_Insert; break;
+ case K_REMOVE: *k = XK_Delete; break;
+ case K_SELECT: *k = XK_End; /* or XK_Select */ break;
+ case K_PGUP: *k = XK_Prior; break;
+ case K_PGDN: *k = XK_Next; break;
+ case K_HELP: *k = XK_Help; break;
+ case K_DO: *k = XK_Execute; break;
+ case K_PAUSE: *k = XK_Pause; break;
+ case K_MACRO: *k = XK_Menu; break;
+ default: break;
+ }
+ break;
+ case KT_SPEC:
+ switch (kbe.kb_value) {
+ case K_ENTER: *k = XK_Return; break;
+ case K_BREAK: *k = XK_Break; break;
+ case K_CAPS: *k = XK_Caps_Lock; break;
+ case K_NUM: *k = XK_Num_Lock; break;
+ case K_HOLD: *k = XK_Scroll_Lock; break;
+ case K_COMPOSE: *k = XK_Multi_key; break;
+ default: break;
+ }
+ break;
+ case KT_PAD:
+ switch (kbe.kb_value) {
+ case K_PPLUS: *k = XK_KP_Add; break;
+ case K_PMINUS: *k = XK_KP_Subtract; break;
+ case K_PSTAR: *k = XK_KP_Multiply; break;
+ case K_PSLASH: *k = XK_KP_Divide; break;
+ case K_PENTER: *k = XK_KP_Enter; break;
+ case K_PCOMMA: *k = XK_KP_Separator; break;
+ case K_PDOT: *k = XK_KP_Decimal; break;
+ case K_PPLUSMINUS: *k = XK_KP_Subtract; break;
+ default: if (kval <= 9) *k = XK_KP_0 + kval; break;
+ }
+ break;
+ case KT_DEAD:
+ /* KT_DEAD keys are for accelerated diacritical creation. */
+ switch (kbe.kb_value) {
+ case K_DGRAVE: *k = XK_dead_grave; break;
+ case K_DACUTE: *k = XK_dead_acute; break;
+ case K_DCIRCM: *k = XK_dead_circumflex; break;
+ case K_DTILDE: *k = XK_dead_tilde; break;
+ case K_DDIERE: *k = XK_dead_diaeresis; break;
+ }
+ break;
+ case KT_CUR:
+ switch (kbe.kb_value) {
+ case K_DOWN: *k = XK_Down; break;
+ case K_LEFT: *k = XK_Left; break;
+ case K_RIGHT: *k = XK_Right; break;
+ case K_UP: *k = XK_Up; break;
+ }
+ break;
+ case KT_SHIFT:
+ switch (kbe.kb_value) {
+ case K_ALTGR: *k = XK_Alt_R; break;
+ case K_ALT:
+ *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L);
+ break;
+ case K_CTRL:
+ *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L);
+ break;
+ case K_CTRLL: *k = XK_Control_L; break;
+ case K_CTRLR: *k = XK_Control_R; break;
+ case K_SHIFT:
+ *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L);
+ break;
+ case K_SHIFTL: *k = XK_Shift_L; break;
+ case K_SHIFTR: *k = XK_Shift_R; break;
+ default: break;
+ }
+ break;
+ case KT_ASCII:
+ /* KT_ASCII keys accumulate a 3 digit decimal number that
+ * gets emitted when the shift state changes. We can't
+ * emulate that.
+ */
+ break;
+ case KT_LOCK:
+ if (kbe.kb_value == K_SHIFTLOCK) *k = XK_Shift_Lock;
+ break;
+ default: break;
+ }
+ }
+
+ if (k[-1] == k[-2]) k[-1] = NoSymbol;
+ if (k[-2] == k[-3]) k[-2] = NoSymbol;
+ if (k[-3] == k[-4]) k[-3] = NoSymbol;
+ if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol;
+ if (k[-1] == k[-4] && k[-2] == k[-3]
+ && k[-2] == NoSymbol) k[-1] = NoSymbol;
+ }
+}
+
+static void kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+ GETPRIV;
+ KeySym *k, *mapCopy;
+ char type;
+ int i;
+
+#if 00/*BP*/
+ mapCopy = malloc(sizeof(map));
+ memcpy(mapCopy, map, sizeof(map));
+#else
+ ErrorF("kbdLinuxGetMap() is broken/no-op'd\n");
+ return;
+#endif
+
+ kbdLinuxReadKernelMapping(priv->fd, pKeySyms);
+
+ /* compute the modifier map */
+ for (i = 0; i < MAP_LENGTH; i++)
+ pModMap[i] = NoSymbol; /* make sure it is restored */
+
+ for (k = mapCopy, i = MIN_KEYCODE;
+ i < NUM_KEYCODES + MIN_KEYCODE;
+ i++, k += 4) {
+ switch(*k) {
+ case XK_Shift_L:
+ case XK_Shift_R: pModMap[i] = ShiftMask; break;
+ case XK_Control_L:
+ case XK_Control_R: pModMap[i] = ControlMask; break;
+ case XK_Caps_Lock: pModMap[i] = LockMask; break;
+ case XK_Alt_L:
+ case XK_Alt_R: pModMap[i] = AltMask; break;
+ case XK_Num_Lock: pModMap[i] = NumLockMask; break;
+ case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break;
+ case XK_Kana_Lock:
+ case XK_Kana_Shift: pModMap[i] = KanaMask; break;
+ case XK_Mode_switch: pModMap[i] = AltLangMask; break;
+ }
+ }
+
+ priv->kbdType = (ioctl(priv->fd, KDGKBTYPE, &type) < 0) ? KB_101 : type;
+
+ pKeySyms->map = mapCopy; /* Must be XFree'able */
+ pKeySyms->mapWidth = GLYPHS_PER_KEY;
+ pKeySyms->minKeyCode = MIN_KEYCODE;
+ pKeySyms->maxKeyCode = MAX_KEYCODE;
+}
+
+/** Fill the \a info structure with information needed to initialize \a
+ * pDev. */
+void kbdLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ info->keyboard = 1;
+ info->keyClass = 1;
+ kbdLinuxGetMap(pDev, &info->keySyms, info->modMap);
+ info->focusClass = 1;
+ info->kbdFeedbackClass = 1;
+}
diff --git a/xorg-server/hw/dmx/input/usb-keyboard.c b/xorg-server/hw/dmx/input/usb-keyboard.c index c4667a3c3..fcbea47f9 100644 --- a/xorg-server/hw/dmx/input/usb-keyboard.c +++ b/xorg-server/hw/dmx/input/usb-keyboard.c @@ -1,444 +1,444 @@ -/* Portions of this file were derived from the following files: - * - ********************************************************************** - * - * xfree86/common/xf86KbdLnx.c - * - * Linux version of keymapping setup. The kernel (since 0.99.14) has support - * for fully remapping the keyboard, but there are some differences between - * the Linux map and the SVR4 map (esp. in the extended keycodes). We also - * remove the restriction on what keycodes can be remapped. - * Orest Zborowski. - * - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - * - * 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 Thomas Roell not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Thomas Roell makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THOMAS ROELL 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. - * - */ - -/* - * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * Authors: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * - * This code implements a low-level device driver for a USB keyboard - * under Linux. The keymap description is derived from code by Thomas - * Roell, Orest Zborowski. */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "atKeynames.h" -#include "usb-private.h" - -#define USB_KEYBOARD_DEBUG 0 - -/*****************************************************************************/ -/* Define some macros to make it easier to move this file to another - * part of the Xserver tree. All calls to the dmx* layer are #defined - * here for the .c file. The .h file will also have to be edited. */ -#include "usb-keyboard.h" -#include <xkbsrv.h> - -#define GETPRIV myPrivate *priv \ - = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private - -#define LOG0(f) dmxLog(dmxDebug,f) -#define LOG1(f,a) dmxLog(dmxDebug,f,a) -#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) -#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) -#define FATAL0(f) dmxLog(dmxFatal,f) -#define FATAL1(f,a) dmxLog(dmxFatal,f,a) -#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) -#define MOTIONPROC dmxMotionProcPtr -#define ENQUEUEPROC dmxEnqueueProcPtr -#define CHECKPROC dmxCheckSpecialProcPtr -#define BLOCK DMXBlockType - -/* End of interface definitions. */ -/*****************************************************************************/ - -#define GLYPHS_PER_KEY 4 -#define NUM_KEYCODES 248 -#define MIN_KEYCODE 8 -#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) - -static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = { -/* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */ - /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, - /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, - /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, - /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, - /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, - /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, - /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, - /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, - /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, - /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, - /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, - /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, - /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, - /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, - /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, - /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, - /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, - /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, - /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, - /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, - /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, - /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, - /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, - /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, - /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, - /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, - /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, - /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, - /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, - /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, - /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, - /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, - /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, - /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, - /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, - /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, - /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, - /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, - /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, - /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, - /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, - /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, - /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, - /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, - /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, - /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, - /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, - /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, - /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, - /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, - /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, - /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, - /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, - /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, - /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, - /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, - /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, - /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, - /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, - /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, - /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, - /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, - /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, - /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, - /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, - /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, - /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, - /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, - /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, - /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, - /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, - /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, - /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, - /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, - /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, - /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, - /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, - /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, - /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, - /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, - /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, - /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, - /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, - /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, - /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, - /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, - /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, - /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol, - /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, - /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol, - /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, - /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol, - /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol, - /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol, - /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol, - /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol, - /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, - /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, - /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, - /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, - /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, -}; - -static int kbdUSBKeyDown(myPrivate *priv, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return 0; - return priv->kbdState[byte] & bit; -} - -static void kbdUSBKeyState(myPrivate *priv, int type, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return; - if (type == KeyPress) priv->kbdState[byte] |= bit; - else priv->kbdState[byte] &= ~bit; -} - -/** Set the LEDs. */ -void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl) -{ - GETPRIV; - struct timeval tv; - struct input_event event; - int i, led; - - gettimeofday(&tv, NULL); - for (i = 0; i < 5; i++) { - event.time.tv_sec = tv.tv_sec; - event.time.tv_usec = tv.tv_usec; - event.type = EV_LED; - if (i == 0) led = 1; /* LED_CAPSL == 0x01 */ - else if (i == 1) led = 0; /* LED_NUML == 0x00 */ - else led = i; - event.code = led; - event.value = !!(ctrl->leds & (1 << led)); - write(priv->fd, &event, sizeof(event)); - } -} - -/** Initialize \a pDev using #usbInit. */ -void kbdUSBInit(DevicePtr pDev) -{ - usbInit(pDev, usbKeyboard); -} - -static void kbdUSBConvert(DevicePtr pDev, - unsigned int scanCode, - int value, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; - int type; - int keyCode; - KeySym keySym = NoSymbol; - int switching; - - /* Set up xEvent information */ - type = value ? KeyPress : KeyRelease; - keyCode = (scanCode & 0xff) + MIN_KEYCODE; - - /* Handle repeats */ - - if (keyCode >= xkbi->desc->min_key_code && - keyCode <= xkbi->desc->max_key_code) { - - int effectiveGroup = XkbGetEffectiveGroup(xkbi, - &xkbi->state, - scanCode); - keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); -#if 0 - switch (keySym) { - case XK_Num_Lock: - case XK_Scroll_Lock: - case XK_Shift_Lock: - case XK_Caps_Lock: - /* Ignore releases and all but first press */ - if (kbdLinuxModIgnore(priv, &xE, keySym)) return; - if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; - else xE.u.u.type = KeyPress; - break; - } -#endif - - /* If key is already down, ignore or autorepeat */ - if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) { - KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed; - - /* No auto-repeat? */ - if ((feed && !feed->ctrl.autoRepeat) - || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode] - || (feed - && !(feed->ctrl.autoRepeats[keyCode >> 3] - & (1 << (keyCode & 7))))) return; /* Ignore */ - - /* Do auto-repeat */ - enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); - type = KeyPress; - } - - /* If key is already up, ignore */ - if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) return; - } - - switching = 0; - if (checkspecial && type == KeyPress) - switching = checkspecial(pDev, keySym); - if (!switching) { - if (enqueue) - enqueue(pDev, type, keyCode, keySym, NULL, block); - kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */ - } -} - -/** Read an event from the \a pDev device. If the event is a motion - * event, enqueue it with the \a motion function. Otherwise, check for - * special keys with the \a checkspecial function and enqueue the event - * with the \a enqueue function. The \a block type is passed to the - * functions so that they may block SIGIO handling as appropriate to the - * caller of this function. */ -void kbdUSBRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - struct input_event raw; - - while (read(priv->fd, &raw, sizeof(raw)) > 0) { -#if USB_KEYBOARD_DEBUG - LOG3("KBD: type = %d, code = 0x%02x, value = %d\n", - raw.type, raw.code, raw.value); -#endif - kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block); - } -} - -/** Turn \a pDev on (i.e., take input from \a pDev). */ -int kbdUSBOn(DevicePtr pDev) -{ - GETPRIV; - - if (priv->fd < 0) kbdUSBInit(pDev); - return priv->fd; -} - -static void kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) -{ - KeySym *k, *mapCopy; - int i; - - mapCopy = xalloc(sizeof(map)); - memcpy(mapCopy, map, sizeof(map)); - - /* compute the modifier map */ - for (i = 0; i < MAP_LENGTH; i++) - pModMap[i] = NoSymbol; /* make sure it is restored */ - - for (k = mapCopy, i = MIN_KEYCODE; - i < NUM_KEYCODES + MIN_KEYCODE; - i++, k += 4) { - switch(*k) { - case XK_Shift_L: - case XK_Shift_R: pModMap[i] = ShiftMask; break; - case XK_Control_L: - case XK_Control_R: pModMap[i] = ControlMask; break; - case XK_Caps_Lock: pModMap[i] = LockMask; break; - case XK_Alt_L: - case XK_Alt_R: pModMap[i] = AltMask; break; - case XK_Num_Lock: pModMap[i] = NumLockMask; break; - case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; - case XK_Kana_Lock: - case XK_Kana_Shift: pModMap[i] = KanaMask; break; - case XK_Mode_switch: pModMap[i] = AltLangMask; break; - } - } - - pKeySyms->map = mapCopy; /* Must be XFree'able */ - pKeySyms->mapWidth = GLYPHS_PER_KEY; - pKeySyms->minKeyCode = MIN_KEYCODE; - pKeySyms->maxKeyCode = MAX_KEYCODE; -} - -/** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) -{ - info->keyboard = 1; - info->keyClass = 1; - kbdUSBGetMap(pDev, &info->keySyms, info->modMap); - info->focusClass = 1; - info->kbdFeedbackClass = 1; - info->names.keycodes = xstrdup("powerpcps2"); - info->force = 1; -} +/* Portions of this file were derived from the following files:
+ *
+ **********************************************************************
+ *
+ * xfree86/common/xf86KbdLnx.c
+ *
+ * Linux version of keymapping setup. The kernel (since 0.99.14) has support
+ * for fully remapping the keyboard, but there are some differences between
+ * the Linux map and the SVR4 map (esp. in the extended keycodes). We also
+ * remove the restriction on what keycodes can be remapped.
+ * Orest Zborowski.
+ *
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ *
+ * 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 Thomas Roell not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Thomas Roell makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THOMAS ROELL 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.
+ *
+ */
+
+/*
+ * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * This code implements a low-level device driver for a USB keyboard
+ * under Linux. The keymap description is derived from code by Thomas
+ * Roell, Orest Zborowski. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "atKeynames.h"
+#include "usb-private.h"
+
+#define USB_KEYBOARD_DEBUG 0
+
+/*****************************************************************************/
+/* Define some macros to make it easier to move this file to another
+ * part of the Xserver tree. All calls to the dmx* layer are #defined
+ * here for the .c file. The .h file will also have to be edited. */
+#include "usb-keyboard.h"
+#include <xkbsrv.h>
+
+#define GETPRIV myPrivate *priv \
+ = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
+
+#define LOG0(f) dmxLog(dmxDebug,f)
+#define LOG1(f,a) dmxLog(dmxDebug,f,a)
+#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define FATAL0(f) dmxLog(dmxFatal,f)
+#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
+#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
+#define MOTIONPROC dmxMotionProcPtr
+#define ENQUEUEPROC dmxEnqueueProcPtr
+#define CHECKPROC dmxCheckSpecialProcPtr
+#define BLOCK DMXBlockType
+
+/* End of interface definitions. */
+/*****************************************************************************/
+
+#define GLYPHS_PER_KEY 4
+#define NUM_KEYCODES 248
+#define MIN_KEYCODE 8
+#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
+
+static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = {
+/* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */
+ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol,
+ /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol,
+ /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol,
+ /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol,
+ /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol,
+ /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol,
+ /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol,
+ /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol,
+ /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol,
+ /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol,
+ /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol,
+ /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol,
+ /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol,
+ /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol,
+ /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol,
+ /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol,
+ /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol,
+ /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol,
+ /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol,
+ /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol,
+ /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol,
+ /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol,
+ /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol,
+ /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol,
+ /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol,
+ /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol,
+ /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol,
+ /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol,
+ /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol,
+ /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol,
+ /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol,
+ /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol,
+ /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol,
+ /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol,
+ /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol,
+ /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol,
+ /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol,
+};
+
+static int kbdUSBKeyDown(myPrivate *priv, int keyCode)
+{
+ CARD8 byte = keyCode >> 5;
+ CARD32 bit = 1 << (keyCode & 0x1f);
+
+ if (byte > NUM_STATE_ENTRIES) return 0;
+ return priv->kbdState[byte] & bit;
+}
+
+static void kbdUSBKeyState(myPrivate *priv, int type, int keyCode)
+{
+ CARD8 byte = keyCode >> 5;
+ CARD32 bit = 1 << (keyCode & 0x1f);
+
+ if (byte > NUM_STATE_ENTRIES) return;
+ if (type == KeyPress) priv->kbdState[byte] |= bit;
+ else priv->kbdState[byte] &= ~bit;
+}
+
+/** Set the LEDs. */
+void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl)
+{
+ GETPRIV;
+ struct timeval tv;
+ struct input_event event;
+ int i, led;
+
+ gettimeofday(&tv, NULL);
+ for (i = 0; i < 5; i++) {
+ event.time.tv_sec = tv.tv_sec;
+ event.time.tv_usec = tv.tv_usec;
+ event.type = EV_LED;
+ if (i == 0) led = 1; /* LED_CAPSL == 0x01 */
+ else if (i == 1) led = 0; /* LED_NUML == 0x00 */
+ else led = i;
+ event.code = led;
+ event.value = !!(ctrl->leds & (1 << led));
+ write(priv->fd, &event, sizeof(event));
+ }
+}
+
+/** Initialize \a pDev using #usbInit. */
+void kbdUSBInit(DevicePtr pDev)
+{
+ usbInit(pDev, usbKeyboard);
+}
+
+static void kbdUSBConvert(DevicePtr pDev,
+ unsigned int scanCode,
+ int value,
+ ENQUEUEPROC enqueue,
+ CHECKPROC checkspecial,
+ BLOCK block)
+{
+ GETPRIV;
+ XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo;
+ int type;
+ int keyCode;
+ KeySym keySym = NoSymbol;
+ int switching;
+
+ /* Set up xEvent information */
+ type = value ? KeyPress : KeyRelease;
+ keyCode = (scanCode & 0xff) + MIN_KEYCODE;
+
+ /* Handle repeats */
+
+ if (keyCode >= xkbi->desc->min_key_code &&
+ keyCode <= xkbi->desc->max_key_code) {
+
+ int effectiveGroup = XkbGetEffectiveGroup(xkbi,
+ &xkbi->state,
+ scanCode);
+ keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup);
+#if 0
+ switch (keySym) {
+ case XK_Num_Lock:
+ case XK_Scroll_Lock:
+ case XK_Shift_Lock:
+ case XK_Caps_Lock:
+ /* Ignore releases and all but first press */
+ if (kbdLinuxModIgnore(priv, &xE, keySym)) return;
+ if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease;
+ else xE.u.u.type = KeyPress;
+ break;
+ }
+#endif
+
+ /* If key is already down, ignore or autorepeat */
+ if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) {
+ KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed;
+
+ /* No auto-repeat? */
+ if ((feed && !feed->ctrl.autoRepeat)
+ || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode]
+ || (feed
+ && !(feed->ctrl.autoRepeats[keyCode >> 3]
+ & (1 << (keyCode & 7))))) return; /* Ignore */
+
+ /* Do auto-repeat */
+ enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block);
+ type = KeyPress;
+ }
+
+ /* If key is already up, ignore */
+ if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) return;
+ }
+
+ switching = 0;
+ if (checkspecial && type == KeyPress)
+ switching = checkspecial(pDev, keySym);
+ if (!switching) {
+ if (enqueue)
+ enqueue(pDev, type, keyCode, keySym, NULL, block);
+ kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */
+ }
+}
+
+/** Read an event from the \a pDev device. If the event is a motion
+ * event, enqueue it with the \a motion function. Otherwise, check for
+ * special keys with the \a checkspecial function and enqueue the event
+ * with the \a enqueue function. The \a block type is passed to the
+ * functions so that they may block SIGIO handling as appropriate to the
+ * caller of this function. */
+void kbdUSBRead(DevicePtr pDev,
+ MOTIONPROC motion,
+ ENQUEUEPROC enqueue,
+ CHECKPROC checkspecial,
+ BLOCK block)
+{
+ GETPRIV;
+ struct input_event raw;
+
+ while (read(priv->fd, &raw, sizeof(raw)) > 0) {
+#if USB_KEYBOARD_DEBUG
+ LOG3("KBD: type = %d, code = 0x%02x, value = %d\n",
+ raw.type, raw.code, raw.value);
+#endif
+ kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block);
+ }
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int kbdUSBOn(DevicePtr pDev)
+{
+ GETPRIV;
+
+ if (priv->fd < 0) kbdUSBInit(pDev);
+ return priv->fd;
+}
+
+static void kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+ KeySym *k, *mapCopy;
+ int i;
+
+ mapCopy = malloc(sizeof(map));
+ memcpy(mapCopy, map, sizeof(map));
+
+ /* compute the modifier map */
+ for (i = 0; i < MAP_LENGTH; i++)
+ pModMap[i] = NoSymbol; /* make sure it is restored */
+
+ for (k = mapCopy, i = MIN_KEYCODE;
+ i < NUM_KEYCODES + MIN_KEYCODE;
+ i++, k += 4) {
+ switch(*k) {
+ case XK_Shift_L:
+ case XK_Shift_R: pModMap[i] = ShiftMask; break;
+ case XK_Control_L:
+ case XK_Control_R: pModMap[i] = ControlMask; break;
+ case XK_Caps_Lock: pModMap[i] = LockMask; break;
+ case XK_Alt_L:
+ case XK_Alt_R: pModMap[i] = AltMask; break;
+ case XK_Num_Lock: pModMap[i] = NumLockMask; break;
+ case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break;
+ case XK_Kana_Lock:
+ case XK_Kana_Shift: pModMap[i] = KanaMask; break;
+ case XK_Mode_switch: pModMap[i] = AltLangMask; break;
+ }
+ }
+
+ pKeySyms->map = mapCopy; /* Must be XFree'able */
+ pKeySyms->mapWidth = GLYPHS_PER_KEY;
+ pKeySyms->minKeyCode = MIN_KEYCODE;
+ pKeySyms->maxKeyCode = MAX_KEYCODE;
+}
+
+/** Fill the \a info structure with information needed to initialize \a
+ * pDev. */
+void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ info->keyboard = 1;
+ info->keyClass = 1;
+ kbdUSBGetMap(pDev, &info->keySyms, info->modMap);
+ info->focusClass = 1;
+ info->kbdFeedbackClass = 1;
+ info->names.keycodes = xstrdup("powerpcps2");
+ info->force = 1;
+}
|