aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c')
-rw-r--r--nx-X11/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c662
1 files changed, 662 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c
new file mode 100644
index 000000000..0a39155f4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c
@@ -0,0 +1,662 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c,v 1.1 2001/05/28 02:42:31 tsi Exp $ */
+/*
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+ * Copyright 1993 by David Dawes <dawes@XFree86.org>
+ * Copyright 1999 by David Holland <davidh@iquest.net)
+ *
+ * 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 Thomas Roell, David Dawes, and David Holland not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Thomas Roell, David Dawes, and
+ * David Holland make no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THOMAS ROELL, DAVID DAWES, AND DAVID HOLLAND DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THOMAS ROELL, DAVID DAWES, OR DAVID HOLLAND
+ * 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 2004-2005 Sun Microsystems, Inc. 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 the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * 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 NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ */
+/* $XdotOrg: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_kbd.c,v 1.7 2005/08/30 22:34:14 alanc Exp $ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#include "xf86OSKbd.h"
+#include "sun_kbd.h"
+
+/* Define to provide support for using /dev/audio to ring the bell instead of
+ the keyboard beeper */
+#define AUDIO_BELL
+
+#ifdef AUDIO_BELL
+#include <sys/audio.h>
+#include <sys/uio.h>
+#include <limits.h>
+#include <math.h>
+#include <poll.h>
+#endif
+
+/***************************************************************************
+ * Common implementation of routines shared by "keyboard" driver in sun_io.c
+ * and "kbd" driver (later on in this file)
+ */
+
+#include <sys/stropts.h>
+#include <sys/vuid_event.h>
+#include <sys/kbd.h>
+
+_X_HIDDEN int
+sunKbdOpen(const char *devName, pointer options)
+{
+ int kbdFD;
+ const char *kbdPath = NULL;
+ const char *defaultKbd = "/dev/kbd";
+
+ if (options != NULL) {
+ kbdPath = xf86SetStrOption(options, "Device", NULL);
+ }
+ if (kbdPath == NULL) {
+ kbdPath = defaultKbd;
+ }
+
+ kbdFD = open(kbdPath, O_RDONLY | O_NONBLOCK);
+
+ if (kbdFD == -1) {
+ xf86Msg(X_ERROR, "%s: cannot open \"%s\"\n", devName, kbdPath);
+ } else {
+ xf86MsgVerb(X_INFO, 3, "%s: Opened device \"%s\"\n", devName, kbdPath);
+ }
+
+ if ((kbdPath != NULL) && (kbdPath != defaultKbd)) {
+ xfree(kbdPath);
+ }
+ return kbdFD;
+}
+
+
+/*
+ * Save initial keyboard state. This is called at the start of each server
+ * generation.
+ */
+
+_X_HIDDEN int
+sunKbdInit(sunKbdPrivPtr priv, int kbdFD, const char *devName, pointer options)
+{
+ int ktype, klayout, i;
+ const char *ktype_name;
+
+ priv->kbdFD = kbdFD;
+ priv->devName = devName;
+ priv->otranslation = -1;
+ priv->odirect = -1;
+
+ if (options != NULL) {
+ priv->strmod = xf86SetStrOption(options, "StreamsModule", NULL);
+ priv->audioDevName = xf86SetStrOption(options, "BellDevice", NULL);
+
+ if (priv->audioDevName && (priv->audioDevName[0] == '\0')) {
+ xfree(priv->audioDevName);
+ priv->audioDevName = NULL;
+ }
+ } else {
+ priv->strmod = NULL;
+ priv->audioDevName = NULL;
+ }
+
+ if (priv->strmod) {
+ SYSCALL(i = ioctl(priv->kbdFD, I_PUSH, priv->strmod));
+ if (i < 0) {
+ xf86Msg(X_ERROR,
+ "%s: cannot push module '%s' onto keyboard device: %s\n",
+ priv->devName, priv->strmod, strerror(errno));
+ }
+ }
+
+ SYSCALL(i = ioctl(kbdFD, KIOCTYPE, &ktype));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Unable to determine keyboard type: %s\n",
+ devName, strerror(errno));
+ return BadImplementation;
+ }
+
+ SYSCALL(i = ioctl(kbdFD, KIOCLAYOUT, &klayout));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Unable to determine keyboard layout: %s\n",
+ devName, strerror(errno));
+ return BadImplementation;
+ }
+
+ switch (ktype) {
+ case KB_SUN3:
+ ktype_name = "Sun Type 3"; break;
+ case KB_SUN4:
+ ktype_name = "Sun Type 4/5/6"; break;
+ case KB_USB:
+ ktype_name = "USB"; break;
+ case KB_PC:
+ ktype_name = "PC"; break;
+ default:
+ ktype_name = "Unknown"; break;
+ }
+
+ xf86Msg(X_PROBED, "%s: Keyboard type: %s (%d)\n",
+ devName, ktype_name, ktype);
+ xf86Msg(X_PROBED, "%s: Keyboard layout: %d\n", devName, klayout);
+
+ priv->ktype = ktype;
+ priv->keyMap = sunGetKbdMapping(ktype);
+ priv->audioState = AB_INITIALIZING;
+ priv->oleds = sunKbdGetLeds(priv);
+
+ return Success;
+}
+
+_X_HIDDEN int
+sunKbdOn(sunKbdPrivPtr priv)
+{
+ int ktrans, kdirect, i;
+
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCGDIRECT, &kdirect));
+ if (i < 0) {
+ xf86Msg(X_ERROR,
+ "%s: Unable to determine keyboard direct setting: %s\n",
+ priv->devName, strerror(errno));
+ return BadImplementation;
+ }
+
+ priv->odirect = kdirect;
+ kdirect = 1;
+
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCSDIRECT, &kdirect));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Failed turning keyboard direct mode on: %s\n",
+ priv->devName, strerror(errno));
+ return BadImplementation;
+ }
+
+ /* Setup translation */
+
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCGTRANS, &ktrans));
+ if (i < 0) {
+ xf86Msg(X_ERROR,
+ "%s: Unable to determine keyboard translation mode: %s\n",
+ priv->devName, strerror(errno));
+ return BadImplementation;
+ }
+
+ priv->otranslation = ktrans;
+ ktrans = TR_UNTRANS_EVENT;
+
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCTRANS, &ktrans));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Failed setting keyboard translation mode: %s\n",
+ priv->devName, strerror(errno));
+ return BadImplementation;
+ }
+
+ return Success;
+}
+
+_X_HIDDEN int
+sunKbdOff(sunKbdPrivPtr priv)
+{
+ int i;
+
+ /* restore original state */
+
+ sunKbdSetLeds(priv, priv->oleds);
+
+ if (priv->otranslation != -1) {
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCTRANS, &priv->otranslation));
+ if (i < 0) {
+ xf86Msg(X_ERROR,
+ "%s: Unable to restore keyboard translation mode: %s\n",
+ priv->devName, strerror(errno));
+ return BadImplementation;
+ }
+ priv->otranslation = -1;
+ }
+
+ if (priv->odirect != -1) {
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCSDIRECT, &priv->odirect));
+ if (i < 0) {
+ xf86Msg(X_ERROR,
+ "%s: Unable to restore keyboard direct setting: %s\n",
+ priv->devName, strerror(errno));
+ return BadImplementation;
+ }
+ priv->odirect = -1;
+ }
+
+ if (priv->strmod) {
+ SYSCALL(i = ioctl(priv->kbdFD, I_POP, priv->strmod));
+ if (i < 0) {
+ xf86Msg(X_WARNING,
+ "%s: cannot pop module '%s' off keyboard device: %s\n",
+ priv->devName, priv->strmod, strerror(errno));
+ }
+ }
+
+ return Success;
+}
+
+#ifdef AUDIO_BELL
+
+/* Helper function to ring bell via audio device instead of keyboard beeper */
+
+#define BELL_RATE 48000 /* Samples per second */
+#define BELL_HZ 50 /* Fraction of a second i.e. 1/x */
+#define BELL_MS (1000/BELL_HZ) /* MS */
+#define BELL_SAMPLES (BELL_RATE / BELL_HZ)
+#define BELL_MIN 3 /* Min # of repeats */
+
+static int
+sunKbdAudioBell(sunKbdPrivPtr priv, int loudness, int pitch, int duration)
+{
+ static short samples[BELL_SAMPLES];
+ static short silence[BELL_SAMPLES]; /* "The Sound of Silence" */
+ static int lastFreq;
+ int cnt;
+ int i;
+ int written;
+ int repeats;
+ int freq;
+ audio_info_t audioInfo;
+ struct iovec iov[IOV_MAX];
+ int iovcnt;
+ double ampl, cyclen, phase;
+ int audioFD;
+
+ if ((loudness <= 0) || (pitch <= 0) || (duration <= 0)) {
+ return 0;
+ }
+
+ if ((priv == NULL) || (priv->audioDevName == NULL)) {
+ return -1;
+ }
+
+ if (priv->audioState == AB_INITIALIZING) {
+ priv->audioState = AB_NORMAL;
+ lastFreq = 0;
+ bzero(silence, sizeof(silence));
+ }
+
+ audioFD = open(priv->audioDevName, O_WRONLY | O_NONBLOCK);
+ if (audioFD == -1) {
+ xf86Msg(X_ERROR, "%s: cannot open audio device \"%s\": %s\n",
+ priv->devName, priv->audioDevName, strerror(errno));
+ return -1;
+ }
+
+ freq = pitch;
+ freq = min(freq, (BELL_RATE / 2) - 1);
+ freq = max(freq, 2 * BELL_HZ);
+
+ /*
+ * Ensure full waves per buffer
+ */
+ freq -= freq % BELL_HZ;
+
+ if (freq != lastFreq) {
+ lastFreq = freq;
+ ampl = 16384.0;
+
+ cyclen = (double) freq / (double) BELL_RATE;
+ phase = 0.0;
+
+ for (i = 0; i < BELL_SAMPLES; i++) {
+ samples[i] = (short) (ampl * sin(2.0 * M_PI * phase));
+ phase += cyclen;
+ if (phase >= 1.0)
+ phase -= 1.0;
+ }
+ }
+
+ repeats = (duration + (BELL_MS / 2)) / BELL_MS;
+ repeats = max(repeats, BELL_MIN);
+
+ loudness = max(0, loudness);
+ loudness = min(loudness, 100);
+
+#ifdef DEBUG
+ ErrorF("BELL : freq %d volume %d duration %d repeats %d\n",
+ freq, loudness, duration, repeats);
+#endif
+
+ AUDIO_INITINFO(&audioInfo);
+ audioInfo.play.encoding = AUDIO_ENCODING_LINEAR;
+ audioInfo.play.sample_rate = BELL_RATE;
+ audioInfo.play.channels = 2;
+ audioInfo.play.precision = 16;
+ audioInfo.play.gain = min(AUDIO_MAX_GAIN, AUDIO_MAX_GAIN * loudness / 100);
+
+ if (ioctl(audioFD, AUDIO_SETINFO, &audioInfo) < 0){
+ xf86Msg(X_ERROR,
+ "%s: AUDIO_SETINFO failed on audio device \"%s\": %s\n",
+ priv->devName, priv->audioDevName, strerror(errno));
+ close(audioFD);
+ return -1;
+ }
+
+ iovcnt = 0;
+
+ for (cnt = 0; cnt <= repeats; cnt++) {
+ iov[iovcnt].iov_base = (char *) samples;
+ iov[iovcnt++].iov_len = sizeof(samples);
+ if (cnt == repeats) {
+ /* Insert a bit of silence so that multiple beeps are distinct and
+ * not compressed into a single tone.
+ */
+ iov[iovcnt].iov_base = (char *) silence;
+ iov[iovcnt++].iov_len = sizeof(silence);
+ }
+ if ((iovcnt >= IOV_MAX) || (cnt == repeats)) {
+ written = writev(audioFD, iov, iovcnt);
+
+ if ((written < ((int)(sizeof(samples) * iovcnt)))) {
+ /* audio buffer was full! */
+
+ int naptime;
+
+ if (written == -1) {
+ if (errno != EAGAIN) {
+ xf86Msg(X_ERROR,
+ "%s: writev failed on audio device \"%s\": %s\n",
+ priv->devName, priv->audioDevName,
+ strerror(errno));
+ close(audioFD);
+ return -1;
+ }
+ i = iovcnt;
+ } else {
+ i = ((sizeof(samples) * iovcnt) - written)
+ / sizeof(samples);
+ }
+ cnt -= i;
+
+ /* sleep a little to allow audio buffer to drain */
+ naptime = BELL_MS * i;
+ poll(NULL, 0, naptime);
+
+ i = ((sizeof(samples) * iovcnt) - written) % sizeof(samples);
+ iovcnt = 0;
+ if ((written != -1) && (i > 0)) {
+ iov[iovcnt].iov_base = ((char *) samples) + i;
+ iov[iovcnt++].iov_len = sizeof(samples) - i;
+ }
+ } else {
+ iovcnt = 0;
+ }
+ }
+ }
+
+ close(audioFD);
+ return 0;
+}
+
+#endif /* AUDIO_BELL */
+
+_X_HIDDEN void
+sunKbdSoundBell(sunKbdPrivPtr priv, int loudness, int pitch, int duration)
+{
+ int kbdCmd, i;
+
+ if (loudness && pitch)
+ {
+#ifdef AUDIO_BELL
+ if (priv->audioDevName != NULL) {
+ if (sunKbdAudioBell(priv, loudness, pitch, duration) == 0) {
+ return;
+ }
+ }
+#endif
+
+ kbdCmd = KBD_CMD_BELL;
+
+ SYSCALL(i = ioctl (priv->kbdFD, KIOCCMD, &kbdCmd));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Failed to activate bell: %s\n",
+ priv->devName, strerror(errno));
+ }
+
+ usleep(duration * loudness * 20);
+
+ kbdCmd = KBD_CMD_NOBELL;
+ SYSCALL(i = ioctl (priv->kbdFD, KIOCCMD, &kbdCmd));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Failed to deactivate bell: %s\n",
+ priv->devName, strerror(errno));
+ }
+ }
+}
+
+_X_HIDDEN void
+sunKbdSetLeds(sunKbdPrivPtr priv, int leds)
+{
+ int i;
+
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCSLED, &leds));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Failed to set keyboard LED's: %s\n",
+ priv->devName, strerror(errno));
+ }
+}
+
+_X_HIDDEN int
+sunKbdGetLeds(sunKbdPrivPtr priv)
+{
+ int i, leds = 0;
+
+ SYSCALL(i = ioctl(priv->kbdFD, KIOCGLED, &leds));
+ if (i < 0) {
+ xf86Msg(X_ERROR, "%s: Failed to get keyboard LED's: %s\n",
+ priv->devName, strerror(errno));
+ }
+ return leds;
+}
+
+/* ARGSUSED0 */
+_X_HIDDEN void
+sunKbdSetRepeat(sunKbdPrivPtr priv, char rad)
+{
+ /* Nothing to do */
+}
+
+/***************************************************************************
+ * Routines called from "kbd" driver via proc vectors filled in by
+ * xf86OSKbdPreInit().
+ */
+
+
+static int
+KbdInit(InputInfoPtr pInfo, int what)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+
+ return sunKbdInit(priv, pInfo->fd, pInfo->name, pInfo->options);
+}
+
+
+static int
+KbdOn(InputInfoPtr pInfo, int what)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+
+ return sunKbdOn(priv);
+}
+
+static int
+KbdOff(InputInfoPtr pInfo, int what)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+
+ return sunKbdOff(priv);
+}
+
+
+static void
+SoundKbdBell(InputInfoPtr pInfo, int loudness, int pitch, int duration)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+
+ sunKbdSoundBell(priv, loudness, pitch, duration);
+}
+
+static void
+SetKbdLeds(InputInfoPtr pInfo, int leds)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+ int real_leds = sunKbdGetLeds(priv);
+
+ real_leds &= ~(LED_CAPS_LOCK | LED_NUM_LOCK | LED_SCROLL_LOCK | LED_COMPOSE);
+
+ if (leds & XLED1) real_leds |= LED_CAPS_LOCK;
+ if (leds & XLED2) real_leds |= LED_NUM_LOCK;
+ if (leds & XLED3) real_leds |= LED_SCROLL_LOCK;
+ if (leds & XLED4) real_leds |= LED_COMPOSE;
+
+ sunKbdSetLeds(priv, real_leds);
+}
+
+static int
+GetKbdLeds(InputInfoPtr pInfo)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+ int leds = 0;
+ int real_leds = sunKbdGetLeds(priv);
+
+ if (real_leds & LED_CAPS_LOCK) leds |= XLED1;
+ if (real_leds & LED_NUM_LOCK) leds |= XLED2;
+ if (real_leds & LED_SCROLL_LOCK) leds |= XLED3;
+ if (real_leds & LED_COMPOSE) leds |= XLED4;
+
+ return leds;
+}
+
+static void
+SetKbdRepeat(InputInfoPtr pInfo, char rad)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+
+ sunKbdSetRepeat(priv, rad);
+}
+
+static void
+KbdGetMapping (InputInfoPtr pInfo, KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+ /* Should probably do something better here */
+ xf86KbdGetMapping(pKeySyms, pModMap);
+}
+
+static void
+ReadInput(InputInfoPtr pInfo)
+{
+ KbdDevPtr pKbd = (KbdDevPtr) pInfo->private;
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+ Firm_event event[64];
+ int nBytes, i;
+
+ /* I certainly hope its not possible to read partial events */
+
+ if ((nBytes = read(pInfo->fd, (char *)event, sizeof(event))) > 0)
+ {
+ for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) {
+ pKbd->PostEvent(pInfo, priv->keyMap[event[i].id],
+ event[i].value == VKEY_DOWN ? TRUE : FALSE);
+ }
+ }
+}
+
+static Bool
+OpenKeyboard(InputInfoPtr pInfo)
+{
+ pInfo->fd = sunKbdOpen(pInfo->name, pInfo->options);
+
+ if (pInfo->fd >= 0) {
+ pInfo->read_input = ReadInput;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+_X_EXPORT Bool
+xf86OSKbdPreInit(InputInfoPtr pInfo)
+{
+ KbdDevPtr pKbd = pInfo->private;
+
+ pKbd->KbdInit = KbdInit;
+ pKbd->KbdOn = KbdOn;
+ pKbd->KbdOff = KbdOff;
+ pKbd->Bell = SoundKbdBell;
+ pKbd->SetLeds = SetKbdLeds;
+ pKbd->GetLeds = GetKbdLeds;
+ pKbd->SetKbdRepeat = SetKbdRepeat;
+ pKbd->KbdGetMapping = KbdGetMapping;
+
+ pKbd->RemapScanCode = NULL;
+ pKbd->GetSpecialKey = NULL;
+ pKbd->SpecialKey = NULL;
+
+ pKbd->OpenKeyboard = OpenKeyboard;
+
+ pKbd->vtSwitchSupported = FALSE;
+ pKbd->CustomKeycodes = FALSE;
+
+ pKbd->private = xcalloc(sizeof(sunKbdPrivRec), 1);
+ if (pKbd->private == NULL) {
+ xf86Msg(X_ERROR,"can't allocate keyboard OS private data\n");
+ return FALSE;
+ } else {
+ sunKbdPrivPtr priv = (sunKbdPrivPtr) pKbd->private;
+ priv->otranslation = -1;
+ priv->odirect = -1;
+ }
+
+ return TRUE;
+}