2 From: faith@cs.unc.edu (Rik Faith)
3 Subject: User mode keyboard rate changer
4 Date: 27 Apr 92 13:44:26 GMT
6 I put together this program, called kbdrate.c, which will reset the keyboard
7 repeat rate and delay in user mode. The program must have read/write
8 access to /dev/port, so if /dev/port is only read/writeable by group port,
9 then kbdrate must run setgid to group port (for example).
11 The "rate" is the rate in characters per second
13 The "delay" is the amount of time the key must remain depressed before it
18 kbdrate set rate to IBM default (10.9 cps, 250ms delay)
19 kbdrate -r 30.0 set rate to 30 cps and delay to 250ms
20 kbdrate -r 20.0 -s set rate to 20 cps (delay 250ms) -- don't print message
21 kbdrate -r 0 -d 0 set rate to 2.0 cps and delay to 250 ms
23 I find it useful to put kbdrate in my /etc/rc file so that the keyboard
24 rate is set to something that I find comfortable at boot time. This sure
25 beats rebuilding the kernel!
28 kbdrate.c -- Set keyboard typematic rate (and delay)
29 Created: Thu Apr 23 12:24:30 1992
30 Author: Rickard E. Faith, faith@cs.unc.edu
32 Copyright 1992 Rickard E. Faith. Distributed under the GPL.
33 This program comes with ABSOLUTELY NO WARRANTY.
34 Usage: kbdrate [-r rate] [-d delay] [-s]
35 Rate can range from 2.0 to 30.0 (units are characters per second)
36 Delay can range from 250 to 1000 (units are milliseconds)
38 Compiles under gcc 2.1 for Linux (tested with the pre-0.96 kernel)
40 Wed Jun 22 21:35:43 1994, faith@cs.unc.edu:
41 Changed valid_rates per suggestion by Andries.Brouwer@cwi.nl.
42 Wed Jun 22 22:18:29 1994, faith@cs.unc.edu:
43 Added patch for AUSTIN notebooks from John Bowman
44 (bowman@hagar.ph.utexas.edu)
46 Linux/68k modifications by Roman Hodek
47 (Roman.Hodek@informatik.uni-erlangen.de):
49 Reading/writing the Intel I/O ports via /dev/port is not the
50 English way... Such hardware dependent stuff can never work on
53 Linux/68k has an new ioctl for setting the keyboard repeat rate
54 and delay. Both values are counted in msecs, the kernel will do
55 any rounding to values possible with the underlying hardware.
57 kbdrate now first tries if the KDKBDREP ioctl is available. If it
58 is, it is used, else the old method is applied.
60 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
61 - added Native Language Support
64 Linux/SPARC modifications by Jeffrey Connell <ankh@canuck.gen.nz>:
65 It seems that the KDKBDREP ioctl is not available on this platform.
66 However, Linux/SPARC has its own ioctl for this (since 2.1.30),
67 with yet another measurement system. Thus, try for KIOCSRATE, too.
76 #include <sys/ioctl.h>
79 #include <asm/param.h>
83 /* usually defined in <linux/kd.h> */
84 #define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate;
85 * actually used values are returned */
87 int delay; /* in msec; <= 0: don't change */
89 int rate; /* in msec; <= 0: don't change */
91 int period; /* in msec; <= 0: don't change */
97 #define KBD_PERIOD(var) var.rate
99 #define KBD_PERIOD(var) var.period
107 static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
108 133, 120, 109, 100, 92, 86, 80, 75, 67,
109 60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
111 #define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
113 static int valid_delays[] = { 250, 500, 750, 1000 };
114 #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
117 KDKBDREP_ioctl_ok(double rate, int delay, int silent) {
118 #if defined(KDKBDREP) && !defined(__sparc__)
119 /* This ioctl is defined in <linux/kd.h> but is not
120 implemented anywhere - must be in some m68k patches.
121 We cannot blindly try unimplemented ioctls on sparc64 -
122 the 32<->64bit transition layer does not like it. */
123 struct kbd_repeat kbdrep_s;
125 /* don't change, just test */
126 KBD_PERIOD(kbdrep_s) = -1;
128 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
129 if (errno == EINVAL || errno == ENOTTY)
131 perror( "ioctl(KDKBDREP)" );
136 printf("old delay %d, period %d\n",
137 kbdrep_s.delay, KBD_PERIOD(kbdrep_s));
141 if (rate == 0) /* switch repeat off */
142 KBD_PERIOD(kbdrep_s) = 0;
144 KBD_PERIOD(kbdrep_s) = 1000.0 / rate; /* convert cps to msec */
145 if (KBD_PERIOD(kbdrep_s) < 1)
146 KBD_PERIOD(kbdrep_s) = 1;
147 kbdrep_s.delay = delay;
148 if (kbdrep_s.delay < 1)
151 if (ioctl(0, KDKBDREP, &kbdrep_s)) {
152 perror("ioctl(KDKBDREP)");
157 if (KBD_PERIOD(kbdrep_s) == 0)
160 rate = 1000.0 / (double) KBD_PERIOD(kbdrep_s);
163 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
164 rate, kbdrep_s.delay );
166 return 1; /* success! */
167 #else /* no KDKBDREP or __sparc__ */
169 #endif /* KDKBDREP */
173 KIOCSRATE_ioctl_ok(double rate, int delay, int silent) {
175 struct kbd_rate kbdrate_s;
178 fd = open("/dev/kbd", O_RDONLY);
180 perror( "open(/dev/kbd)" );
184 KBD_PERIOD(kbdrate_s) = (int) (rate + 0.5); /* round up */
185 kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */
186 if (KBD_PERIOD(kbdrate_s) > 50)
187 KBD_PERIOD(kbdrate_s) = 50;
189 if (ioctl( fd, KIOCSRATE, &kbdrate_s )) {
190 perror( "ioctl(KIOCSRATE)" );
196 printf( "Typematic Rate set to %d cps (delay = %d ms)\n",
197 KBD_PERIOD(kbdrate_s), kbdrate_s.delay * 1000 / HZ );
200 #else /* no KIOCSRATE */
202 #endif /* KIOCSRATE */
206 sigalrmhandler( int sig ) {
207 fprintf( stderr, "kbdrate: Failed waiting for kbd controller!\n" );
212 main( int argc, char **argv ) {
214 double rate = 20.0; /* Default rate */
215 int delay = 200; /* Default delay */
217 double rate = 10.9; /* Default rate */
218 int delay = 250; /* Default delay */
220 int value = 0x7f; /* Maximum delay with slowest rate */
221 /* DO NOT CHANGE this value */
229 set_progname(argv[0]);
231 setlocale(LC_ALL, "");
232 bindtextdomain(PACKAGE, LOCALEDIR);
236 (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
237 print_version_and_exit();
239 while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) {
242 rate = atof( optarg );
245 delay = atoi( optarg );
252 _("Usage: kbdrate [-V] [-s] [-r rate] [-d delay]\n"));
257 if(KDKBDREP_ioctl_ok(rate, delay, silent)) /* m68k? */
260 if(KIOCSRATE_ioctl_ok(rate, delay, silent)) /* sparc? */
264 /* The ioport way - will crash on sparc */
267 for (i = 0; i < RATE_COUNT; i++)
268 if (rate * 10 >= valid_rates[i]) {
275 for (i = 0; i < DELAY_COUNT; i++)
276 if (delay <= valid_delays[i]) {
282 if ( (fd = open( "/dev/port", O_RDWR )) < 0) {
283 perror( _("Cannot open /dev/port") );
287 signal( SIGALRM, sigalrmhandler );
291 lseek( fd, 0x64, 0 );
292 if (read( fd, &data, 1 ) == -1) {
296 } while ((data & 2) == 2 ); /* wait */
298 lseek( fd, 0x60, 0 );
299 data = 0xf3; /* set typematic rate */
300 if (write( fd, &data, 1 ) == -1) {
306 lseek( fd, 0x64, 0 );
307 if (read( fd, &data, 1 ) == -1) {
311 } while ((data & 2) == 2 ); /* wait */
315 lseek( fd, 0x60, 0 );
317 if (write( fd, &value, 1 ) == -1) {
325 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
326 valid_rates[value & 0x1f] / 10.0,
327 valid_delays[ (value & 0x60) >> 5 ] );