663 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			663 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $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.3 2004/06/13 04:50:21 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;
 | |
| }
 |