]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/kbdrate.c
Imported from util-linux-2.9i tarball.
[thirdparty/util-linux.git] / sys-utils / 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 */
61
62 #include <stdio.h>
63 #include <unistd.h>
64 #include <stdlib.h>
65 #include <errno.h>
66 #include <sys/file.h>
67 #include <sys/ioctl.h>
68 #include <linux/version.h>
69 #if LINUX_VERSION_CODE >= 131072
70 /* kd.h is not available with all linux versions. 131072 is equivalent
71 to linux 2.0.0 */
72 #include <linux/kd.h>
73 #endif
74
75 #define VERSION "1.3"
76
77 static int valid_rates[] = { 300, 267, 240, 218, 200, 185, 171, 160, 150,
78 133, 120, 109, 100, 92, 86, 80, 75, 67,
79 60, 55, 50, 46, 43, 40, 37, 33, 30, 27,
80 25, 23, 21, 20 };
81 #define RATE_COUNT (sizeof( valid_rates ) / sizeof( int ))
82
83 static int valid_delays[] = { 250, 500, 750, 1000 };
84 #define DELAY_COUNT (sizeof( valid_delays ) / sizeof( int ))
85
86 #ifdef KDKBDREP
87 static int ioctl_possible = 0;
88 struct kbd_repeat kbdrep_s;
89 #endif
90
91 int main( int argc, char **argv )
92 {
93 double rate = 10.9; /* Default rate */
94 int delay = 250; /* Default delay */
95 int value = 0x7f; /* Maximum delay with slowest rate */
96 /* DO NOT CHANGE this value */
97 int silent = 0;
98 int fd;
99 char data;
100 int c;
101 int i;
102 extern char *optarg;
103
104 while ( (c = getopt( argc, argv, "r:d:sv" )) != EOF )
105 switch (c) {
106 case 'r':
107 rate = atof( optarg );
108 break;
109 case 'd':
110 delay = atoi( optarg );
111 break;
112 case 's':
113 silent = 1;
114 break;
115 case 'v':
116 fprintf( stderr, "util-linux kbdrate " VERSION "\n");
117 exit(0);
118 }
119
120 #ifdef KDKBDREP
121 kbdrep_s.rate = -1; /* don't change, just test */
122 kbdrep_s.delay = -1;
123 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
124 if (errno == EINVAL)
125 ioctl_possible = 0;
126 else {
127 perror( "ioctl(KDKBDREP)" );
128 exit( 1 );
129 }
130 } else ioctl_possible = 1;
131
132 if (ioctl_possible) {
133 if (rate == 0) /* switch repeat off */
134 kbdrep_s.rate = 0;
135 else
136 kbdrep_s.rate = 1000.0 / rate; /* convert cps to msec */
137 if (kbdrep_s.rate < 1)
138 kbdrep_s.rate = 1;
139 kbdrep_s.delay = delay;
140 if (kbdrep_s.delay < 1)
141 kbdrep_s.delay = 1;
142
143 if (ioctl( 0, KDKBDREP, &kbdrep_s )) {
144 perror( "ioctl(KDKBDREP)" );
145 exit( 1 );
146 }
147
148 if (!silent)
149 printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n",
150 1000.0 / (double)kbdrep_s.rate, kbdrep_s.delay );
151 } else {
152 #endif
153
154 /* The ioport way */
155
156 for (i = 0; i < RATE_COUNT; i++)
157 if (rate * 10 >= valid_rates[i]) {
158 value &= 0x60;
159 value |= i;
160 break;
161 }
162
163
164 for (i = 0; i < DELAY_COUNT; i++)
165 if (delay <= valid_delays[i]) {
166 value &= 0x1f;
167 value |= i << 5;
168 break;
169 }
170
171 if ( (fd = open( "/dev/port", O_RDWR )) < 0) {
172 perror( "Cannot open /dev/port" );
173 exit( 1 );
174 }
175
176 do {
177 lseek( fd, 0x64, 0 );
178 read( fd, &data, 1 );
179 } while ((data & 2) == 2 ); /* wait */
180
181 lseek( fd, 0x60, 0 );
182 data = 0xf3; /* set typematic rate */
183 write( fd, &data, 1 );
184
185 do {
186 lseek( fd, 0x64, 0 );
187 read( fd, &data, 1 );
188 } while ((data & 2) == 2 ); /* wait */
189
190 lseek( fd, 0x60, 0 );
191 sleep( 1 );
192 write( fd, &value, 1 );
193
194 close( fd );
195
196 if (!silent) printf( "Typematic Rate set to %.1f cps (delay = %d mS)\n",
197 valid_rates[value & 0x1f] / 10.0,
198 valid_delays[ (value & 0x60) >> 5 ] );
199
200 #ifdef KDKBDREP
201 }
202 #endif
203
204 return 0;
205 }