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);
 | 
						|
}
 | 
						|
 |