aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/sun/sunKbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/sun/sunKbd.c')
-rw-r--r--nx-X11/programs/Xserver/hw/sun/sunKbd.c1071
1 files changed, 1071 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/sun/sunKbd.c b/nx-X11/programs/Xserver/hw/sun/sunKbd.c
new file mode 100644
index 000000000..a11026d6f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/sun/sunKbd.c
@@ -0,0 +1,1071 @@
+/* $Xorg: sunKbd.c,v 1.3 2000/08/17 19:48:30 cpqbld Exp $ */
+/*-
+ * Copyright 1987 by the Regents of the University of California
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+/************************************************************
+Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright no-
+tice appear in all copies and that both that copyright no-
+tice and this permission notice appear in supporting docu-
+mentation, and that the names of Sun or The Open Group
+not be used in advertising or publicity pertaining to
+distribution of the software without specific prior
+written permission. Sun and The Open Group make no
+representations about the suitability of this software for
+any purpose. It is provided "as is" without any express or
+implied warranty.
+
+SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
+NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
+ABLE 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: xc/programs/Xserver/hw/sun/sunKbd.c,v 1.8 2001/10/28 03:33:11 tsi Exp $ */
+
+#define NEED_EVENTS
+#include "sun.h"
+#include "keysym.h"
+#include "Sunkeysym.h"
+#include "mi.h"
+
+#ifdef XKB
+#include <X11/extensions/XKB.h>
+#include <X11/extensions/XKBstr.h>
+#include <X11/extensions/XKBsrv.h>
+#endif
+
+#define SUN_LED_MASK 0x0f
+#define MIN_KEYCODE 7 /* necessary to avoid the mouse buttons */
+#define MAX_KEYCODE 255 /* limited by the protocol */
+#ifndef KB_SUN4
+#define KB_SUN4 4
+#endif
+
+#define AUTOREPEAT_INITIATE 400
+#define AUTOREPEAT_DELAY 50
+
+#define tvminus(tv, tv1, tv2) /* tv = tv1 - tv2 */ \
+ if ((tv1).tv_usec < (tv2).tv_usec) { \
+ (tv1).tv_usec += 1000000; \
+ (tv1).tv_sec -= 1; \
+ } \
+ (tv).tv_usec = (tv1).tv_usec - (tv2).tv_usec; \
+ (tv).tv_sec = (tv1).tv_sec - (tv2).tv_sec;
+
+#define tvplus(tv, tv1, tv2) /* tv = tv1 + tv2 */ \
+ (tv).tv_sec = (tv1).tv_sec + (tv2).tv_sec; \
+ (tv).tv_usec = (tv1).tv_usec + (tv2).tv_usec; \
+ if ((tv).tv_usec > 1000000) { \
+ (tv).tv_usec -= 1000000; \
+ (tv).tv_sec += 1; \
+ }
+
+extern KeySymsRec sunKeySyms[];
+extern SunModmapRec* sunModMaps[];
+
+long sunAutoRepeatInitiate = 1000 * AUTOREPEAT_INITIATE;
+long sunAutoRepeatDelay = 1000 * AUTOREPEAT_DELAY;
+
+static int autoRepeatKeyDown = 0;
+static int autoRepeatReady;
+static int autoRepeatFirst;
+#if defined(_LP64) || defined(_I32LPx)
+static struct timeval32 autoRepeatLastKeyDownTv;
+static struct timeval32 autoRepeatDeltaTv;
+#else
+static struct timeval autoRepeatLastKeyDownTv;
+static struct timeval autoRepeatDeltaTv;
+#endif
+
+void sunKbdWait()
+{
+ static struct timeval lastChngKbdTransTv;
+ struct timeval tv;
+ struct timeval lastChngKbdDeltaTv;
+ unsigned int lastChngKbdDelta;
+
+ X_GETTIMEOFDAY(&tv);
+ if (!lastChngKbdTransTv.tv_sec)
+ lastChngKbdTransTv = tv;
+ tvminus(lastChngKbdDeltaTv, tv, lastChngKbdTransTv);
+ lastChngKbdDelta = TVTOMILLI(lastChngKbdDeltaTv);
+ if (lastChngKbdDelta < 750) {
+ unsigned wait;
+ /*
+ * We need to guarantee at least 750 milliseconds between
+ * calls to KIOCTRANS. YUCK!
+ */
+ wait = (750L - lastChngKbdDelta) * 1000L;
+ usleep (wait);
+ X_GETTIMEOFDAY(&tv);
+ }
+ lastChngKbdTransTv = tv;
+}
+
+static void SwapLKeys(keysyms)
+ KeySymsRec* keysyms;
+{
+ unsigned int i;
+ KeySym k;
+
+ for (i = 2; i < keysyms->maxKeyCode * keysyms->mapWidth; i++)
+ if (keysyms->map[i] == XK_L1 ||
+ keysyms->map[i] == XK_L2 ||
+ keysyms->map[i] == XK_L3 ||
+ keysyms->map[i] == XK_L4 ||
+ keysyms->map[i] == XK_L5 ||
+ keysyms->map[i] == XK_L6 ||
+ keysyms->map[i] == XK_L7 ||
+ keysyms->map[i] == XK_L8 ||
+ keysyms->map[i] == XK_L9 ||
+ keysyms->map[i] == XK_L10) {
+ /* yes, I could have done a clever two line swap! */
+ k = keysyms->map[i - 2];
+ keysyms->map[i - 2] = keysyms->map[i];
+ keysyms->map[i] = k;
+ }
+}
+
+static void SetLights (ctrl, fd)
+ KeybdCtrl* ctrl;
+ int fd;
+{
+#ifdef KIOCSLED
+ static unsigned char led_tab[16] = {
+ 0,
+ LED_NUM_LOCK,
+ LED_SCROLL_LOCK,
+ LED_SCROLL_LOCK | LED_NUM_LOCK,
+ LED_COMPOSE,
+ LED_COMPOSE | LED_NUM_LOCK,
+ LED_COMPOSE | LED_SCROLL_LOCK,
+ LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK,
+ LED_CAPS_LOCK,
+ LED_CAPS_LOCK | LED_NUM_LOCK,
+ LED_CAPS_LOCK | LED_SCROLL_LOCK,
+ LED_CAPS_LOCK | LED_SCROLL_LOCK | LED_NUM_LOCK,
+ LED_CAPS_LOCK | LED_COMPOSE,
+ LED_CAPS_LOCK | LED_COMPOSE | LED_NUM_LOCK,
+ LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK,
+ LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK
+ };
+ if (ioctl (fd, KIOCSLED, (caddr_t)&led_tab[ctrl->leds & 0x0f]) == -1)
+ Error("Failed to set keyboard lights");
+#endif
+}
+
+
+static void ModLight (device, on, led)
+ DeviceIntPtr device;
+ Bool on;
+ int led;
+{
+ KeybdCtrl* ctrl = &device->kbdfeed->ctrl;
+ sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate;
+
+ if(on) {
+ ctrl->leds |= led;
+ pPriv->leds |= led;
+ } else {
+ ctrl->leds &= ~led;
+ pPriv->leds &= ~led;
+ }
+ SetLights (ctrl, pPriv->fd);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunBell --
+ * Ring the terminal/keyboard bell
+ *
+ * Results:
+ * Ring the keyboard bell for an amount of time proportional to
+ * "loudness."
+ *
+ * Side Effects:
+ * None, really...
+ *
+ *-----------------------------------------------------------------------
+ */
+
+static void bell (
+ int fd,
+ int duration)
+{
+ int kbdCmd; /* Command to give keyboard */
+
+ kbdCmd = KBD_CMD_BELL;
+ if (ioctl (fd, KIOCCMD, &kbdCmd) == -1) {
+ Error("Failed to activate bell");
+ return;
+ }
+ if (duration) usleep (duration);
+ kbdCmd = KBD_CMD_NOBELL;
+ if (ioctl (fd, KIOCCMD, &kbdCmd) == -1)
+ Error ("Failed to deactivate bell");
+}
+
+static void sunBell (
+ int percent,
+ DeviceIntPtr device,
+ pointer ctrl,
+ int unused)
+{
+ KeybdCtrl* kctrl = (KeybdCtrl*) ctrl;
+ sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate;
+
+ if (percent == 0 || kctrl->bell == 0)
+ return;
+
+ bell (pPriv->fd, kctrl->bell_duration * 1000);
+}
+
+static void sunEnqueueEvent (xE)
+ xEvent* xE;
+{
+#ifndef i386
+ sigset_t holdmask;
+
+#ifdef SVR4
+ (void) sigaddset (&holdmask, SIGPOLL);
+#else
+ (void) sigaddset (&holdmask, SIGIO);
+#endif
+ (void) sigprocmask (SIG_BLOCK, &holdmask, (sigset_t*)NULL);
+ mieqEnqueue (xE);
+ (void) sigprocmask (SIG_UNBLOCK, &holdmask, (sigset_t*)NULL);
+#else
+ int oldmask = sigblock (sigmask (SIGIO));
+
+ mieqEnqueue (xE);
+ sigsetmask (oldmask);
+#endif
+}
+
+
+#define XLED_NUM_LOCK 0x1
+#define XLED_COMPOSE 0x4
+#define XLED_SCROLL_LOCK 0x2
+#define XLED_CAPS_LOCK 0x8
+
+static KeyCode LookupKeyCode (keysym, keysymsrec)
+ KeySym keysym;
+ KeySymsPtr keysymsrec;
+{
+ KeyCode i;
+ int ii, index = 0;
+
+ for (i = keysymsrec->minKeyCode; i < keysymsrec->maxKeyCode; i++)
+ for (ii = 0; ii < keysymsrec->mapWidth; ii++)
+ if (keysymsrec->map[index++] == keysym)
+ return i;
+ return 0;
+}
+
+static void pseudoKey(device, down, keycode)
+ DeviceIntPtr device;
+ Bool down;
+ KeyCode keycode;
+{
+ int bit;
+ CARD8 modifiers;
+ CARD16 mask;
+ BYTE* kptr;
+
+ kptr = &device->key->down[keycode >> 3];
+ bit = 1 << (keycode & 7);
+ modifiers = device->key->modifierMap[keycode];
+ if (down) {
+ /* fool dix into thinking this key is now "down" */
+ int i;
+ *kptr |= bit;
+ device->key->prev_state = device->key->state;
+ for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
+ if (mask & modifiers) {
+ device->key->modifierKeyCount[i]++;
+ device->key->state += mask;
+ modifiers &= ~mask;
+ }
+ } else {
+ /* fool dix into thinking this key is now "up" */
+ if (*kptr & bit) {
+ int i;
+ *kptr &= ~bit;
+ device->key->prev_state = device->key->state;
+ for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
+ if (mask & modifiers) {
+ if (--device->key->modifierKeyCount[i] <= 0) {
+ device->key->state &= ~mask;
+ device->key->modifierKeyCount[i] = 0;
+ }
+ modifiers &= ~mask;
+ }
+ }
+ }
+}
+
+static void DoLEDs(device, ctrl, pPriv)
+ DeviceIntPtr device; /* Keyboard to alter */
+ KeybdCtrl* ctrl;
+ sunKbdPrivPtr pPriv;
+{
+#ifdef XKB
+ if (noXkbExtension) {
+#endif
+ if ((ctrl->leds & XLED_CAPS_LOCK) && !(pPriv->leds & XLED_CAPS_LOCK))
+ pseudoKey(device, TRUE,
+ LookupKeyCode(XK_Caps_Lock, &device->key->curKeySyms));
+
+ if (!(ctrl->leds & XLED_CAPS_LOCK) && (pPriv->leds & XLED_CAPS_LOCK))
+ pseudoKey(device, FALSE,
+ LookupKeyCode(XK_Caps_Lock, &device->key->curKeySyms));
+
+ if ((ctrl->leds & XLED_NUM_LOCK) && !(pPriv->leds & XLED_NUM_LOCK))
+ pseudoKey(device, TRUE,
+ LookupKeyCode(XK_Num_Lock, &device->key->curKeySyms));
+
+ if (!(ctrl->leds & XLED_NUM_LOCK) && (pPriv->leds & XLED_NUM_LOCK))
+ pseudoKey(device, FALSE,
+ LookupKeyCode(XK_Num_Lock, &device->key->curKeySyms));
+
+ if ((ctrl->leds & XLED_SCROLL_LOCK) && !(pPriv->leds & XLED_SCROLL_LOCK))
+ pseudoKey(device, TRUE,
+ LookupKeyCode(XK_Scroll_Lock, &device->key->curKeySyms));
+
+ if (!(ctrl->leds & XLED_SCROLL_LOCK) && (pPriv->leds & XLED_SCROLL_LOCK))
+ pseudoKey(device, FALSE,
+ LookupKeyCode(XK_Scroll_Lock, &device->key->curKeySyms));
+
+ if ((ctrl->leds & XLED_COMPOSE) && !(pPriv->leds & XLED_COMPOSE))
+ pseudoKey(device, TRUE,
+ LookupKeyCode(SunXK_Compose, &device->key->curKeySyms));
+
+ if (!(ctrl->leds & XLED_COMPOSE) && (pPriv->leds & XLED_COMPOSE))
+ pseudoKey(device, FALSE,
+ LookupKeyCode(SunXK_Compose, &device->key->curKeySyms));
+#ifdef XKB
+ }
+#endif
+ pPriv->leds = ctrl->leds & 0x0f;
+ SetLights (ctrl, pPriv->fd);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunKbdCtrl --
+ * Alter some of the keyboard control parameters
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Some...
+ *
+ *-----------------------------------------------------------------------
+ */
+
+static void sunKbdCtrl (
+ DeviceIntPtr device,
+ KeybdCtrl* ctrl)
+{
+ sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate;
+
+ if (pPriv->fd < 0) return;
+
+ if (ctrl->click != pPriv->click) {
+ int kbdClickCmd;
+
+ pPriv->click = ctrl->click;
+ kbdClickCmd = pPriv->click ? KBD_CMD_CLICK : KBD_CMD_NOCLICK;
+ if (ioctl (pPriv->fd, KIOCCMD, &kbdClickCmd) == -1)
+ Error("Failed to set keyclick");
+ }
+ if ((pPriv->type == KB_SUN4) && (pPriv->leds != (ctrl->leds & 0x0f)))
+ DoLEDs(device, ctrl, pPriv);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunInitKbdNames --
+ * Handle the XKB initialization
+ *
+ * Results:
+ * None.
+ *
+ * Comments:
+ * This function needs considerable work, in conjunctions with
+ * the need to add geometry descriptions of Sun Keyboards.
+ * It would also be nice to have #defines for all the keyboard
+ * layouts so that we don't have to have these hard-coded
+ * numbers.
+ *
+ *-----------------------------------------------------------------------
+ */
+#ifdef XKB
+static void sunInitKbdNames (
+ XkbComponentNamesRec* names,
+ sunKbdPrivPtr pKbd)
+{
+#ifndef XKBBUFSIZE
+#define XKBBUFSIZE 64
+#endif
+ static char keycodesbuf[XKBBUFSIZE];
+ static char geometrybuf[XKBBUFSIZE];
+ static char symbolsbuf[XKBBUFSIZE];
+
+ names->keymap = NULL;
+ names->compat = "compat/complete";
+ names->types = "types/complete";
+ names->keycodes = keycodesbuf;
+ names->geometry = geometrybuf;
+ names->symbols = symbolsbuf;
+ (void) strcpy (keycodesbuf, "keycodes/");
+ (void) strcpy (geometrybuf, "geometry/");
+ (void) strcpy (symbolsbuf, "symbols/");
+
+ /* keycodes & geometry */
+ switch (pKbd->type) {
+ case KB_SUN2:
+ (void) strcat (names->keycodes, "sun(type2)");
+ (void) strcat (names->geometry, "sun(type2)");
+ (void) strcat (names->symbols, "us(sun2)");
+ break;
+ case KB_SUN3:
+ (void) strcat (names->keycodes, "sun(type3)");
+ (void) strcat (names->geometry, "sun(type3)");
+ (void) strcat (names->symbols, "us(sun3)");
+ break;
+ case KB_SUN4:
+ /* First, catch "fully known" models */
+ switch (pKbd->layout) {
+ case 11: /* type4, Sweden */
+ (void) strcat (names->geometry, "sun(type4_se)");
+ (void) strcat (names->keycodes,
+ "sun(type4_se_swapctl)");
+ (void) strcat (names->symbols,
+ "sun/se(sun4)+se(fixdollar)");
+ return;
+ break;
+ case 43: /* type5/5c, Sweden */
+ (void) strcat (names->geometry, "sun(type5c_se)");
+ (void) strcat (names->keycodes, "sun(type5_se)");
+ (void) strcat (names->symbols,
+ "sun/se(sun5)+se(fixdollar)");
+ return;
+ break;
+ case 90: /* "Compact 1", Sweden (???) */
+ break; /* No specific mapping, yet */
+ default:
+ break;
+ }
+
+ if (pKbd->layout == 19) {
+ (void) strcat (names->keycodes, "sun(US101A)");
+ (void) strcat (names->geometry, "pc101-NG"); /* XXX */
+ (void) strcat (names->symbols, "us(pc101)");
+ } else if (pKbd->layout < 33) {
+ (void) strcat (names->keycodes, "sun(type4)");
+ (void) strcat (names->geometry, "sun(type4)");
+ if (sunSwapLkeys)
+ (void) strcat (names->symbols, "sun/us(sun4ol)");
+ else
+ (void) strcat (names->symbols, "sun/us(sun4)");
+ } else {
+ (void) strcat (names->keycodes, "sun(type5)");
+
+ switch (pKbd->layout) {
+ case 33: case 80: /* U.S. */
+ case 47: case 94: /* Korea */
+ case 48: case 95: /* Taiwan */
+ case 49: case 96: /* Japan */
+ (void) strcat (names->geometry, "sun(type5)");
+ break;
+ case 34: case 81: /* U.S. Unix */
+ (void) strcat (names->geometry, "sun(type5unix)");
+ break;
+ default:
+ (void) strcat (names->geometry, "sun(type5euro)");
+ }
+
+ if (sunSwapLkeys)
+ (void) strcat (names->symbols, "sun/us(sun5ol)");
+ else
+ (void) strcat (names->symbols, "sun/us(sun5)");
+ }
+ break;
+ default:
+ names->keycodes = names->geometry = NULL;
+ break;
+ }
+
+ /* extra symbols */
+
+ if (pKbd->type == KB_SUN4) {
+ switch (pKbd->layout) {
+ case 4: case 36: case 83:
+ case 5: case 37: case 84:
+ case 6: case 38: case 85:
+ case 8: case 40: case 87:
+ case 9: case 41: case 88:
+ case 10: case 42: case 89:
+/* case 11: case 43: case 90: */ /* handled earlier */
+ case 12: case 44: case 91:
+ case 13: case 45: case 92:
+ case 14: case 46: case 93:
+ (void) strcat (names->symbols, "+iso9995-3(basic)"); break;
+ }
+ }
+
+ if (pKbd->type == KB_SUN4) {
+ switch (pKbd->layout) {
+ case 0: case 1: case 33: case 34: case 80: case 81:
+ break;
+ case 3:
+ (void) strcat (names->symbols, "+ca"); break;
+ case 4: case 36: case 83:
+ (void) strcat (names->symbols, "+dk"); break;
+ case 5: case 37: case 84:
+ (void) strcat (names->symbols, "+de"); break;
+ case 6: case 38: case 85:
+ (void) strcat (names->symbols, "+it"); break;
+ case 8: case 40: case 87:
+ (void) strcat (names->symbols, "+no"); break;
+ case 9: case 41: case 88:
+ (void) strcat (names->symbols, "+pt"); break;
+ case 10: case 42: case 89:
+ (void) strcat (names->symbols, "+es"); break;
+ /* case 11: case 43: */ /* handled earlier */
+ case 90:
+ (void) strcat (names->symbols, "+se"); break;
+ case 12: case 44: case 91:
+ (void) strcat (names->symbols, "+fr_CH"); break;
+ case 13: case 45: case 92:
+ (void) strcat (names->symbols, "+de_CH"); break;
+ case 14: case 46: case 93:
+ (void) strcat (names->symbols, "+gb"); break; /* s/b en_UK */
+ case 52:
+ (void) strcat (names->symbols, "+pl"); break;
+ case 53:
+ (void) strcat (names->symbols, "+cs"); break;
+ case 54:
+ (void) strcat (names->symbols, "+ru"); break;
+#if 0
+ /* don't have symbols defined for these yet, let them default */
+ case 2:
+ (void) strcat (names->symbols, "+fr_BE"); break;
+ case 7: case 39: case 86:
+ (void) strcat (names->symbols, "+nl"); break;
+ case 50: case 97:
+ (void) strcat (names->symbols, "+fr_CA"); break;
+ case 16: case 47: case 94:
+ (void) strcat (names->symbols, "+ko"); break;
+ case 17: case 48: case 95:
+ (void) strcat (names->symbols, "+tw"); break;
+ case 32: case 49: case 96:
+ (void) strcat (names->symbols, "+jp"); break;
+ case 51:
+ (void) strcat (names->symbols, "+hu"); break;
+#endif
+ /*
+ * by setting the symbols to NULL XKB will use the symbols in
+ * the "default" keymap.
+ */
+ default:
+ names->symbols = NULL; return; break;
+ }
+ }
+}
+#endif /* XKB */
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunKbdProc --
+ * Handle the initialization, etc. of a keyboard.
+ *
+ * Results:
+ * None.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+int sunKbdProc (
+ DeviceIntPtr device,
+ int what)
+{
+ int i;
+ DevicePtr pKeyboard = (DevicePtr) device;
+ sunKbdPrivPtr pPriv;
+ KeybdCtrl* ctrl = &device->kbdfeed->ctrl;
+ extern int XkbDfltRepeatDelay, XkbDfltRepeatInterval;
+
+ static CARD8 *workingModMap = NULL;
+ static KeySymsRec *workingKeySyms;
+
+ switch (what) {
+ case DEVICE_INIT:
+ if (pKeyboard != LookupKeyboardDevice()) {
+ ErrorF ("Cannot open non-system keyboard\n");
+ return (!Success);
+ }
+
+ if (!workingKeySyms) {
+ workingKeySyms = &sunKeySyms[sunKbdPriv.type];
+
+ if (sunKbdPriv.type == KB_SUN4 && sunSwapLkeys)
+ SwapLKeys(workingKeySyms);
+
+ if (workingKeySyms->minKeyCode < MIN_KEYCODE) {
+ workingKeySyms->minKeyCode += MIN_KEYCODE;
+ workingKeySyms->maxKeyCode += MIN_KEYCODE;
+ }
+ if (workingKeySyms->maxKeyCode > MAX_KEYCODE)
+ workingKeySyms->maxKeyCode = MAX_KEYCODE;
+ }
+
+ if (!workingModMap) {
+ workingModMap=(CARD8 *)xalloc(MAP_LENGTH);
+ (void) memset(workingModMap, 0, MAP_LENGTH);
+ for(i=0; sunModMaps[sunKbdPriv.type][i].key != 0; i++)
+ workingModMap[sunModMaps[sunKbdPriv.type][i].key + MIN_KEYCODE] =
+ sunModMaps[sunKbdPriv.type][i].modifiers;
+ }
+
+ (void) memset ((void *) defaultKeyboardControl.autoRepeats,
+ ~0, sizeof defaultKeyboardControl.autoRepeats);
+
+#ifdef XKB
+ if (noXkbExtension) {
+ sunAutoRepeatInitiate = XkbDfltRepeatDelay * 1000;
+ sunAutoRepeatDelay = XkbDfltRepeatInterval * 1000;
+#endif
+ autoRepeatKeyDown = 0;
+#ifdef XKB
+ }
+#endif
+ pKeyboard->devicePrivate = (pointer)&sunKbdPriv;
+ pKeyboard->on = FALSE;
+
+#ifdef XKB
+ if (noXkbExtension) {
+#endif
+ InitKeyboardDeviceStruct(pKeyboard,
+ workingKeySyms, workingModMap,
+ sunBell, sunKbdCtrl);
+#ifdef XKB
+ } else {
+ XkbComponentNamesRec names;
+ sunInitKbdNames (&names, &sunKbdPriv);
+ XkbInitKeyboardDeviceStruct((DeviceIntPtr) pKeyboard, &names,
+ workingKeySyms, workingModMap,
+ sunBell, sunKbdCtrl);
+ }
+#endif
+ break;
+
+ case DEVICE_ON:
+ pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate;
+ /*
+ * Set the keyboard into "direct" mode and turn on
+ * event translation.
+ */
+ if (sunChangeKbdTranslation(pPriv->fd,TRUE) == -1)
+ FatalError("Can't set keyboard translation\n");
+ AddEnabledDevice(pPriv->fd);
+ pKeyboard->on = TRUE;
+ break;
+
+ case DEVICE_CLOSE:
+ case DEVICE_OFF:
+ pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate;
+ if (pPriv->type == KB_SUN4) {
+ /* dumb bug in Sun's keyboard! Turn off LEDS before resetting */
+ pPriv->leds = 0;
+ ctrl->leds = 0;
+ SetLights(ctrl, pPriv->fd);
+ }
+ /*
+ * Restore original keyboard directness and translation.
+ */
+ if (sunChangeKbdTranslation(pPriv->fd,FALSE) == -1)
+ FatalError("Can't reset keyboard translation\n");
+ RemoveEnabledDevice(pPriv->fd);
+ pKeyboard->on = FALSE;
+ break;
+ default:
+ FatalError("Unknown keyboard operation\n");
+ }
+ return Success;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunKbdGetEvents --
+ * Return the events waiting in the wings for the given keyboard.
+ *
+ * Results:
+ * A pointer to an array of Firm_events or (Firm_event *)0 if no events
+ * The number of events contained in the array.
+ * A boolean as to whether more events might be available.
+ *
+ * Side Effects:
+ * None.
+ *-----------------------------------------------------------------------
+ */
+
+Firm_event* sunKbdGetEvents (
+ int fd,
+ Bool on,
+ int* pNumEvents,
+ Bool* pAgain)
+{
+ int nBytes; /* number of bytes of events available. */
+ static Firm_event evBuf[MAXEVENTS]; /* Buffer for Firm_events */
+
+ if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) {
+ if (errno == EWOULDBLOCK) {
+ *pNumEvents = 0;
+ *pAgain = FALSE;
+ } else {
+ Error ("Reading keyboard");
+ FatalError ("Could not read the keyboard");
+ }
+ } else {
+ if (on) {
+ *pNumEvents = nBytes / sizeof (Firm_event);
+ *pAgain = (nBytes == sizeof (evBuf));
+ } else {
+ *pNumEvents = 0;
+ *pAgain = FALSE;
+ }
+ }
+ return evBuf;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunKbdEnqueueEvent --
+ *
+ *-----------------------------------------------------------------------
+ */
+static xEvent autoRepeatEvent;
+static int composeCount;
+
+static Bool DoSpecialKeys(device, xE, fe)
+ DeviceIntPtr device;
+ xEvent* xE;
+ Firm_event* fe;
+{
+ int shift_index, map_index, bit;
+ KeySym ksym;
+ BYTE* kptr;
+ sunKbdPrivPtr pPriv = (sunKbdPrivPtr)device->public.devicePrivate;
+ BYTE keycode = xE->u.u.detail;
+ CARD8 keyModifiers = device->key->modifierMap[keycode];
+
+ /* look up the present idea of the keysym */
+ shift_index = 0;
+ if (device->key->state & ShiftMask)
+ shift_index ^= 1;
+ if (device->key->state & LockMask)
+ shift_index ^= 1;
+ map_index = (fe->id - 1) * device->key->curKeySyms.mapWidth;
+ ksym = device->key->curKeySyms.map[shift_index + map_index];
+ if (ksym == NoSymbol)
+ ksym = device->key->curKeySyms.map[map_index];
+
+ /*
+ * Toggle functionality is hardcoded. This is achieved by always
+ * discarding KeyReleases on these keys, and converting every other
+ * KeyPress into a KeyRelease.
+ */
+ if (xE->u.u.type == KeyRelease
+ && (ksym == XK_Num_Lock
+ || ksym == XK_Scroll_Lock
+ || ksym == SunXK_Compose
+ || (keyModifiers & LockMask)))
+ return TRUE;
+
+ kptr = &device->key->down[keycode >> 3];
+ bit = 1 << (keycode & 7);
+ if ((*kptr & bit) &&
+ (ksym == XK_Num_Lock || ksym == XK_Scroll_Lock ||
+ ksym == SunXK_Compose || (keyModifiers & LockMask)))
+ xE->u.u.type = KeyRelease;
+
+ if (pPriv->type == KB_SUN4) {
+ if (ksym == XK_Num_Lock) {
+ ModLight (device, xE->u.u.type == KeyPress, XLED_NUM_LOCK);
+ } else if (ksym == XK_Scroll_Lock) {
+ ModLight (device, xE->u.u.type == KeyPress, XLED_SCROLL_LOCK);
+ } else if (ksym == SunXK_Compose) {
+ ModLight (device, xE->u.u.type == KeyPress, XLED_COMPOSE);
+ if (xE->u.u.type == KeyPress) composeCount = 2;
+ else composeCount = 0;
+ } else if (keyModifiers & LockMask) {
+ ModLight (device, xE->u.u.type == KeyPress, XLED_CAPS_LOCK);
+ }
+ if (xE->u.u.type == KeyRelease) {
+ if (composeCount > 0 && --composeCount == 0) {
+ pseudoKey(device, FALSE,
+ LookupKeyCode(SunXK_Compose, &device->key->curKeySyms));
+ ModLight (device, FALSE, XLED_COMPOSE);
+ }
+ }
+ }
+
+ if ((xE->u.u.type == KeyPress) && (keyModifiers == 0)) {
+ /* initialize new AutoRepeater event & mark AutoRepeater on */
+ autoRepeatEvent = *xE;
+ autoRepeatFirst = TRUE;
+ autoRepeatKeyDown++;
+ autoRepeatLastKeyDownTv = fe->time;
+ }
+ return FALSE;
+}
+
+void sunKbdEnqueueEvent (
+ DeviceIntPtr device,
+ Firm_event *fe)
+{
+ xEvent xE;
+ BYTE keycode;
+ CARD8 keyModifiers;
+
+ keycode = (fe->id & 0x7f) + MIN_KEYCODE;
+
+ keyModifiers = device->key->modifierMap[keycode];
+#ifdef XKB
+ if (noXkbExtension) {
+#endif
+ if (autoRepeatKeyDown && (keyModifiers == 0) &&
+ ((fe->value == VKEY_DOWN) || (keycode == autoRepeatEvent.u.u.detail))) {
+ /*
+ * Kill AutoRepeater on any real non-modifier key down, or auto key up
+ */
+ autoRepeatKeyDown = 0;
+ }
+#ifdef XKB
+ }
+#endif
+ xE.u.keyButtonPointer.time = TVTOMILLI(fe->time);
+ xE.u.u.type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress);
+ xE.u.u.detail = keycode;
+#ifdef XKB
+ if (noXkbExtension) {
+#endif
+ if (DoSpecialKeys(device, &xE, fe))
+ return;
+#ifdef XKB
+ }
+#endif /* ! XKB */
+ mieqEnqueue (&xE);
+}
+
+void sunEnqueueAutoRepeat ()
+{
+ int delta;
+ int i, mask;
+ DeviceIntPtr device = (DeviceIntPtr)LookupKeyboardDevice();
+ KeybdCtrl* ctrl = &device->kbdfeed->ctrl;
+ sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate;
+
+ if (ctrl->autoRepeat != AutoRepeatModeOn) {
+ autoRepeatKeyDown = 0;
+ return;
+ }
+ i=(autoRepeatEvent.u.u.detail >> 3);
+ mask=(1 << (autoRepeatEvent.u.u.detail & 7));
+ if (!(ctrl->autoRepeats[i] & mask)) {
+ autoRepeatKeyDown = 0;
+ return;
+ }
+
+ /*
+ * Generate auto repeat event. XXX one for now.
+ * Update time & pointer location of saved KeyPress event.
+ */
+
+ delta = TVTOMILLI(autoRepeatDeltaTv);
+ autoRepeatFirst = FALSE;
+
+ /*
+ * Fake a key up event and a key down event
+ * for the last key pressed.
+ */
+ autoRepeatEvent.u.keyButtonPointer.time += delta;
+ autoRepeatEvent.u.u.type = KeyRelease;
+
+ /*
+ * hold off any more inputs while we get these safely queued up
+ * further SIGIO are
+ */
+ sunEnqueueEvent (&autoRepeatEvent);
+ autoRepeatEvent.u.u.type = KeyPress;
+ sunEnqueueEvent (&autoRepeatEvent);
+ if (ctrl->click) bell (pPriv->fd, 0);
+
+ /* Update time of last key down */
+ tvplus(autoRepeatLastKeyDownTv, autoRepeatLastKeyDownTv,
+ autoRepeatDeltaTv);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * sunChangeKbdTranslation
+ * Makes operating system calls to set keyboard translation
+ * and direction on or off.
+ *
+ * Results:
+ * -1 if failure, else 0.
+ *
+ * Side Effects:
+ * Changes kernel management of keyboard.
+ *
+ *-----------------------------------------------------------------------
+ */
+int sunChangeKbdTranslation(
+ int fd,
+ Bool makeTranslated)
+
+{
+ int tmp;
+#ifndef i386 /* { */
+ sigset_t hold_mask, old_mask;
+#else /* }{ */
+ int old_mask;
+#endif /* } */
+ int toread;
+ char junk[8192];
+
+#ifndef i386 /* { */
+ (void) sigfillset(&hold_mask);
+ (void) sigprocmask(SIG_BLOCK, &hold_mask, &old_mask);
+#else /* }{ */
+ old_mask = sigblock (~0);
+#endif /* } */
+ sunKbdWait();
+ if (makeTranslated) {
+ /*
+ * Next set the keyboard into "direct" mode and turn on
+ * event translation. If either of these fails, we can't go
+ * on.
+ */
+ tmp = 1;
+ if (ioctl (fd, KIOCSDIRECT, &tmp) == -1) {
+ Error ("Setting keyboard direct mode");
+ return -1;
+ }
+ tmp = TR_UNTRANS_EVENT;
+ if (ioctl (fd, KIOCTRANS, &tmp) == -1) {
+ Error ("Setting keyboard translation");
+ ErrorF ("sunChangeKbdTranslation: kbdFd=%d\n", fd);
+ return -1;
+ }
+ } else {
+ /*
+ * Next set the keyboard into "indirect" mode and turn off
+ * event translation.
+ */
+ tmp = 0;
+ (void)ioctl (fd, KIOCSDIRECT, &tmp);
+ tmp = TR_ASCII;
+ (void)ioctl (fd, KIOCTRANS, &tmp);
+ }
+ if (ioctl (fd, FIONREAD, &toread) != -1 && toread > 0) {
+ while (toread) {
+ tmp = toread;
+ if (toread > sizeof (junk))
+ tmp = sizeof (junk);
+ (void) read (fd, junk, tmp);
+ toread -= tmp;
+ }
+ }
+#ifndef i386 /* { */
+ (void) sigprocmask(SIG_SETMASK, &old_mask, (sigset_t *)NULL);
+#else /* }{ */
+ sigsetmask (old_mask);
+#endif /* } */
+ return 0;
+}
+
+/*ARGSUSED*/
+Bool LegalModifier(key, pDev)
+ unsigned int key;
+ DevicePtr pDev;
+{
+ return TRUE;
+}
+
+/*ARGSUSED*/
+void sunBlockHandler(nscreen, pbdata, pptv, pReadmask)
+ int nscreen;
+ pointer pbdata;
+ struct timeval **pptv;
+ pointer pReadmask;
+{
+ KeybdCtrl* ctrl = &((DeviceIntPtr)LookupKeyboardDevice())->kbdfeed->ctrl;
+ static struct timeval artv = { 0, 0 }; /* autorepeat timeval */
+
+ if (!autoRepeatKeyDown)
+ return;
+
+ if (ctrl->autoRepeat != AutoRepeatModeOn)
+ return;
+
+ if (autoRepeatFirst == TRUE)
+ artv.tv_usec = sunAutoRepeatInitiate;
+ else
+ artv.tv_usec = sunAutoRepeatDelay;
+ *pptv = &artv;
+
+}
+
+/*ARGSUSED*/
+void sunWakeupHandler(nscreen, pbdata, err, pReadmask)
+ int nscreen;
+ pointer pbdata;
+ unsigned long err;
+ pointer pReadmask;
+{
+ KeybdCtrl* ctrl = &((DeviceIntPtr)LookupKeyboardDevice())->kbdfeed->ctrl;
+ struct timeval tv;
+
+ if (ctrl->autoRepeat != AutoRepeatModeOn)
+ return;
+
+ if (autoRepeatKeyDown) {
+ X_GETTIMEOFDAY(&tv);
+ tvminus(autoRepeatDeltaTv, tv, autoRepeatLastKeyDownTv);
+ if (autoRepeatDeltaTv.tv_sec > 0 ||
+ (!autoRepeatFirst && autoRepeatDeltaTv.tv_usec >
+ sunAutoRepeatDelay) ||
+ (autoRepeatDeltaTv.tv_usec >
+ sunAutoRepeatInitiate))
+ autoRepeatReady++;
+ }
+
+ if (autoRepeatReady)
+ {
+ sunEnqueueAutoRepeat ();
+ autoRepeatReady = 0;
+ }
+}