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).
This commit is contained in:
parent
616a65c4cc
commit
c29051f9d1
|
@ -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
|
||||
static sunKbdPrivRec sunKeyboardPriv;
|
||||
|
||||
_X_HIDDEN void
|
||||
xf86KbdInit(void)
|
||||
{
|
||||
const char *kbdName = "keyboard";
|
||||
pointer *kbdOptions = NULL;
|
||||
IDevPtr pDev;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
_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)
|
||||
{
|
||||
int kbdCmd;
|
||||
|
||||
if (loudness && pitch)
|
||||
{
|
||||
kbdCmd = KBD_CMD_BELL;
|
||||
if (ioctl (xf86Info.kbdFd, KIOCCMD, &kbdCmd) == -1) {
|
||||
ErrorF("Failed to activate bell\n");
|
||||
return;
|
||||
}
|
||||
|
||||
usleep(xf86Info.bell_duration * loudness * 20);
|
||||
|
||||
kbdCmd = KBD_CMD_NOBELL;
|
||||
if (ioctl (xf86Info.kbdFd, KIOCCMD, &kbdCmd) == -1)
|
||||
ErrorF ("Failed to deactivate bell\n");
|
||||
}
|
||||
sunKbdSoundBell(&sunKeyboardPriv, loudness, pitch, duration);
|
||||
}
|
||||
|
||||
void
|
||||
_X_HIDDEN void
|
||||
xf86SetKbdLeds(int leds)
|
||||
{
|
||||
if( ioctl(xf86Info.kbdFd, KIOCSLED, &leds) < 0 )
|
||||
ErrorF("Failed to set Keyboard LED's\n");
|
||||
sunKbdSetLeds(&sunKeyboardPriv, leds);
|
||||
}
|
||||
|
||||
#include "xf86OSKbd.h"
|
||||
|
||||
Bool
|
||||
xf86OSKbdPreInit(InputInfoPtr pInfo)
|
||||
_X_HIDDEN int
|
||||
xf86GetKbdLeds(void)
|
||||
{
|
||||
return FALSE;
|
||||
return sunKbdGetLeds(&sunKeyboardPriv);
|
||||
}
|
||||
|
||||
_X_HIDDEN void
|
||||
xf86SetKbdRepeat(char rad)
|
||||
{
|
||||
sunKbdSetRepeat(&sunKeyboardPriv, rad);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
#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 leds;
|
||||
int kbdFD;
|
||||
const char *kbdPath = NULL;
|
||||
const char *defaultKbd = "/dev/kbd";
|
||||
|
||||
ioctl(xf86Info.kbdFd, KIOCGLED, &leds);
|
||||
return leds;
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
xf86SetKbdRepeat(char rad)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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");
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* None of the following should ever fail. If it does, something is
|
||||
* broken (IMO) - DWH 8/21/99
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (ioctl(xf86Info.kbdFd, KIOCTYPE, &sun_ktype) < 0)
|
||||
FatalError("Unable to determine keyboard type: %d\n", errno);
|
||||
priv->odirect = kdirect;
|
||||
kdirect = 1;
|
||||
|
||||
if (ioctl(xf86Info.kbdFd, KIOCLAYOUT, &klayout) < 0)
|
||||
FatalError("Unable to determine keyboard layout: %d\n", errno);
|
||||
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;
|
||||
}
|
||||
|
||||
if (ioctl(xf86Info.kbdFd, KIOCGTRANS, &sun_otranslation) < 0)
|
||||
FatalError("Unable to determine keyboard translation mode\n");
|
||||
/* Setup translation */
|
||||
|
||||
if (ioctl(xf86Info.kbdFd, KIOCGDIRECT, &sun_odirect) < 0)
|
||||
FatalError("Unable to determine keyboard direct setting\n");
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
xf86Msg(X_PROBED, "Keyboard type: %s (%d)\n", ktype_name, sun_ktype);
|
||||
xf86Msg(X_PROBED, "Keyboard layout: %d\n", klayout);
|
||||
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;
|
||||
}
|
||||
|
||||
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 (ioctl(xf86Info.kbdFd, KIOCSDIRECT, &tmp) == -1)
|
||||
FatalError("Setting keyboard direct mode on\n");
|
||||
if ((loudness <= 0) || (pitch <= 0) || (duration <= 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Setup translation */
|
||||
if ((priv == NULL) || (priv->audioDevName == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = TR_UNTRANS_EVENT;
|
||||
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;
|
||||
}
|
||||
|
||||
if (ioctl(xf86Info.kbdFd, KIOCTRANS, &tmp) == -1)
|
||||
FatalError("Setting keyboard translation\n");
|
||||
freq = pitch;
|
||||
freq = min(freq, (BELL_RATE / 2) - 1);
|
||||
freq = max(freq, 2 * BELL_HZ);
|
||||
|
||||
return xf86Info.kbdFd;
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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 ((sun_odirect != 0) &&
|
||||
(ioctl(xf86Info.kbdFd, KIOCSDIRECT, &sun_odirect) < 0 ))
|
||||
FatalError("Unable to restore keyboard direct setting\n");
|
||||
|
||||
return xf86Info.kbdFd;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue