1 /* $XConsortium: xev.c,v 1.15 94/04/17 20:45:20 keith Exp $ */
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 /***************************************************************************/
44 #include <sys/signal.h>
47 #include <sys/ioctl.h>
55 void cleanup_sighandling();
56 void setup_sighandling();
62 /***************************************************************************/
65 static char *ProgramName
;
68 static unsigned char table
[256];
70 /***************************************************************************/
72 #define CODE_NONE 0xFF
73 #define CODE_ESCAPE 0x01
74 static struct _asktable
79 unsigned char nokey_code
;
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
},
137 /***************************************************************************/
139 void doaskuser(char *title
,int rawkeystart
, int numkeys
, unsigned char sc
);
141 /***************************************************************************/
145 static char *msg
[] = {
146 " -o <filename> Table output file name",
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
);
162 /***************************************************************************/
164 int main (int argc
, char **argv
)
166 char *tablefilename
= NULL
;
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
++) {
177 case 'o': /* table file name */
178 if (++i
>= argc
) usage ();
179 tablefilename
= argv
[i
];
184 } /* end switch on - */
187 } /* end for over argc */
191 fprintf (stderr
, "%s: output filename missing\n",
196 printf("%s\n", name
);
198 memset(table
, 0xFF, 256);
201 fprintf(stderr
, "Could not init keyboard\n");
206 for(ask
= asktable
; ask
->title
; ask
++)
208 doaskuser(ask
->title
, ask
->rawkeystart
, ask
->numkeys
, ask
->nokey_code
);
211 fh
= fopen(tablefilename
,"wb");
214 fprintf(stderr
, "%s: unable to open \"%s\" in write mode\n",
215 ProgramName
, tablefilename
);
220 i
= fwrite(table
, 1, 256, fh
);
223 fprintf (stderr
, "%s: writing to \"%s\" failed\n",
224 ProgramName
, tablefilename
);
236 /***************************************************************************/
239 static unsigned char lastcode
= 0xFF;
241 void doaskuser(char *title
,int rawkeystart
, int numkeys
, unsigned char actcode
)
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);
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
;
266 if (actcode
== CODE_ESCAPE
&& actcode
== code
)
271 printf("Got key up: 0x%x\n", code);
274 /* printf("SETING LASTCODE 0x%x AND EXITING LOOP\n", lastcode);
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
));
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
));
305 static int oldkbdmode
;
306 static struct termios oldtio
;
307 static struct kbd_repeat repeat
;
309 int mode_done
= FALSE
311 , termios_done
= FALSE
312 , repeat_done
= FALSE
;
314 #define KBD_DEVNAME "/dev/console"
319 printf("INIT_KBD\n");
321 kbdfd
= open(KBD_DEVNAME
, O_RDONLY
);
323 fprintf(stderr
, "!!! Could not open keyboard device: %s\n", strerror(errno
));
326 /* Try to read some data from the keyboard */
327 struct termios newtio
;
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
));
339 /* Set some new attrs */
340 newtio
.c_lflag
= ~(ICANON
| ECHO
| ISIG
);
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
));
350 printf("SET TERMIO ATTRS\n");
351 if (!set_kbd_mode(kbdfd
, K_MEDIUMRAW
, &oldkbdmode
)) {
352 fprintf(stderr
, "!!! Could not set kbdmode\n");
355 printf("KBD MODE SET\n");
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
));
368 } /* if (termios attrs set) */
369 } /* if (got old termios attrs) */
383 ioctl(kbdfd
, KDKBDREP
, &repeat
);
384 /* Reset the kbd mode */
386 set_kbd_mode(kbdfd
, oldkbdmode
, NULL
);
389 tcsetattr(kbdfd
, TCSAFLUSH
, &oldtio
);
394 cleanup_sighandling();
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");
412 void kbdsighandler(int sig
)
417 /* Avoid that some signal kills us without resetting the keyboard */
418 void setup_sighandling(void)
422 for (i
= 0; i
< sizeof (signals
); i
++) {
423 signal(signals
[i
], kbdsighandler
);
426 /* signal(SIGALRM, exit_sighandler);
431 void cleanup_sighandling()
434 for (i
= 0; i
< sizeof (signals
); i
++) {
435 signal(signals
[i
], SIG_DFL
);
439 void cleanup(int exitcode
)