]>
Commit | Line | Data |
---|---|---|
b6f7b4ba CPE |
1 | /* |
2 | * GRUB -- GRand Unified Bootloader | |
3 | * Copyright (C) 2010 Free Software Foundation, Inc. | |
4 | * | |
5 | * GRUB is free software: you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation, either version 3 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * GRUB is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
1d12cf29 YB |
19 | #include <config.h> |
20 | ||
b6f7b4ba CPE |
21 | #include <grub/util/misc.h> |
22 | #include <grub/i18n.h> | |
23 | #include <grub/term.h> | |
24 | #include <grub/keyboard_layouts.h> | |
b6f7b4ba CPE |
25 | |
26 | #include <stdio.h> | |
27 | #include <stdlib.h> | |
28 | #include <string.h> | |
29 | #include <getopt.h> | |
30 | #include <unistd.h> | |
5a3e99b3 | 31 | #include <errno.h> |
b6f7b4ba CPE |
32 | |
33 | #include "progname.h" | |
34 | ||
35 | #define CKBCOMP "ckbcomp" | |
36 | ||
37 | static struct option options[] = { | |
38 | {"output", required_argument, 0, 'o'}, | |
39 | {"help", no_argument, 0, 'h'}, | |
40 | {"version", no_argument, 0, 'V'}, | |
41 | {"verbose", no_argument, 0, 'v'}, | |
42 | {0, 0, 0, 0} | |
43 | }; | |
44 | ||
45 | struct console_grub_equivalence | |
46 | { | |
47 | char *layout; | |
48 | grub_uint32_t grub; | |
49 | }; | |
50 | ||
c32f26bc VS |
51 | static struct console_grub_equivalence console_grub_equivalences_shift[] = { |
52 | {"KP_0", '0'}, | |
53 | {"KP_1", '1'}, | |
54 | {"KP_2", '2'}, | |
55 | {"KP_3", '3'}, | |
56 | {"KP_4", '4'}, | |
57 | {"KP_5", '5'}, | |
58 | {"KP_6", '6'}, | |
59 | {"KP_7", '7'}, | |
60 | {"KP_8", '8'}, | |
61 | {"KP_9", '9'}, | |
62 | {"KP_Period", '.'}, | |
63 | }; | |
64 | ||
65 | static struct console_grub_equivalence console_grub_equivalences_unshift[] = { | |
66 | {"KP_0", GRUB_TERM_KEY_INSERT}, | |
67 | {"KP_1", GRUB_TERM_KEY_END}, | |
68 | {"KP_2", GRUB_TERM_KEY_DOWN}, | |
69 | {"KP_3", GRUB_TERM_KEY_NPAGE}, | |
70 | {"KP_4", GRUB_TERM_KEY_LEFT}, | |
71 | {"KP_5", GRUB_TERM_KEY_CENTER}, | |
72 | {"KP_6", GRUB_TERM_KEY_RIGHT}, | |
73 | {"KP_7", GRUB_TERM_KEY_HOME}, | |
74 | {"KP_8", GRUB_TERM_KEY_UP}, | |
75 | {"KP_9", GRUB_TERM_KEY_PPAGE}, | |
76 | {"KP_Period", GRUB_TERM_KEY_DC}, | |
77 | }; | |
78 | ||
79 | static struct console_grub_equivalence console_grub_equivalences_common[] = { | |
b09634f0 VS |
80 | {"Escape", GRUB_TERM_ESC}, |
81 | {"Tab", GRUB_TERM_TAB}, | |
82 | {"Delete", GRUB_TERM_BACKSPACE}, | |
83 | ||
c32f26bc VS |
84 | {"KP_Enter", '\n'}, |
85 | {"Return", '\n'}, | |
86 | ||
b6f7b4ba | 87 | {"KP_Multiply", '*'}, |
b1752041 | 88 | {"KP_Subtract", '-'}, |
b6f7b4ba CPE |
89 | {"KP_Add", '+'}, |
90 | {"KP_Divide", '/'}, | |
91 | ||
b1752041 VS |
92 | {"F1", GRUB_TERM_KEY_F1}, |
93 | {"F2", GRUB_TERM_KEY_F2}, | |
94 | {"F3", GRUB_TERM_KEY_F3}, | |
95 | {"F4", GRUB_TERM_KEY_F4}, | |
96 | {"F5", GRUB_TERM_KEY_F5}, | |
97 | {"F6", GRUB_TERM_KEY_F6}, | |
98 | {"F7", GRUB_TERM_KEY_F7}, | |
99 | {"F8", GRUB_TERM_KEY_F8}, | |
100 | {"F9", GRUB_TERM_KEY_F9}, | |
101 | {"F10", GRUB_TERM_KEY_F10}, | |
102 | {"F11", GRUB_TERM_KEY_F11}, | |
103 | {"F12", GRUB_TERM_KEY_F12}, | |
104 | {"F13", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT}, | |
105 | {"F14", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT}, | |
106 | {"F15", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT}, | |
107 | {"F16", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT}, | |
108 | {"F17", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT}, | |
109 | {"F18", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT}, | |
110 | {"F19", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT}, | |
111 | {"F20", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT}, | |
112 | {"F21", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT}, | |
113 | {"F22", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT}, | |
114 | {"F23", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT}, | |
115 | {"F24", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT}, | |
116 | {"Console_13", GRUB_TERM_KEY_F1 | GRUB_TERM_ALT}, | |
117 | {"Console_14", GRUB_TERM_KEY_F2 | GRUB_TERM_ALT}, | |
118 | {"Console_15", GRUB_TERM_KEY_F3 | GRUB_TERM_ALT}, | |
119 | {"Console_16", GRUB_TERM_KEY_F4 | GRUB_TERM_ALT}, | |
120 | {"Console_17", GRUB_TERM_KEY_F5 | GRUB_TERM_ALT}, | |
121 | {"Console_18", GRUB_TERM_KEY_F6 | GRUB_TERM_ALT}, | |
122 | {"Console_19", GRUB_TERM_KEY_F7 | GRUB_TERM_ALT}, | |
123 | {"Console_20", GRUB_TERM_KEY_F8 | GRUB_TERM_ALT}, | |
124 | {"Console_21", GRUB_TERM_KEY_F9 | GRUB_TERM_ALT}, | |
125 | {"Console_22", GRUB_TERM_KEY_F10 | GRUB_TERM_ALT}, | |
126 | {"Console_23", GRUB_TERM_KEY_F11 | GRUB_TERM_ALT}, | |
127 | {"Console_24", GRUB_TERM_KEY_F12 | GRUB_TERM_ALT}, | |
128 | {"Console_25", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
129 | {"Console_26", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
130 | {"Console_27", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
131 | {"Console_28", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
132 | {"Console_29", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
133 | {"Console_30", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
134 | {"Console_31", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
135 | {"Console_32", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
136 | {"Console_33", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
137 | {"Console_34", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
138 | {"Console_35", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
139 | {"Console_36", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, | |
140 | ||
141 | {"Insert", GRUB_TERM_KEY_INSERT}, | |
142 | {"Down", GRUB_TERM_KEY_DOWN}, | |
143 | {"Up", GRUB_TERM_KEY_UP}, | |
144 | {"Home", GRUB_TERM_KEY_HOME}, | |
145 | {"End", GRUB_TERM_KEY_END}, | |
146 | {"Right", GRUB_TERM_KEY_RIGHT}, | |
147 | {"Left", GRUB_TERM_KEY_LEFT}, | |
c32f26bc VS |
148 | {"Next", GRUB_TERM_KEY_NPAGE}, |
149 | {"Prior", GRUB_TERM_KEY_PPAGE}, | |
150 | {"Remove", GRUB_TERM_KEY_DC}, | |
b1752041 VS |
151 | {"VoidSymbol", 0}, |
152 | ||
153 | /* "Undead" keys since no dead key support in GRUB. */ | |
154 | {"dead_acute", '\''}, | |
155 | {"dead_circumflex", '^'}, | |
156 | {"dead_grave", '`'}, | |
157 | {"dead_tilde", '~'}, | |
158 | {"dead_diaeresis", '"'}, | |
159 | ||
160 | /* Following ones don't provide any useful symbols for shell. */ | |
161 | {"dead_cedilla", 0}, | |
162 | {"dead_ogonek", 0}, | |
163 | {"dead_caron", 0}, | |
164 | {"dead_breve", 0}, | |
165 | {"dead_doubleacute", 0}, | |
166 | ||
b1752041 VS |
167 | /* Unused in GRUB. */ |
168 | {"Pause", 0}, | |
b1752041 VS |
169 | {"Scroll_Forward", 0}, |
170 | {"Scroll_Backward", 0}, | |
171 | {"Hex_0", 0}, | |
172 | {"Hex_1", 0}, | |
173 | {"Hex_2", 0}, | |
174 | {"Hex_3", 0}, | |
175 | {"Hex_4", 0}, | |
176 | {"Hex_5", 0}, | |
177 | {"Hex_6", 0}, | |
178 | {"Hex_7", 0}, | |
179 | {"Hex_8", 0}, | |
180 | {"Hex_9", 0}, | |
181 | {"Hex_A", 0}, | |
182 | {"Hex_B", 0}, | |
183 | {"Hex_C", 0}, | |
184 | {"Hex_D", 0}, | |
185 | {"Hex_E", 0}, | |
186 | {"Hex_F", 0}, | |
187 | {"Scroll_Lock", 0}, | |
188 | {"Show_Memory", 0}, | |
189 | {"Show_Registers", 0}, | |
190 | {"Control_backslash", 0}, | |
8bb7e816 | 191 | {"Compose", 0}, |
b1752041 | 192 | |
b1752041 | 193 | {NULL, '\0'} |
b6f7b4ba CPE |
194 | }; |
195 | ||
5ea70ca5 | 196 | static grub_uint8_t linux_to_usb_map[128] = { |
09206dc3 VS |
197 | /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, |
198 | /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, | |
199 | /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, | |
200 | /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, | |
201 | /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, | |
202 | /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, | |
203 | /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, | |
204 | /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, | |
205 | /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, | |
206 | /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, | |
207 | /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, | |
208 | /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, | |
209 | /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, | |
210 | /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, | |
211 | /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, | |
212 | /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, | |
213 | /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, | |
214 | /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, | |
215 | /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, | |
216 | /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, | |
217 | /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, | |
218 | /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, | |
219 | /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, | |
220 | /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, | |
221 | /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, | |
222 | /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, | |
223 | /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, | |
224 | /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, | |
225 | /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, | |
226 | /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, | |
227 | /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, | |
228 | /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, | |
229 | /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, | |
230 | /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, | |
231 | /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, | |
232 | /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, | |
233 | /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, | |
234 | /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, | |
235 | /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, | |
236 | /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, | |
237 | /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, | |
238 | /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, | |
239 | /* 0x54 */ 0, 0, | |
240 | /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, | |
241 | /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, | |
242 | /* 0x5a */ 0, 0, | |
243 | /* 0x5c */ 0, 0, | |
244 | /* 0x5e */ 0, 0, | |
245 | /* 0x60 */ GRUB_KEYBOARD_KEY_NUMENTER, GRUB_KEYBOARD_KEY_RIGHT_CTRL, | |
246 | /* 0x62 */ GRUB_KEYBOARD_KEY_NUMSLASH, 0, | |
247 | /* 0x64 */ GRUB_KEYBOARD_KEY_RIGHT_ALT, 0, | |
248 | /* 0x66 */ GRUB_KEYBOARD_KEY_HOME, GRUB_KEYBOARD_KEY_UP, | |
400ef90d | 249 | /* 0x68 */ GRUB_KEYBOARD_KEY_PPAGE, GRUB_KEYBOARD_KEY_LEFT, |
09206dc3 | 250 | /* 0x6a */ GRUB_KEYBOARD_KEY_RIGHT, GRUB_KEYBOARD_KEY_END, |
400ef90d | 251 | /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_NPAGE, |
09206dc3 | 252 | /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE |
5ea70ca5 VS |
253 | }; |
254 | ||
b6f7b4ba CPE |
255 | static void |
256 | usage (int status) | |
257 | { | |
258 | if (status) | |
259 | fprintf (stderr, "Try `%s --help' for more information.\n", program_name); | |
260 | else | |
261 | printf ("\ | |
6fef99b4 VS |
262 | Usage: %s [OPTIONS]\n\ |
263 | -i, --input set input filename. Default is STDIN\n\ | |
264 | -o, --output set output filename. Default is STDOUT\n\ | |
b6f7b4ba CPE |
265 | -h, --help display this message and exit.\n\ |
266 | -V, --version print version information and exit.\n\ | |
267 | -v, --verbose print verbose messages.\n\ | |
268 | \n\ | |
269 | Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); | |
270 | ||
271 | exit (status); | |
272 | } | |
273 | ||
c32f26bc | 274 | static void |
e55e0962 VS |
275 | add_special_keys (struct grub_keyboard_layout *layout) |
276 | { | |
c32f26bc | 277 | (void) layout; |
e55e0962 VS |
278 | } |
279 | ||
0b335a97 | 280 | static unsigned |
c32f26bc | 281 | lookup (char *code, int shift) |
b6f7b4ba CPE |
282 | { |
283 | int i; | |
c32f26bc VS |
284 | struct console_grub_equivalence *pr; |
285 | ||
286 | if (shift) | |
287 | pr = console_grub_equivalences_shift; | |
288 | else | |
289 | pr = console_grub_equivalences_unshift; | |
b6f7b4ba | 290 | |
c32f26bc VS |
291 | for (i = 0; pr[i].layout != NULL; i++) |
292 | if (strcmp (code, pr[i].layout) == 0) | |
293 | return pr[i].grub; | |
294 | ||
295 | for (i = 0; console_grub_equivalences_common[i].layout != NULL; i++) | |
296 | if (strcmp (code, console_grub_equivalences_common[i].layout) == 0) | |
297 | return console_grub_equivalences_common[i].grub; | |
b6f7b4ba | 298 | |
8bb7e816 | 299 | fprintf (stderr, "Unknown key %s\n", code); |
b1752041 | 300 | |
b6f7b4ba CPE |
301 | return '\0'; |
302 | } | |
303 | ||
e55e0962 | 304 | static unsigned int |
c32f26bc | 305 | get_grub_code (char *layout_code, int shift) |
b6f7b4ba CPE |
306 | { |
307 | unsigned int code; | |
308 | ||
309 | if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0) | |
310 | sscanf (layout_code, "U+%x", &code); | |
311 | else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0) | |
312 | sscanf (layout_code, "+U+%x", &code); | |
313 | else | |
c32f26bc | 314 | code = lookup (layout_code, shift); |
b6f7b4ba CPE |
315 | return code; |
316 | } | |
317 | ||
e55e0962 | 318 | static void |
5a3e99b3 | 319 | write_file (FILE *out, struct grub_keyboard_layout *layout) |
b6f7b4ba | 320 | { |
b6f7b4ba CPE |
321 | grub_uint32_t version; |
322 | unsigned i; | |
323 | ||
324 | version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); | |
325 | ||
5ef4e084 VS |
326 | for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++) |
327 | layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]); | |
e55e0962 | 328 | |
5ef4e084 VS |
329 | for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift); i++) |
330 | layout->keyboard_map_shift[i] | |
331 | = grub_cpu_to_le32(layout->keyboard_map_shift[i]); | |
e55e0962 | 332 | |
5ef4e084 VS |
333 | for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_l3); i++) |
334 | layout->keyboard_map_l3[i] | |
335 | = grub_cpu_to_le32(layout->keyboard_map_l3[i]); | |
e55e0962 | 336 | |
5ef4e084 VS |
337 | for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift_l3); i++) |
338 | layout->keyboard_map_shift_l3[i] | |
339 | = grub_cpu_to_le32(layout->keyboard_map_shift_l3[i]); | |
eb628338 | 340 | |
b6f7b4ba | 341 | fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, |
5a3e99b3 VS |
342 | GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, out); |
343 | fwrite (&version, sizeof (version), 1, out); | |
344 | fwrite (layout, 1, sizeof (*layout), out); | |
b6f7b4ba CPE |
345 | } |
346 | ||
e55e0962 | 347 | static void |
5a3e99b3 | 348 | write_keymaps (FILE *in, FILE *out) |
b6f7b4ba | 349 | { |
e55e0962 | 350 | struct grub_keyboard_layout layout; |
b6f7b4ba | 351 | char line[2048]; |
b6f7b4ba CPE |
352 | int ok; |
353 | ||
e55e0962 | 354 | memset (&layout, 0, sizeof (layout)); |
b6f7b4ba CPE |
355 | |
356 | /* Process the ckbcomp output and prepare the layouts. */ | |
357 | ok = 0; | |
5a3e99b3 | 358 | while (fgets (line, sizeof (line), in)) |
b6f7b4ba CPE |
359 | { |
360 | if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) | |
361 | { | |
5ea70ca5 | 362 | unsigned keycode_linux; |
c32f26bc | 363 | unsigned keycode_usb; |
b6f7b4ba CPE |
364 | char normal[64]; |
365 | char shift[64]; | |
eb628338 VS |
366 | char normalalt[64]; |
367 | char shiftalt[64]; | |
5ea70ca5 VS |
368 | |
369 | sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_linux, | |
eb628338 | 370 | normal, shift, normalalt, shiftalt); |
c32f26bc VS |
371 | |
372 | /* Not used. */ | |
5ea70ca5 | 373 | if (keycode_linux == 0x77 /* Pause */ |
c32f26bc | 374 | /* Some obscure keys */ |
5ea70ca5 VS |
375 | || keycode_linux == 0x63 || keycode_linux == 0x7d |
376 | || keycode_linux == 0x7e) | |
c32f26bc VS |
377 | continue; |
378 | ||
c32f26bc | 379 | /* Not remappable. */ |
5ea70ca5 | 380 | if (keycode_linux == 0x1d /* Left CTRL */ |
9f5a5ad5 | 381 | || keycode_linux == 0x61 /* Right CTRL */ |
5ea70ca5 VS |
382 | || keycode_linux == 0x2a /* Left Shift. */ |
383 | || keycode_linux == 0x36 /* Right Shift. */ | |
384 | || keycode_linux == 0x38 /* Left ALT. */ | |
9f5a5ad5 | 385 | || keycode_linux == 0x64 /* Right ALT. */ |
5ea70ca5 VS |
386 | || keycode_linux == 0x3a /* CapsLock. */ |
387 | || keycode_linux == 0x45 /* NumLock. */ | |
388 | || keycode_linux == 0x46 /* ScrollLock. */) | |
c32f26bc VS |
389 | continue; |
390 | ||
5ea70ca5 | 391 | keycode_usb = linux_to_usb_map[keycode_linux]; |
c32f26bc VS |
392 | if (keycode_usb == 0 |
393 | || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) | |
394 | { | |
5ea70ca5 | 395 | fprintf (stderr, "Unknown keycode 0x%02x\n", keycode_linux); |
c32f26bc VS |
396 | continue; |
397 | } | |
398 | if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) | |
e55e0962 | 399 | { |
c32f26bc VS |
400 | layout.keyboard_map[keycode_usb] = get_grub_code (normal, 0); |
401 | layout.keyboard_map_shift[keycode_usb] = get_grub_code (shift, 1); | |
402 | layout.keyboard_map_l3[keycode_usb] | |
403 | = get_grub_code (normalalt, 0); | |
404 | layout.keyboard_map_shift_l3[keycode_usb] | |
405 | = get_grub_code (shiftalt, 1); | |
e55e0962 VS |
406 | ok = 1; |
407 | } | |
b6f7b4ba CPE |
408 | } |
409 | } | |
410 | ||
411 | if (ok == 0) | |
412 | { | |
b1752041 VS |
413 | fprintf (stderr, "ERROR: no keycodes found. Check output of %s.\n", |
414 | CKBCOMP); | |
b6f7b4ba CPE |
415 | exit (1); |
416 | } | |
417 | ||
e55e0962 VS |
418 | add_special_keys (&layout); |
419 | ||
5a3e99b3 | 420 | write_file (out, &layout); |
b6f7b4ba CPE |
421 | } |
422 | ||
423 | int | |
424 | main (int argc, char *argv[]) | |
425 | { | |
426 | int verbosity; | |
5a3e99b3 VS |
427 | char *infile_name = NULL; |
428 | char *outfile_name = NULL; | |
429 | FILE *in, *out; | |
b6f7b4ba CPE |
430 | |
431 | set_program_name (argv[0]); | |
432 | ||
433 | verbosity = 0; | |
434 | ||
435 | /* Check for options. */ | |
436 | while (1) | |
437 | { | |
5a3e99b3 | 438 | int c = getopt_long (argc, argv, "o:i:hVv", options, 0); |
b6f7b4ba CPE |
439 | |
440 | if (c == -1) | |
441 | break; | |
442 | else | |
443 | switch (c) | |
444 | { | |
445 | case 'h': | |
446 | usage (0); | |
447 | break; | |
448 | ||
5a3e99b3 VS |
449 | case 'i': |
450 | infile_name = optarg; | |
451 | break; | |
452 | ||
b6f7b4ba | 453 | case 'o': |
5a3e99b3 | 454 | outfile_name = optarg; |
b6f7b4ba CPE |
455 | break; |
456 | ||
457 | case 'V': | |
458 | printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, | |
459 | PACKAGE_VERSION); | |
460 | return 0; | |
461 | ||
462 | case 'v': | |
463 | verbosity++; | |
464 | break; | |
465 | ||
466 | default: | |
467 | usage (1); | |
468 | break; | |
469 | } | |
470 | } | |
471 | ||
5a3e99b3 VS |
472 | if (infile_name) |
473 | in = fopen (infile_name, "r"); | |
474 | else | |
475 | in = stdin; | |
476 | ||
477 | if (!in) | |
478 | grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); | |
b6f7b4ba | 479 | |
5a3e99b3 | 480 | if (outfile_name) |
8bb7e816 | 481 | out = fopen (outfile_name, "wb"); |
5a3e99b3 VS |
482 | else |
483 | out = stdout; | |
484 | ||
485 | if (!out) | |
b6f7b4ba | 486 | { |
5a3e99b3 VS |
487 | if (in != stdin) |
488 | fclose (in); | |
8bb7e816 | 489 | grub_util_error ("Couldn't open output file: %s\n", strerror (errno)); |
b6f7b4ba | 490 | } |
5a3e99b3 VS |
491 | |
492 | write_keymaps (in, out); | |
493 | ||
494 | if (in != stdin) | |
495 | fclose (in); | |
496 | ||
497 | if (out != stdout) | |
498 | fclose (out); | |
b6f7b4ba CPE |
499 | |
500 | return 0; | |
501 | } |