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 dependant 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, with yet another
67 different measurement system. Thus, try for KIOCSRATE, too.
76 #include <sys/ioctl.h>
78 #include "../defines.h"
83 #include <asm/param.h>
90 static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
91 133, 120, 109, 100, 92, 86, 80, 75, 67,
92 60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
94 #define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
96 static int valid_delays[] = { 250, 500, 750, 1000 };
97 #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
100 KDKBDREP_ioctl_ok(double rate, int delay, int silent) {
102 /* This ioctl is defined in <linux/kd.h> but is not
103 implemented anywhere - must be in some m68k patches. */
104 struct kbd_repeat kbdrep_s;
106 /* don't change, just test */
109 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
112 perror( "ioctl(KDKBDREP)" );
117 if (rate == 0) /* switch repeat off */
120 kbdrep_s.rate = 1000.0 / rate; /* convert cps to msec */
121 if (kbdrep_s.rate < 1)
123 kbdrep_s.delay = delay;
124 if (kbdrep_s.delay < 1)
127 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
128 perror( "ioctl(KDKBDREP)" );
133 if (kbdrep_s.rate == 0)
136 rate = 1000.0 / (double) kbdrep_s.rate;
139 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
140 rate, kbdrep_s.delay );
142 return 1; /* success! */
144 #else /* no KDKBDREP */
146 #endif /* KDKBDREP */
150 KIOCSRATE_ioctl_ok(double rate, int delay, int silent) {
152 struct kbd_rate kbdrate_s;
155 fd = open("/dev/kbd", O_RDONLY);
157 perror( "open(/dev/kbd)" );
161 kbdrate_s.rate = (int) (rate + 0.5); /* round up */
162 kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */
163 if (kbdrate_s.rate > 50)
166 if (ioctl( fd, KIOCSRATE, &kbdrate_s )) {
167 perror( "ioctl(KIOCSRATE)" );
173 printf( "Typematic Rate set to %d cps (delay = %d ms)\n",
174 kbdrate_s.rate, kbdrate_s.delay * 1000 / HZ );
177 #else /* no KIOCSRATE */
179 #endif /* KIOCSRATE */
182 int main( int argc, char **argv )
185 double rate = 5.0; /* Default rate */
186 int delay = 200; /* Default delay */
188 double rate = 10.9; /* Default rate */
189 int delay = 250; /* Default delay */
191 int value = 0x7f; /* Maximum delay with slowest rate */
192 /* DO NOT CHANGE this value */
200 set_progname(argv[0]);
202 setlocale(LC_ALL, "");
203 bindtextdomain(PACKAGE, LOCALEDIR);
206 if (argc == 2 && !strcmp(argv[1], "-V"))
207 print_version_and_exit();
209 while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF ) {
212 rate = atof( optarg );
215 delay = atoi( optarg );
221 fprintf(stderr, "kbdrate from kbd-%s\n", VERSION);
226 if(KDKBDREP_ioctl_ok(rate, delay, silent)) /* m68k? */
229 if(KIOCSRATE_ioctl_ok(rate, delay, silent)) /* sparc? */
235 for (i = 0; i < RATE_COUNT; i++)
236 if (rate * 10 >= valid_rates[i]) {
243 for (i = 0; i < DELAY_COUNT; i++)
244 if (delay <= valid_delays[i]) {
250 if ( (fd = open( "/dev/port", O_RDWR )) < 0) {
251 perror( _("Cannot open /dev/port") );
256 lseek( fd, 0x64, 0 );
257 read( fd, &data, 1 );
258 } while ((data & 2) == 2 ); /* wait */
260 lseek( fd, 0x60, 0 );
261 data = 0xf3; /* set typematic rate */
262 write( fd, &data, 1 );
265 lseek( fd, 0x64, 0 );
266 read( fd, &data, 1 );
267 } while ((data & 2) == 2 ); /* wait */
269 lseek( fd, 0x60, 0 );
271 write( fd, &value, 1 );
276 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
277 valid_rates[value & 0x1f] / 10.0,
278 valid_delays[ (value & 0x60) >> 5 ] );