Added support for compiling C++ files. It isn't included for all
[AROS.git] / arch / all-linux / hidd / linuxkbd / makelinuxkeytable.c
blob22b196fc513f482622d8982d73868af8ce0cce40
1 /* $XConsortium: xev.c,v 1.15 94/04/17 20:45:20 keith Exp $ */
2 /*
4 Copyright (c) 1988 X Consortium
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of the X Consortium shall
26 not be used in advertising or otherwise to promote the sale, use or
27 other dealings in this Software without prior written authorization
28 from the X Consortium.
33 * Author: Jim Fulton, MIT X Consortium
36 /***************************************************************************/
38 #include <stdio.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <sys/signal.h>
45 #include <unistd.h>
46 #include <termios.h>
47 #include <sys/ioctl.h>
48 #include <linux/kd.h>
49 #include <limits.h>
51 #define FALSE 0
52 #define TRUE 1
54 void cleanup(int);
55 void cleanup_sighandling();
56 void setup_sighandling();
57 void cleanup_kbd();
58 int init_kbd();
59 void cleanup(int);
62 /***************************************************************************/
65 static char *ProgramName;
66 static FILE *fh;
68 static unsigned char table[256];
70 /***************************************************************************/
72 #define CODE_NONE 0xFF
73 #define CODE_ESCAPE 0x01
74 static struct _asktable
76 char *title;
77 int rawkeystart;
78 int numkeys;
79 unsigned char nokey_code;
80 } asktable [] =
82 {"1st row: Press ESCAPE Key", 0x45, 1, },
83 {"1st row: Press F1 .. F10", 0x50, 10, CODE_NONE},
84 {"1st row: Press F11 (or ESCAPE if key doesn't exist)", 0x4B, 1, CODE_ESCAPE},
85 {"1st row: Press F12 (or ESCAPE if key doesn't exist)", 0x6F, 1, CODE_ESCAPE},
87 {"2nd row: Press the key left of 1, or ESCAPE if there's no key left of 1", 0x00, 1, CODE_ESCAPE},
88 {"2nd row: Press 1 .. 0", 0x1, 10, CODE_NONE},
89 {"2nd row: Press the three normal (!!) keys right of 0. Press ESCAPE instead of third key if you only have two keys right of 0", 0X0B, 3, CODE_ESCAPE},
90 {"2nd row: Press BACKSPACE", 0x41, 1, CODE_NONE},
92 {"3rd row: Press TAB", 0x42, 1, CODE_NONE},
93 {"3rd row: Press the twelve keys right of TAB (= upto and excl. RETURN)", 0x10, 12, CODE_NONE},
94 {"3rd row: Press RETURN", 0x44, 1, CODE_NONE},
96 {"4th row: Press the (left) CONTROL key which might also be in 6th row", 0x63, 1, CODE_NONE},
97 {"4th row: Press CAPS LOCK", 0x62, 1, CODE_NONE},
98 {"4th row: Press the twelve keys right of CAPS LOCK. Press ESCAPE for last if you only have eleven keys there", 0x20, 12, CODE_ESCAPE},
100 {"5th row: Press LEFT SHIFT", 0x60, 1, CODE_NONE},
101 {"5th row: If in this row you have eleven normal keys, press the key right of LEFT SHIFT, otherwise ESCAPE", 0x30, 1, CODE_ESCAPE},
102 {"5th row: Press the next ten keys in this row (= upto and excl. RIGHT SHIFT)", 0x31, 10, CODE_NONE},
103 {"5th row: Press RIGHT SHIFT", 0x61, 1, CODE_NONE},
105 {"6th row: Press left ALT", 0x64, 1, CODE_NONE},
106 {"6th row: Press left AMIGA", 0x66, 1, CODE_NONE},
107 {"6th row: Press SPACE", 0x40, 1, CODE_NONE},
108 {"6th row: Press right AMIGA", 0x67, 1, CODE_NONE},
109 {"6th row: Press right ALT", 0x65, 1, CODE_NONE},
110 {"6th row: Press right CONTROL (or ESCAPE if key doesn't exist)", 0x63, 1, CODE_NONE},
112 {"Above cursor keys: Press INSERT (or ESCAPE if key doesn't exist)", 0x47, 1, CODE_ESCAPE},
113 {"Above cursor keys: Press HOME (or ESCAPE if key doesn't exist)", 0x70, 1, CODE_ESCAPE},
114 {"Above cursor keys: Press PAGE UP (or ESCAPE if key doesn't exist)", 0x48, 1, CODE_ESCAPE},
115 {"Above cursor keys: Press DELETE", 0x46, 1, CODE_NONE},
116 {"Above cursor keys: Press END (or ESCAPE if key doesn't exist)", 0x71, 1, CODE_ESCAPE},
117 {"Above cursor keys: Press PAGE DOWN (or ESCAPE if key doesn't exist)", 0x49, 1, CODE_ESCAPE},
118 {"Above cursor keys: Press HELP (or key you want to use for HELP if it doesn't exist)", 0x5F, 1, CODE_NONE},
120 {"Cursor keys: Press CURSOR UP", 0x4C, 1, CODE_NONE},
121 {"Cursor keys: Press CURSOR LEFT", 0x4F, 1, CODE_NONE},
122 {"Cursor keys: Press CURSOR DOWN", 0x4D, 1, CODE_NONE},
123 {"Cursor keys: Press CURSOR RIGHT", 0x4E, 1, CODE_NONE},
125 {"Numeric pad 1st row: Press the four keys above (!!!!) 7 8 9 (Or ESCAPE if keys do not exist)", 0x5A, 4, CODE_ESCAPE},
126 {"Numeric pad 2nd row: Press 7 8 9 (Or ESCAPE if keys do not exist)", 0x3D, 3, CODE_ESCAPE},
127 {"Numeric pad 2nd row: If key right of 9 is a normal size key press it, otherwise ESCAPE", 0x4A, 1, CODE_ESCAPE},
128 {"Numeric pad 3rd row: Press 4 5 6 (Or ESCAPE if keys do not exist)", 0x2D, 3, CODE_ESCAPE},
129 {"Numeric pad 3rd row: Press + (Or ESCAPE if key does not exist)", 0x5e, 1, CODE_ESCAPE},
130 {"Numeric pad 4th row: Press 1 2 3 (Or ESCAPE if keys do not exist)", 0x1D, 3, CODE_ESCAPE},
131 {"Numeric pad 5th row: Press 0 (Or ESCAPE if key does not exist)", 0x0F, 1, CODE_ESCAPE},
132 {"Numeric pad 5th row: Press COMMA (Or ESCAPE if key does not exist)", 0x3C, 1, CODE_ESCAPE},
133 {"Numeric pad 5th row: Press ENTER (Or ESCAPE if key does not exist)", 0x43, 1, CODE_ESCAPE},
134 {0, 0, 0, CODE_NONE}
137 /***************************************************************************/
139 void doaskuser(char *title,int rawkeystart, int numkeys, unsigned char sc);
141 /***************************************************************************/
143 void usage ()
145 static char *msg[] = {
146 " -o <filename> Table output file name",
148 NULL};
149 char **cpp;
151 fprintf (stderr, "usage: %s [-options ...]\n", ProgramName);
152 fprintf (stderr, "where options include:\n");
154 for (cpp = msg; *cpp; cpp++) {
155 fprintf (stderr, "%s\n", *cpp);
158 cleanup(1);
162 /***************************************************************************/
164 int main (int argc, char **argv)
166 char *tablefilename = NULL;
167 int i;
168 char *name = "Linux Scancode to Rawkey table generation tool";
169 struct _asktable *ask;
171 ProgramName = argv[0];
172 for (i = 1; i < argc; i++) {
173 char *arg = argv[i];
175 if (arg[0] == '-') {
176 switch (arg[1]) {
177 case 'o': /* table file name */
178 if (++i >= argc) usage ();
179 tablefilename = argv[i];
180 continue;
182 default:
183 usage ();
184 } /* end switch on - */
185 } else
186 usage ();
187 } /* end for over argc */
189 if (!tablefilename)
191 fprintf (stderr, "%s: output filename missing\n",
192 ProgramName);
193 cleanup(1);
196 printf("%s\n", name);
198 memset(table, 0xFF, 256);
200 if (!init_kbd()) {
201 fprintf(stderr, "Could not init keyboard\n");
202 cleanup(1);
206 for(ask = asktable; ask->title; ask++)
208 doaskuser(ask->title, ask->rawkeystart, ask->numkeys, ask->nokey_code);
211 fh = fopen(tablefilename,"wb");
212 if (!fh)
214 fprintf(stderr, "%s: unable to open \"%s\" in write mode\n",
215 ProgramName, tablefilename);
217 cleanup(1);
220 i = fwrite(table, 1, 256, fh);
221 if (i != 256)
223 fprintf (stderr, "%s: writing to \"%s\" failed\n",
224 ProgramName, tablefilename);
225 cleanup(1);
228 fclose(fh);
229 fh = 0;
231 cleanup(0);
233 return 0;
236 /***************************************************************************/
238 static int kbdfd;
239 static unsigned char lastcode = 0xFF;
241 void doaskuser(char *title,int rawkeystart, int numkeys, unsigned char actcode)
243 int i;
245 printf("%s\n", title);
248 for(i = 0;i < numkeys;)
250 /* printf("IN OUTER LOOP, i=%d, numkeys=%d, lastcode=0x%x\n", i, numkeys, lastcode);
251 */ for (;;) {
252 int bytesread;
253 unsigned char code;
254 int exitloop = FALSE;
257 bytesread = read(kbdfd, &code, 1);
258 if (code != lastcode && code < 0x80) {
259 /* printf("Got key down: 0x%x, actcode=0x%x, lastocode: 0x%x\n"
260 , code, actcode, lastcode);
261 */ if (actcode == CODE_NONE || actcode != code) {
262 printf("SETTING IN TABLE\n");
263 table[code] = rawkeystart + i;
264 exitloop = TRUE;
266 if (actcode == CODE_ESCAPE && actcode == code)
267 exitloop = TRUE;
270 /* if (code >= 0x80)
271 printf("Got key up: 0x%x\n", code);
273 lastcode = code;
274 /* printf("SETING LASTCODE 0x%x AND EXITING LOOP\n", lastcode);
275 */ if (exitloop)
276 break;
278 i ++;
280 } /* for(i = 0;i < numkeys;) */
285 int set_kbd_mode(int fd, int mode, int *oldmode)
287 /* Get and preserve the old kbd mode */
288 if (NULL != oldmode) {
289 if (-1 == ioctl(fd, KDGKBMODE, oldmode)) {
290 fprintf(stderr, "Unable to get old kbd mode: %s\n", strerror(errno));
291 return 0;
295 /* Set the new mode */
296 if (-1 == ioctl(fd, KDSKBMODE, mode)) {
297 fprintf(stderr, "Unable to set new kbd mode: %s\n", strerror(errno));
298 return 0;
301 return 1;
305 static int oldkbdmode;
306 static struct termios oldtio;
307 static struct kbd_repeat repeat;
309 int mode_done = FALSE
310 , fd_done = FALSE
311 , termios_done = FALSE
312 , repeat_done = FALSE;
314 #define KBD_DEVNAME "/dev/console"
316 int init_kbd()
318 int ret = TRUE;
319 printf("INIT_KBD\n");
321 kbdfd = open(KBD_DEVNAME, O_RDONLY);
322 if (-1 == kbdfd) {
323 fprintf(stderr, "!!! Could not open keyboard device: %s\n", strerror(errno));
324 ret = FALSE;
325 } else {
326 /* Try to read some data from the keyboard */
327 struct termios newtio;
329 fd_done = TRUE;
332 setup_sighandling();
334 printf("SIGNALS SETUP\n");
335 if ( (-1 == tcgetattr(kbdfd, &oldtio)) || (-1 == tcgetattr(kbdfd, &newtio))) {
336 fprintf(stderr, "!!! Could not get old termios attrs: %s\n", strerror(errno));
337 ret = FALSE;
338 } else {
339 /* Set some new attrs */
340 newtio.c_lflag = ~(ICANON | ECHO | ISIG);
341 newtio.c_iflag = 0;
342 newtio.c_cc[VMIN] = 1;
343 newtio.c_cc[VTIME] = 0;
345 if (-1 == tcsetattr(kbdfd, TCSAFLUSH, &newtio)) {
346 fprintf(stderr, "!!! Could not set new termio: %s\n", strerror(errno));
347 ret = FALSE;
348 } else {
349 termios_done = TRUE;
350 printf("SET TERMIO ATTRS\n");
351 if (!set_kbd_mode(kbdfd, K_MEDIUMRAW, &oldkbdmode)) {
352 fprintf(stderr, "!!! Could not set kbdmode\n");
353 ret = FALSE;
354 } else {
355 printf("KBD MODE SET\n");
356 mode_done = TRUE;
357 /* Set keyboard repeat */
358 repeat.delay = 100000;
359 repeat.rate = 100000;
360 if (-1 == ioctl(kbdfd, KDKBDREP, &repeat)) {
361 fprintf(stderr, "!!!! Could not set keyboard repeat: %s\n", strerror(errno));
362 } else {
363 repeat_done = TRUE;
364 ret = TRUE;
368 } /* if (termios attrs set) */
369 } /* if (got old termios attrs) */
372 if (!ret) {
373 cleanup_kbd();
376 return ret;
380 void cleanup_kbd()
382 if (repeat_done)
383 ioctl(kbdfd, KDKBDREP, &repeat);
384 /* Reset the kbd mode */
385 if (mode_done)
386 set_kbd_mode(kbdfd, oldkbdmode, NULL);
388 if (termios_done)
389 tcsetattr(kbdfd, TCSAFLUSH, &oldtio);
391 if (fd_done)
392 close(kbdfd);
394 cleanup_sighandling();
396 return;
399 const int signals[] = {
400 SIGHUP, SIGINT, SIGQUIT, SIGILL,
401 SIGTRAP, SIGBUS, SIGFPE, SIGKILL,
402 SIGALRM, SIGSEGV , SIGTERM
406 void exit_sighandler(int sig)
408 printf("PARENT EXITING VIA SIGHANDLER\n");
409 cleanup(0);
412 void kbdsighandler(int sig)
414 cleanup_kbd();
417 /* Avoid that some signal kills us without resetting the keyboard */
418 void setup_sighandling(void)
420 unsigned int i;
422 for (i = 0; i < sizeof (signals); i ++) {
423 signal(signals[i], kbdsighandler);
426 /* signal(SIGALRM, exit_sighandler);
427 alarm(200);
431 void cleanup_sighandling()
433 unsigned int i;
434 for (i = 0; i < sizeof (signals); i ++) {
435 signal(signals[i], SIG_DFL);
439 void cleanup(int exitcode)
441 cleanup_kbd();
442 exit (0);