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>
84 /* usually defined in <linux/kd.h> */
85 #define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate;
86 * actually used values are returned */
89 /* Equal to kernel version, but field names vary. */
90 struct my_kbd_repeat {
91 int delay; /* in msec; <= 0: don't change */
92 int period; /* in msec; <= 0: don't change */
93 /* earlier this field was misnamed "rate" */
101 static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
102 133, 120, 109, 100, 92, 86, 80, 75, 67,
103 60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
105 #define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
107 static int valid_delays[] = { 250, 500, 750, 1000 };
108 #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
111 KDKBDREP_ioctl_ok(double rate, int delay, int silent) {
113 * This ioctl is defined in <linux/kd.h> but is not
114 * implemented anywhere - must be in some m68k patches.
115 * Since 2.4.9 also on i386.
117 struct my_kbd_repeat kbdrep_s;
119 /* don't change, just test */
120 kbdrep_s.period = -1;
122 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
123 if (errno == EINVAL || errno == ENOTTY)
125 perror( "ioctl(KDKBDREP)" );
130 printf("old delay %d, period %d\n",
131 kbdrep_s.delay, kbdrep_s.period);
135 if (rate == 0) /* switch repeat off */
138 kbdrep_s.period = 1000.0 / rate; /* convert cps to msec */
139 if (kbdrep_s.period < 1)
141 kbdrep_s.delay = delay;
142 if (kbdrep_s.delay < 1)
145 if (ioctl(0, KDKBDREP, &kbdrep_s)) {
146 perror("ioctl(KDKBDREP)");
151 if (kbdrep_s.period == 0)
154 rate = 1000.0 / (double) kbdrep_s.period;
157 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
158 rate, kbdrep_s.delay );
160 kbdrep_s.period = -1;
162 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
165 perror( "ioctl(KDKBDREP)" );
168 printf("old delay %d, period %d\n",
169 kbdrep_s.delay, kbdrep_s.period);
170 if (kbdrep_s.period == 0)
173 rate = 1000.0 / (double) kbdrep_s.period;
176 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
177 rate, kbdrep_s.delay );
179 return 1; /* success! */
183 KIOCSRATE_ioctl_ok(double rate, int delay, int silent) {
185 struct kbd_rate kbdrate_s;
188 fd = open("/dev/kbd", O_RDONLY);
190 perror( "open(/dev/kbd)" );
194 kbdrate_s.rate = (int) (rate + 0.5); /* round up */
195 kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */
196 if (kbdrate_s.rate > 50)
199 if (ioctl( fd, KIOCSRATE, &kbdrate_s )) {
200 perror( "ioctl(KIOCSRATE)" );
206 printf( "Typematic Rate set to %d cps (delay = %d ms)\n",
207 kbdrate_s.rate, kbdrate_s.delay * 1000 / HZ );
210 #else /* no KIOCSRATE */
212 #endif /* KIOCSRATE */
216 sigalrmhandler( int sig ) {
217 fprintf( stderr, "kbdrate: Failed waiting for kbd controller!\n" );
222 main( int argc, char **argv ) {
224 double rate = 5.0; /* Default rate */
225 int delay = 200; /* Default delay */
227 double rate = 10.9; /* Default rate */
228 int delay = 250; /* Default delay */
230 int value = 0x7f; /* Maximum delay with slowest rate */
231 /* DO NOT CHANGE this value */
239 set_progname(argv[0]);
241 setlocale(LC_ALL, "");
242 bindtextdomain(PACKAGE_NAME, LOCALEDIR);
243 textdomain(PACKAGE_NAME);
246 (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
247 print_version_and_exit();
249 while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) {
252 rate = atof( optarg );
255 delay = atoi( optarg );
262 _("Usage: kbdrate [-V] [-s] [-r rate] [-d delay]\n"));
267 if(KDKBDREP_ioctl_ok(rate, delay, silent)) /* m68k? */
270 if(KIOCSRATE_ioctl_ok(rate, delay, silent)) /* sparc? */
276 for (i = 0; i < RATE_COUNT; i++)
277 if (rate * 10 >= valid_rates[i]) {
284 for (i = 0; i < DELAY_COUNT; i++)
285 if (delay <= valid_delays[i]) {
291 if ( (fd = open( "/dev/port", O_RDWR )) < 0) {
292 perror( _("Cannot open /dev/port") );
296 signal( SIGALRM, sigalrmhandler );
300 lseek( fd, 0x64, 0 );
301 if (read( fd, &data, 1 ) == -1) {
305 } while ((data & 2) == 2 ); /* wait */
307 lseek( fd, 0x60, 0 );
308 data = 0xf3; /* set typematic rate */
309 if (write( fd, &data, 1 ) == -1) {
315 lseek( fd, 0x64, 0 );
316 if (read( fd, &data, 1 ) == -1) {
320 } while ((data & 2) == 2 ); /* wait */
324 lseek( fd, 0x60, 0 );
326 if (write( fd, &value, 1 ) == -1) {
334 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
335 valid_rates[value & 0x1f] / 10.0,
336 valid_delays[ (value & 0x60) >> 5 ] );