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>
80 #include <asm/param.h>
84 #include "compat/linux-kd.h"
87 /* Equal to kernel version, but field names vary. */
88 struct my_kbd_repeat {
89 int delay; /* in msec; <= 0: don't change */
90 int period; /* in msec; <= 0: don't change */
91 /* earlier this field was misnamed "rate" */
99 static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
100 133, 120, 109, 100, 92, 86, 80, 75, 67,
101 60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
103 #define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
105 static int valid_delays[] = { 250, 500, 750, 1000 };
106 #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
109 KDKBDREP_ioctl_ok(double rate, int delay, int silent) {
111 * This ioctl is defined in <linux/kd.h> but is not
112 * implemented anywhere - must be in some m68k patches.
113 * Since 2.4.9 also on i386.
115 struct my_kbd_repeat kbdrep_s;
117 /* don't change, just test */
118 kbdrep_s.period = -1;
120 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
121 if (errno == EINVAL || errno == ENOTTY)
123 perror( "ioctl(KDKBDREP)" );
128 printf("old delay %d, period %d\n",
129 kbdrep_s.delay, kbdrep_s.period);
133 if (rate == 0) /* switch repeat off */
136 kbdrep_s.period = 1000.0 / rate; /* convert cps to msec */
137 if (kbdrep_s.period < 1)
139 kbdrep_s.delay = delay;
140 if (kbdrep_s.delay < 1)
143 if (ioctl(0, KDKBDREP, &kbdrep_s)) {
144 perror("ioctl(KDKBDREP)");
149 if (kbdrep_s.period == 0)
152 rate = 1000.0 / (double) kbdrep_s.period;
155 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
156 rate, kbdrep_s.delay );
158 kbdrep_s.period = -1;
160 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
163 perror( "ioctl(KDKBDREP)" );
166 printf("old delay %d, period %d\n",
167 kbdrep_s.delay, kbdrep_s.period);
168 if (kbdrep_s.period == 0)
171 rate = 1000.0 / (double) kbdrep_s.period;
174 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
175 rate, kbdrep_s.delay );
177 return 1; /* success! */
181 #define arg_state __attribute__ ((unused))
187 KIOCSRATE_ioctl_ok(arg_state double rate, arg_state int delay, arg_state int silent) {
189 struct kbd_rate kbdrate_s;
192 fd = open("/dev/kbd", O_RDONLY);
194 perror( "open(/dev/kbd)" );
198 kbdrate_s.rate = (int) (rate + 0.5); /* round up */
199 kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */
200 if (kbdrate_s.rate > 50)
203 if (ioctl( fd, KIOCSRATE, &kbdrate_s )) {
204 perror( "ioctl(KIOCSRATE)" );
210 printf( "Typematic Rate set to %d cps (delay = %d ms)\n",
211 kbdrate_s.rate, kbdrate_s.delay * 1000 / HZ );
214 #else /* no KIOCSRATE */
216 #endif /* KIOCSRATE */
220 sigalrmhandler(int sig __attribute__ ((unused))) {
221 fprintf( stderr, "kbdrate: Failed waiting for kbd controller!\n" );
226 main( int argc, char **argv ) {
228 double rate = 5.0; /* Default rate */
229 int delay = 200; /* Default delay */
231 double rate = 10.9; /* Default rate */
232 int delay = 250; /* Default delay */
234 int value = 0x7f; /* Maximum delay with slowest rate */
235 /* DO NOT CHANGE this value */
243 set_progname(argv[0]);
245 setlocale(LC_ALL, "");
246 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
247 textdomain(PACKAGE_NAME);
250 (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
251 print_version_and_exit();
253 while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) {
256 rate = atof( optarg );
259 delay = atoi( optarg );
266 _("Usage: kbdrate [-V] [-s] [-r rate] [-d delay]\n"));
271 if(KDKBDREP_ioctl_ok(rate, delay, silent)) /* m68k? */
274 if(KIOCSRATE_ioctl_ok(rate, delay, silent)) /* sparc? */
280 for (i = 0; i < RATE_COUNT; i++)
281 if (rate * 10 >= valid_rates[i]) {
288 for (i = 0; i < DELAY_COUNT; i++)
289 if (delay <= valid_delays[i]) {
295 if ( (fd = open( "/dev/port", O_RDWR )) < 0) {
296 perror( _("Cannot open /dev/port") );
300 signal( SIGALRM, sigalrmhandler );
304 lseek( fd, 0x64, 0 );
305 if (read( fd, &data, 1 ) == -1) {
309 } while ((data & 2) == 2 ); /* wait */
311 lseek( fd, 0x60, 0 );
312 data = 0xf3; /* set typematic rate */
313 if (write( fd, &data, 1 ) == -1) {
319 lseek( fd, 0x64, 0 );
320 if (read( fd, &data, 1 ) == -1) {
324 } while ((data & 2) == 2 ); /* wait */
328 lseek( fd, 0x60, 0 );
330 if (write( fd, &value, 1 ) == -1) {
338 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
339 valid_rates[value & 0x1f] / 10.0,
340 valid_delays[ (value & 0x60) >> 5 ] );