diff options
author | Alan Coopersmith <Alan.Coopersmith@sun.com> | 2005-08-13 00:11:28 +0000 |
---|---|---|
committer | Alan Coopersmith <Alan.Coopersmith@sun.com> | 2005-08-13 00:11:28 +0000 |
commit | c29051f9d108fe49c23d9cf36fd08cc64c87262a (patch) | |
tree | c52152835d5e076088d20181445c31db42013d79 | |
parent | 616a65c4cc528278168db1414776f3a867cd463e (diff) |
Add LintTarget()
Bugzilla #1068 <https://bugs.freedesktop.org/show_bug.cgi?id=1068> Port
Solaris keyboard code to work with kbd driver.
Also incorporated "audio bell" feature from Xsun keyboard DDX to play bell
tones via /dev/audio (specified via Option "BellDevice" "/dev/audio" in
keyboard device options).
-rw-r--r-- | hw/xfree86/os-support/solaris/sun_io.c | 136 | ||||
-rw-r--r-- | hw/xfree86/os-support/solaris/sun_kbd.c | 662 | ||||
-rw-r--r-- | hw/xfree86/os-support/solaris/sun_kbd.h | 71 | ||||
-rw-r--r-- | hw/xfree86/os-support/solaris/sun_kbdEv.c | 38 |
4 files changed, 792 insertions, 115 deletions
diff --git a/hw/xfree86/os-support/solaris/sun_io.c b/hw/xfree86/os-support/solaris/sun_io.c index c4dc23669..96344033f 100644 --- a/hw/xfree86/os-support/solaris/sun_io.c +++ b/hw/xfree86/os-support/solaris/sun_io.c @@ -1,4 +1,5 @@ /* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sunos/sun_io.c,v 1.2 2002/10/11 01:40:37 dawes Exp $ */ +/* $XdotOrg: $ */ /* * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany * Copyright 1993 by David Dawes <dawes@xfree86.org> @@ -23,6 +24,35 @@ * PERFORMANCE OF THIS SOFTWARE. * */ +/* Copyright 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. + */ + +/* Solaris support routines for builtin "keyboard" driver */ #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> @@ -30,39 +60,101 @@ #include "xf86Priv.h" #include "xf86_OSlib.h" +#include "sun_kbd.h" -void -xf86SoundKbdBell(int loudness, int pitch, int duration) -{ - int kbdCmd; +static sunKbdPrivRec sunKeyboardPriv; - if (loudness && pitch) - { - kbdCmd = KBD_CMD_BELL; - if (ioctl (xf86Info.kbdFd, KIOCCMD, &kbdCmd) == -1) { - ErrorF("Failed to activate bell\n"); - return; - } +_X_HIDDEN void +xf86KbdInit(void) +{ + const char *kbdName = "keyboard"; + pointer *kbdOptions = NULL; + IDevPtr pDev; - usleep(xf86Info.bell_duration * loudness * 20); + /* There should be a better way to find the keyboard device name, but + this seems to work for now. */ + for (pDev = xf86ConfigLayout.inputs; pDev && pDev->identifier; pDev++) { + if (!xf86NameCmp(pDev->driver, "keyboard")) { + kbdName = pDev->identifier; + kbdOptions = pDev->commonOptions; + break; + } + } - kbdCmd = KBD_CMD_NOBELL; - if (ioctl (xf86Info.kbdFd, KIOCCMD, &kbdCmd) == -1) - ErrorF ("Failed to deactivate bell\n"); + if (xf86Info.kbdFd < 0) { + xf86Info.kbdFd = sunKbdOpen(kbdName, kbdOptions); + if (xf86Info.kbdFd < 0) { + FatalError("Unable to open keyboard: /dev/kbd\n"); } + } + + memset(&sunKeyboardPriv, 0, sizeof(sunKbdPrivRec)); + if (sunKbdInit(&sunKeyboardPriv, xf86Info.kbdFd, + kbdName, kbdOptions) != Success) { + FatalError("Unable to initialize keyboard driver\n"); + } } -void +_X_HIDDEN int +xf86KbdOn(void) +{ + if (sunKbdOn(&sunKeyboardPriv) != Success) { + FatalError("Enabling keyboard"); + } + + return xf86Info.kbdFd; +} + +_X_HIDDEN int +xf86KbdOff(void) +{ + if (sunKbdOff(&sunKeyboardPriv) != Success) { + FatalError("Disabling keyboard"); + } + + return xf86Info.kbdFd; +} + +_X_EXPORT void +xf86SoundKbdBell(int loudness, int pitch, int duration) +{ + sunKbdSoundBell(&sunKeyboardPriv, loudness, pitch, duration); +} + +_X_HIDDEN void xf86SetKbdLeds(int leds) { - if( ioctl(xf86Info.kbdFd, KIOCSLED, &leds) < 0 ) - ErrorF("Failed to set Keyboard LED's\n"); + sunKbdSetLeds(&sunKeyboardPriv, leds); +} + +_X_HIDDEN int +xf86GetKbdLeds(void) +{ + return sunKbdGetLeds(&sunKeyboardPriv); } -#include "xf86OSKbd.h" +_X_HIDDEN void +xf86SetKbdRepeat(char rad) +{ + sunKbdSetRepeat(&sunKeyboardPriv, rad); +} -Bool -xf86OSKbdPreInit(InputInfoPtr pInfo) +/* + * Lets try reading more than one keyboard event at a time in the hopes that + * this will be slightly more efficient. Or we could just try the MicroSoft + * method, and forget about efficiency. :-) + */ +_X_HIDDEN void +xf86KbdEvents(void) { - return FALSE; + Firm_event event[64]; + int nBytes, i; + + /* I certainly hope its not possible to read partial events */ + + if ((nBytes = read(xf86Info.kbdFd, (char *)event, sizeof(event))) > 0) + { + for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) + sunPostKbdEvent(sunKeyboardPriv.ktype, &event[i]); + } } diff --git a/hw/xfree86/os-support/solaris/sun_kbd.c b/hw/xfree86/os-support/solaris/sun_kbd.c index 35d3a7731..ac8e46bb4 100644 --- a/hw/xfree86/os-support/solaris/sun_kbd.c +++ b/hw/xfree86/os-support/solaris/sun_kbd.c @@ -23,6 +23,33 @@ * 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.3 2004/06/13 04:50:21 alanc Exp $ */ #ifdef HAVE_XORG_CONFIG_H @@ -32,104 +59,599 @@ #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" +#include "xf86OSKbd.h" +#include "sun_kbd.h" -static int sun_otranslation = -1; -static int sun_odirect = -1; -int sun_ktype; +/* Define to provide support for using /dev/audio to ring the bell instead of + the keyboard beeper */ +#define AUDIO_BELL -int -xf86GetKbdLeds() -{ - int leds; +#ifdef AUDIO_BELL +#include <sys/audio.h> +#include <sys/uio.h> +#include <limits.h> +#include <math.h> +#include <poll.h> +#endif - ioctl(xf86Info.kbdFd, KIOCGLED, &leds); - return leds; -} +/*************************************************************************** + * Common implementation of routines shared by "keyboard" driver in sun_io.c + * and "kbd" driver (later on in this file) + */ -void -xf86SetKbdRepeat(char rad) +#include <sys/stropts.h> +#include <sys/vuid_event.h> +#include <sys/kbd.h> + +_X_HIDDEN int +sunKbdOpen(const char *devName, pointer options) { - /* Nothing to do */ + 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 { + xf86Msg(X_INFO, "%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. */ -void -xf86KbdInit() +_X_HIDDEN int +sunKbdInit(sunKbdPrivPtr priv, int kbdFD, const char *devName, pointer options) { - int klayout; - const char *ktype_name; + int ktype, klayout, i; + const char *ktype_name; + + priv->kbdFD = kbdFD; + priv->devName = devName; + priv->otranslation = -1; + priv->odirect = -1; + + 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; + } - if (xf86Info.kbdFd < 0) { - xf86Info.kbdFd = open("/dev/kbd", O_RDWR|O_NONBLOCK); - if(xf86Info.kbdFd < 0) - FatalError("Unable to open keyboard: /dev/kbd\n"); + 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; + + 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; + } + + return Success; +} + +_X_HIDDEN int +sunKbdOn(sunKbdPrivPtr priv) +{ + int ktrans, kdirect, i; + + 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(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; + + 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; + } - /* - * None of the following should ever fail. If it does, something is - * broken (IMO) - DWH 8/21/99 - */ - - if (ioctl(xf86Info.kbdFd, KIOCTYPE, &sun_ktype) < 0) - FatalError("Unable to determine keyboard type: %d\n", errno); - - if (ioctl(xf86Info.kbdFd, KIOCLAYOUT, &klayout) < 0) - FatalError("Unable to determine keyboard layout: %d\n", errno); - - if (ioctl(xf86Info.kbdFd, KIOCGTRANS, &sun_otranslation) < 0) - FatalError("Unable to determine keyboard translation mode\n"); - - if (ioctl(xf86Info.kbdFd, KIOCGDIRECT, &sun_odirect) < 0) - FatalError("Unable to determine keyboard direct setting\n"); - - switch (sun_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; + 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; } - xf86Msg(X_PROBED, "Keyboard type: %s (%d)\n", ktype_name, sun_ktype); - xf86Msg(X_PROBED, "Keyboard layout: %d\n", klayout); + 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; } -int -xf86KbdOn(void) +#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) { - int tmp = 1; + 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); - if (ioctl(xf86Info.kbdFd, KIOCSDIRECT, &tmp) == -1) - FatalError("Setting keyboard direct mode on\n"); + loudness = max(0, loudness); + loudness = min(loudness, 100); - /* Setup translation */ +#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! */ - tmp = TR_UNTRANS_EVENT; + int naptime; - if (ioctl(xf86Info.kbdFd, KIOCTRANS, &tmp) == -1) - FatalError("Setting keyboard translation\n"); + 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); - return xf86Info.kbdFd; + 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; } -int -xf86KbdOff() +#endif /* AUDIO_BELL */ + +_X_HIDDEN void +sunKbdSoundBell(sunKbdPrivPtr priv, int loudness, int pitch, int duration) { - if ((sun_otranslation != -1) && - (ioctl(xf86Info.kbdFd, KIOCTRANS, &sun_otranslation) < 0)) - FatalError("Unable to restore keyboard translation mode\n"); + 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; + + 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; - if ((sun_odirect != 0) && - (ioctl(xf86Info.kbdFd, KIOCSDIRECT, &sun_odirect) < 0 )) - FatalError("Unable to restore keyboard direct setting\n"); + 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 xf86Info.kbdFd; + return TRUE; } diff --git a/hw/xfree86/os-support/solaris/sun_kbd.h b/hw/xfree86/os-support/solaris/sun_kbd.h new file mode 100644 index 000000000..17979e1d4 --- /dev/null +++ b/hw/xfree86/os-support/solaris/sun_kbd.h @@ -0,0 +1,71 @@ +/* Copyright 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. + */ + +#ifndef _XORG_SUN_KBD_H_ +#define _XORG_SUN_KBD_H_ + +/* + * Keyboard common implementation routines shared by "keyboard" driver + * in sun_io.c and "kbd" driver in sun_kbd.c + */ + +typedef struct { + int kbdFD; + const char * devName; + int ktype; /* Keyboard type from KIOCTYPE */ + Bool kbdActive; /* Have we set kbd modes for X? */ + int otranslation; /* Original translation mode */ + int odirect; /* Original "direct" mode setting */ + const char * strmod; /* Streams module pushed on kbd device */ + const char * audioDevName; /* Audio device path to use for bell + or NULL to use keyboard beeper */ + enum {AB_INITIALIZING, AB_NORMAL} audioState; + const unsigned char *keyMap; +} sunKbdPrivRec, *sunKbdPrivPtr; + +/* sun_kbd.c */ +extern int sunKbdOpen (const char *devName, pointer options); +extern int sunKbdInit (sunKbdPrivPtr priv, int kbdFD, + const char *devName, pointer options); +extern int sunKbdOn (sunKbdPrivPtr priv); +extern int sunKbdOff (sunKbdPrivPtr priv); + +extern void sunKbdSoundBell (sunKbdPrivPtr priv, + int loudness, int pitch, int duration); + +extern void sunKbdSetLeds (sunKbdPrivPtr priv, int leds); +extern int sunKbdGetLeds (sunKbdPrivPtr priv); +extern void sunKbdSetRepeat (sunKbdPrivPtr priv, char rad); + +/* sun_kbdEv.c */ +#include <sys/vuid_event.h> +extern void sunPostKbdEvent (int ktype, Firm_event *event); + +extern const unsigned char *sunGetKbdMapping(int ktype); + +#endif diff --git a/hw/xfree86/os-support/solaris/sun_kbdEv.c b/hw/xfree86/os-support/solaris/sun_kbdEv.c index 620b18d18..13fe902d0 100644 --- a/hw/xfree86/os-support/solaris/sun_kbdEv.c +++ b/hw/xfree86/os-support/solaris/sun_kbdEv.c @@ -32,6 +32,7 @@ #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" +#include "sun_kbd.h" #ifdef XINPUT #include <X11/extensions/XI.h> @@ -45,12 +46,9 @@ #include "dgaproc.h" #endif -#include <sys/vuid_event.h> #include <sys/kbd.h> #include "atKeynames.h" -extern int sun_ktype; - #ifdef XKB extern Bool noXkbExtension; #endif @@ -629,6 +627,18 @@ static unsigned char usbmap[256] = { }; #endif /* KB_USB */ + +_X_HIDDEN const unsigned char * +sunGetKbdMapping(int ktype) { +#if defined(KB_USB) + if (ktype == KB_USB) + return usbmap; + else +#endif + return map; +} + + /* * sunPostKbdEvent -- * Translate the raw hardware Firm_event into an XEvent, and tell DIX @@ -638,8 +648,8 @@ static unsigned char usbmap[256] = { * interests of simplicity - DWH 8/30/99 */ -static void -sunPostKbdEvent(Firm_event *event) +_X_HIDDEN void +sunPostKbdEvent(int sun_ktype, Firm_event *event) { Bool down; KeyClassRec *keyc = ((DeviceIntPtr)xf86Info.pKeyboard)->key; @@ -873,25 +883,7 @@ sunPostKbdEvent(Firm_event *event) ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD); } -/* - * Lets try reading more than one keyboard event at a time in the hopes that - * this will be slightly more efficient. Or we could just try the MicroSoft - * method, and forget about efficiency. :-) - */ -void -xf86KbdEvents() -{ - Firm_event event[64]; - int nBytes, i; - /* I certainly hope its not possible to read partial events */ - - if ((nBytes = read(xf86Info.kbdFd, (char *)event, sizeof(event))) > 0) - { - for (i = 0; i < (nBytes / sizeof(Firm_event)); i++) - sunPostKbdEvent(&event[i]); - } -} /* * Autorepeat stuff |