[comp.os.minix] Fastkey - speeding up an AT keyboard

nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (02/21/90)

Long ago (lost somewhere in the mists of time), I posted a program which
reprograms the keyboard controller on an AT to modify the keyboard's
typematic action.  Bruce Evans has pointed out that the port_in/port_out
interface is quite different in 1.5, so I've updated the program.

The program lets you specify a delay until key repetition begins (between
1/4 and 1 second) and the rate at which a held key is repeated (an interval
between 34 and 504 milliseconds).  I have a line in /etc/rc which says
"fastkey -d 500"; that gives me a 1/2 second delay before key repetition
begins and uses the maximum rate.  Experiment to see what you like.

The program has been tested and works for PC versions 1.3 through 1.5,
on AT's and strict compatibles.  It will not work on PC's, which don't
have a programmable controller.  It doesn't seem to work on PS/2's (which
do have a programmable controller) but I don't know why.  As for Ataris,
what do I know!

A standard mini-man page is included.

Norbert
------------------------------------------------------------------------
echo x - fastkey.1
sed '/^X/s///' > fastkey.1 << '/'
X#fastkey
XCommand:	fastkey - modify keyboard responsiveness on an AT
XSyntax:		fastkey [-d delay] [-r rate] [-v]
XFlags:		-d delay  Typematic delay set to delay milliseconds
X		-r rate   Typematic rate set to rate milliseconds
X		-v	  Verbose
X
X   Fastkey programs the AT's keyboard controller to improve its
Xresponsiveness.  Flags may specify, to the granularity of the keyboard
Xcontroller, both the delay until the keyboard starts repeating a held key,
Xand the time between repetitions (the rate).
/
echo x - fastkey.c
sed '/^X/s///' > fastkey.c << '/'
X/* fastkey - modify PC/AT's home keyboard response */
X
X/* Norbert Schlenker (nfs@princeton.edu)  1990-02-10
X * Released to the public domain.
X *
X * This program modifies the responsiveness of a keyboard on an IBM PC/AT
X * and strict compatibles.  On such machines, the keyboard controller can
X * be programmed to change the time until keys begin to repeat (the delay)
X * and the speed at which they repeat thereafter (the rate).  This program
X * has no useful effect on other machine types or on RS-232 terminals.
X *
X * Compilation:	cc -i -o fastkey fastkey.c
X *		chmem =3072 fastkey
X */
X
X/* External interfaces */
X#include <limits.h>
X#include <stdio.h>
X
Xextern int getopt(/* int argc, char **argv, char *optstring */);
Xextern char* optarg;
Xextern int opterr;
X
X/* Local definitions */
X#define KBC_PORT	0x60	/* keyboard controller port on an AT */
X#define TYPEMATIC_REG	0xf3	/* typematic register in the AT's KBC */
X#define KBC_ACK		0xfa	/* keyboard controller acknowledgement byte */
X#define ACK_LOOP	1000	/* look for acknowledgement this many times */
X#define DELAY_SHIFT	5	/* delay position in control byte */
X#define RATE_SHIFT	0	/* rate position in control byte */
X
X#define EBADARG		1	/* bad argument(s) */
X#define ENOPORT		2	/* no access to port */
X#define ENOACK		3	/* no acknowledgement from port */
X
X/* Private storage */
Xstatic char *program;
Xstatic char *errors[] = {
X  "",
X  "Usage: %s [-d delay] [-r rate] [-v]\n",
X  "%s: keyboard port inaccessible\n",
X  "%s: keyboard controller timed out\n"
X};
X
Xstatic int delays[] = {		/* initial delay in milliseconds */
X  250, 500, 750, 1000,
X  INT_MAX			/* sentinel */
X};
X
Xstatic int rates[] = {		/* repetition interval in milliseconds */
X   34,  38,  42,  46,  50,  55,  59,  63,
X   68,  76,  84,  92, 100, 110, 118, 126,
X  136, 152, 168, 184, 200, 220, 236, 252,
X  272, 304, 336, 368, 400, 440, 472, 504,
X  INT_MAX			/* sentinel */
X};
X
X
Xvoid error_exit(rc)
Xint rc;
X{
X  fprintf(stderr, errors[rc], program);
X  exit(rc);
X}
X
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  int delay = 0;		/* default delay is very short */
X  int rate = 0;			/* default rate is very fast */
X  int verbose = 0;		/* default is no tongue wagging */
X  int flag;
X  int n;
X  int ack;
X
X  program = argv[0];
X
X  opterr = 0;
X  while ((flag = getopt(argc, argv, "d:r:v")) != EOF) {
X	switch(flag) {
X	      case 'd':
X		n = atoi(optarg);
X		for (delay = 0; n > delays[delay]; delay++) ;
X		break;
X	      case 'r':
X		n = atoi(optarg);
X		for (rate = 0; n > rates[rate]; rate++) ;
X		break;
X	      case 'v':
X		verbose = 1;
X		break;
X	      default:
X		error_exit(EBADARG);
X	}
X  }
X  if (delays[delay] == INT_MAX || rates[rate] == INT_MAX)
X	error_exit(EBADARG);
X
X  if (port_out(KBC_PORT, TYPEMATIC_REG) < 0)
X	error_exit(ENOPORT);
X  for (n = ACK_LOOP, ack = 0; --n >= 0 && ack != KBC_ACK; ) {
X	port_in(KBC_PORT, &ack);
X	if (ack < 0) error_exit(ENOPORT);
X  }
X  if (n < 0) error_exit(ENOACK);
X  if (port_out(KBC_PORT, (delay << DELAY_SHIFT) | (rate << RATE_SHIFT)) < 0)
X	error_exit(ENOPORT);
X
X  if (verbose)
X	printf("%s: %d ms typematic delay and %d ms typematic rate.\n",
X		program, delays[delay], rates[rate]);
X  exit(0);
X}
/