247 lines
6.1 KiB
C
247 lines
6.1 KiB
C
|
/*
|
||
|
* Copyright 1992 by Orest Zborowski <obz@Kodak.com>
|
||
|
* Copyright 1993 by David Dawes <dawes@xfree86.org>
|
||
|
*
|
||
|
* 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 Orest Zborowski and David Dawes
|
||
|
* not be used in advertising or publicity pertaining to distribution of
|
||
|
* the software without specific, written prior permission. Orest Zborowski
|
||
|
* and David Dawes make no representations about the suitability of this
|
||
|
* software for any purpose. It is provided "as is" without express or
|
||
|
* implied warranty.
|
||
|
*
|
||
|
* OREST ZBOROWSKI AND DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD
|
||
|
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||
|
* FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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.
|
||
|
*
|
||
|
*/
|
||
|
/* $XConsortium: lnx_io.c /main/8 1996/10/19 18:06:28 kaleb $ */
|
||
|
|
||
|
#define NEED_EVENTS
|
||
|
#ifdef HAVE_XORG_CONFIG_H
|
||
|
#include <xorg-config.h>
|
||
|
#endif
|
||
|
|
||
|
#include <X11/X.h>
|
||
|
|
||
|
#include "compiler.h"
|
||
|
|
||
|
#include "xf86.h"
|
||
|
#include "xf86Priv.h"
|
||
|
#include "xf86_OSlib.h"
|
||
|
|
||
|
#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */
|
||
|
|
||
|
_X_EXPORT void
|
||
|
xf86SoundKbdBell(int loudness, int pitch, int duration)
|
||
|
{
|
||
|
if (loudness && pitch)
|
||
|
{
|
||
|
ioctl(xf86Info.consoleFd, KDMKTONE,
|
||
|
((1193190 / pitch) & 0xffff) |
|
||
|
(((unsigned long)duration *
|
||
|
loudness / 50) << 16));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
xf86SetKbdLeds(int leds)
|
||
|
{
|
||
|
ioctl(xf86Info.consoleFd, KDSETLED, leds);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
xf86GetKbdLeds()
|
||
|
{
|
||
|
int leds = 0;
|
||
|
|
||
|
ioctl(xf86Info.consoleFd, KDGETLED, &leds);
|
||
|
return(leds);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
KDKBDREP_ioctl_ok(int rate, int delay) {
|
||
|
#if defined(KDKBDREP) && !defined(__sparc__)
|
||
|
/* This ioctl is defined in <linux/kd.h> but is not
|
||
|
implemented anywhere - must be in some m68k patches. */
|
||
|
struct kbd_repeat kbdrep_s;
|
||
|
|
||
|
/* don't change, just test */
|
||
|
kbdrep_s.LNX_KBD_PERIOD_NAME = -1;
|
||
|
kbdrep_s.delay = -1;
|
||
|
if (ioctl( xf86Info.consoleFd, KDKBDREP, &kbdrep_s )) {
|
||
|
return 0;
|
||
|
}
|
||
|
/* do the change */
|
||
|
if (rate == 0) /* switch repeat off */
|
||
|
kbdrep_s.LNX_KBD_PERIOD_NAME = 0;
|
||
|
else
|
||
|
kbdrep_s.LNX_KBD_PERIOD_NAME = 10000 / rate; /* convert cps to msec */
|
||
|
if (kbdrep_s.LNX_KBD_PERIOD_NAME < 1)
|
||
|
kbdrep_s.LNX_KBD_PERIOD_NAME = 1;
|
||
|
kbdrep_s.delay = delay;
|
||
|
if (kbdrep_s.delay < 1)
|
||
|
kbdrep_s.delay = 1;
|
||
|
|
||
|
if (ioctl( xf86Info.consoleFd, KDKBDREP, &kbdrep_s )) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 1; /* success! */
|
||
|
#else /* no KDKBDREP */
|
||
|
return 0;
|
||
|
#endif /* KDKBDREP */
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
KIOCSRATE_ioctl_ok(int rate, int delay) {
|
||
|
#ifdef KIOCSRATE
|
||
|
struct kbd_rate kbdrate_s;
|
||
|
int fd;
|
||
|
|
||
|
fd = open("/dev/kbd", O_RDONLY);
|
||
|
if (fd == -1)
|
||
|
return 0;
|
||
|
|
||
|
kbdrate_s.rate = (rate + 5) / 10; /* must be integer, so round up */
|
||
|
kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */
|
||
|
if (kbdrate_s.rate > 50)
|
||
|
kbdrate_s.rate = 50;
|
||
|
|
||
|
if (ioctl( fd, KIOCSRATE, &kbdrate_s )) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
close( fd );
|
||
|
|
||
|
return 1;
|
||
|
#else /* no KIOCSRATE */
|
||
|
return 0;
|
||
|
#endif /* KIOCSRATE */
|
||
|
}
|
||
|
|
||
|
void xf86SetKbdRepeat(char rad)
|
||
|
{
|
||
|
#ifdef __sparc__
|
||
|
int rate = 500; /* Default rate */
|
||
|
int delay = 200; /* Default delay */
|
||
|
#else
|
||
|
int rate = 300; /* Default rate */
|
||
|
int delay = 250; /* Default delay */
|
||
|
#endif
|
||
|
|
||
|
#if defined(__alpha__) || defined (__i386__) || defined(__ia64__)
|
||
|
int i;
|
||
|
int timeout;
|
||
|
int value = 0x7f; /* Maximum delay with slowest rate */
|
||
|
|
||
|
static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
|
||
|
133, 120, 109, 100, 92, 86, 80, 75, 67,
|
||
|
60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
|
||
|
25, 23, 21, 20 };
|
||
|
#define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
|
||
|
|
||
|
static int valid_delays[] = { 250, 500, 750, 1000 };
|
||
|
#define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
|
||
|
#endif
|
||
|
|
||
|
if (xf86Info.kbdRate >= 0)
|
||
|
rate = xf86Info.kbdRate * 10;
|
||
|
if (xf86Info.kbdDelay >= 0)
|
||
|
delay = xf86Info.kbdDelay;
|
||
|
|
||
|
if(KDKBDREP_ioctl_ok(rate, delay)) /* m68k? */
|
||
|
return;
|
||
|
|
||
|
if(KIOCSRATE_ioctl_ok(rate, delay)) /* sparc? */
|
||
|
return;
|
||
|
|
||
|
if (xf86IsPc98())
|
||
|
return;
|
||
|
|
||
|
#if defined(__alpha__) || defined (__i386__) || defined(__ia64__)
|
||
|
|
||
|
/* The ioport way */
|
||
|
|
||
|
for (i = 0; i < RATE_COUNT; i++)
|
||
|
if (rate >= valid_rates[i]) {
|
||
|
value &= 0x60;
|
||
|
value |= i;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < DELAY_COUNT; i++)
|
||
|
if (delay <= valid_delays[i]) {
|
||
|
value &= 0x1f;
|
||
|
value |= i << 5;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
timeout = KBC_TIMEOUT;
|
||
|
while (((inb(0x64) & 2) == 2) && --timeout)
|
||
|
usleep(1000); /* wait */
|
||
|
|
||
|
if (timeout == 0)
|
||
|
return;
|
||
|
|
||
|
outb(0x60, 0xf3); /* set typematic rate */
|
||
|
while (((inb(0x64) & 2) == 2) && --timeout)
|
||
|
usleep(1000); /* wait */
|
||
|
|
||
|
usleep(10000);
|
||
|
outb(0x60, value);
|
||
|
|
||
|
#endif /* __alpha__ || __i386__ || __ia64__ */
|
||
|
}
|
||
|
|
||
|
static int kbdtrans;
|
||
|
static struct termios kbdtty;
|
||
|
|
||
|
void
|
||
|
xf86KbdInit()
|
||
|
{
|
||
|
ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans);
|
||
|
tcgetattr (xf86Info.consoleFd, &kbdtty);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
xf86KbdOn()
|
||
|
{
|
||
|
struct termios nTty;
|
||
|
|
||
|
#ifdef __powerpc__
|
||
|
if (xf86Info.kbdCustomKeycodes)
|
||
|
ioctl(xf86Info.consoleFd, KDSKBMODE, K_MEDIUMRAW);
|
||
|
else
|
||
|
#endif
|
||
|
ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW);
|
||
|
|
||
|
nTty = kbdtty;
|
||
|
nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
|
||
|
nTty.c_oflag = 0;
|
||
|
nTty.c_cflag = CREAD | CS8;
|
||
|
nTty.c_lflag = 0;
|
||
|
nTty.c_cc[VTIME]=0;
|
||
|
nTty.c_cc[VMIN]=1;
|
||
|
cfsetispeed(&nTty, 9600);
|
||
|
cfsetospeed(&nTty, 9600);
|
||
|
tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty);
|
||
|
return(xf86Info.consoleFd);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
xf86KbdOff()
|
||
|
{
|
||
|
ioctl(xf86Info.consoleFd, KDSKBMODE, kbdtrans);
|
||
|
tcsetattr(xf86Info.consoleFd, TCSANOW, &kbdtty);
|
||
|
return(xf86Info.consoleFd);
|
||
|
}
|
||
|
|