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