]> git.ipfire.org Git - thirdparty/util-linux.git/blob - kbd/kbdrate.c
Imported from util-linux-2.10s tarball.
[thirdparty/util-linux.git] / kbd / kbdrate.c
1 /*
2 From: faith@cs.unc.edu (Rik Faith)
3 Subject: User mode keyboard rate changer
4 Date: 27 Apr 92 13:44:26 GMT
5
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).
10
11 The "rate" is the rate in characters per second
12
13 The "delay" is the amount of time the key must remain depressed before it
14 will start to repeat.
15
16 Usage examples:
17
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
22
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!
26
27
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
31
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)
37 -s suppressed message
38 Compiles under gcc 2.1 for Linux (tested with the pre-0.96 kernel)
39
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)
45
46 Linux/68k modifications by Roman Hodek
47 (Roman.Hodek@informatik.uni-erlangen.de):
48
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
51 other architectures.
52
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.
56
57 kbdrate now first tries if the KDKBDREP ioctl is available. If it
58 is, it is used, else the old method is applied.
59
60 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
61 - added Native Language Support
62
63 1999-03-17
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.
68
69 */
70
71 #include <stdio.h>
72 #include <unistd.h>
73 #include <stdlib.h>
74 #include <errno.h>
75 #include <sys/file.h>
76 #include <sys/ioctl.h>
77
78 #include "../defines.h"
79 #ifdef HAVE_kd_h
80 #include <linux/kd.h>
81 #endif
82 #ifdef __sparc__
83 #include <asm/param.h>
84 #include <asm/kbio.h>
85 #endif
86
87 #include "nls.h"
88
89 static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
90 133, 120, 109, 100, 92, 86, 80, 75, 67,
91 60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
92 25, 23, 21, 20 };
93 #define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
94
95 static int valid_delays[] = { 250, 500, 750, 1000 };
96 #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
97
98 static int
99 KDKBDREP_ioctl_ok(double rate, int delay, int silent) {
100 #ifdef KDKBDREP
101 /* This ioctl is defined in <linux/kd.h> but is not
102 implemented anywhere - must be in some m68k patches. */
103 struct kbd_repeat kbdrep_s;
104
105 /* don't change, just test */
106 kbdrep_s.rate = -1;
107 kbdrep_s.delay = -1;
108 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
109 if (errno == EINVAL)
110 return 0;
111 perror( "ioctl(KDKBDREP)" );
112 exit( 1 );
113 }
114
115 /* do the change */
116 if (rate == 0) /* switch repeat off */
117 kbdrep_s.rate = 0;
118 else
119 kbdrep_s.rate = 1000.0 / rate; /* convert cps to msec */
120 if (kbdrep_s.rate < 1)
121 kbdrep_s.rate = 1;
122 kbdrep_s.delay = delay;
123 if (kbdrep_s.delay < 1)
124 kbdrep_s.delay = 1;
125
126 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
127 perror( "ioctl(KDKBDREP)" );
128 exit( 1 );
129 }
130
131 /* report */
132 if (kbdrep_s.rate == 0)
133 rate = 0;
134 else
135 rate = 1000.0 / (double) kbdrep_s.rate;
136
137 if (!silent)
138 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
139 rate, kbdrep_s.delay );
140
141 return 1; /* success! */
142
143 #else /* no KDKBDREP */
144 return 0;
145 #endif /* KDKBDREP */
146 }
147
148 static int
149 KIOCSRATE_ioctl_ok(double rate, int delay, int silent) {
150 #ifdef KIOCSRATE
151 struct kbd_rate kbdrate_s;
152 int fd;
153
154 fd = open("/dev/kbd", O_RDONLY);
155 if (fd == -1) {
156 perror( "open(/dev/kbd)" );
157 exit( 1 );
158 }
159
160 kbdrate_s.rate = (int) (rate + 0.5); /* must be integer, so round up */
161 kbdrate_s.delay = delay * HZ / 1000; /* convert ms to Hz */
162 if (kbdrate_s.rate > 50)
163 kbdrate_s.rate = 50;
164
165 if (ioctl( fd, KIOCSRATE, &kbdrate_s )) {
166 perror( "ioctl(KIOCSRATE)" );
167 exit( 1 );
168 }
169 close( fd );
170
171 if (!silent)
172 printf( "Typematic Rate set to %d cps (delay = %d ms)\n",
173 kbdrate_s.rate, kbdrate_s.delay * 1000 / HZ );
174
175 return 1;
176 #else /* no KIOCSRATE */
177 return 0;
178 #endif /* KIOCSRATE */
179 }
180
181 int main( int argc, char **argv )
182 {
183 #ifdef __sparc__
184 double rate = 5.0; /* Default rate */
185 int delay = 200; /* Default delay */
186 #else
187 double rate = 10.9; /* Default rate */
188 int delay = 250; /* Default delay */
189 #endif
190 int value = 0x7f; /* Maximum delay with slowest rate */
191 /* DO NOT CHANGE this value */
192 int silent = 0;
193 int fd;
194 char data;
195 int c;
196 int i;
197 extern char *optarg;
198
199 setlocale(LC_ALL, "");
200 bindtextdomain(PACKAGE, LOCALEDIR);
201 textdomain(PACKAGE);
202
203
204 while ( (c = getopt( argc, argv, "r:d:svVh?" )) != EOF ) {
205 switch (c) {
206 case 'r':
207 rate = atof( optarg );
208 break;
209 case 'd':
210 delay = atoi( optarg );
211 break;
212 case 's':
213 silent = 1;
214 break;
215 case 'v':
216 case 'V':
217 fprintf( stderr, "util-linux %s kbdrate\n", UTIL_LINUX_VERSION);
218 exit(0);
219 case 'h':
220 case '?':
221 fprintf( stderr,
222 _("Usage: kbdrate [-V] [-s] [-r rate] [-d delay]\n"));
223 exit(0);
224 }
225 }
226
227 if(KDKBDREP_ioctl_ok(rate, delay, silent)) /* m68k? */
228 return 0;
229
230 if(KIOCSRATE_ioctl_ok(rate, delay, silent)) /* sparc? */
231 return 0;
232
233
234 /* The ioport way */
235
236 for (i = 0; i < RATE_COUNT; i++)
237 if (rate * 10 >= valid_rates[i]) {
238 value &= 0x60;
239 value |= i;
240 break;
241 }
242
243
244 for (i = 0; i < DELAY_COUNT; i++)
245 if (delay <= valid_delays[i]) {
246 value &= 0x1f;
247 value |= i << 5;
248 break;
249 }
250
251 if ( (fd = open( "/dev/port", O_RDWR )) < 0) {
252 perror( _("Cannot open /dev/port") );
253 exit( 1 );
254 }
255
256 do {
257 lseek( fd, 0x64, 0 );
258 read( fd, &data, 1 );
259 } while ((data & 2) == 2 ); /* wait */
260
261 lseek( fd, 0x60, 0 );
262 data = 0xf3; /* set typematic rate */
263 write( fd, &data, 1 );
264
265 do {
266 lseek( fd, 0x64, 0 );
267 read( fd, &data, 1 );
268 } while ((data & 2) == 2 ); /* wait */
269
270 lseek( fd, 0x60, 0 );
271 sleep( 1 );
272 write( fd, &value, 1 );
273
274 close( fd );
275
276 if (!silent)
277 printf( _("Typematic Rate set to %.1f cps (delay = %d ms)\n"),
278 valid_rates[value & 0x1f] / 10.0,
279 valid_delays[ (value & 0x60) >> 5 ] );
280
281 return 0;
282 }