2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2010 Free Software Foundation, Inc.
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.
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.
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/>.
19 #include <grub/util/misc.h>
20 #include <grub/i18n.h>
21 #include <grub/term.h>
22 #include <grub/keyboard_layouts.h>
23 #include <grub/at_keyboard.h>
34 #define CKBCOMP "ckbcomp"
36 static struct option options
[] = {
37 {"output", required_argument
, 0, 'o'},
38 {"help", no_argument
, 0, 'h'},
39 {"version", no_argument
, 0, 'V'},
40 {"verbose", no_argument
, 0, 'v'},
44 struct console_grub_equivalence
50 static struct console_grub_equivalence console_grub_equivalences
[] = {
51 {"Escape", GRUB_TERM_ESC
},
52 {"Tab", GRUB_TERM_TAB
},
53 {"Delete", GRUB_TERM_BACKSPACE
},
63 {"F1", GRUB_TERM_KEY_F1
},
64 {"F2", GRUB_TERM_KEY_F2
},
65 {"F3", GRUB_TERM_KEY_F3
},
66 {"F4", GRUB_TERM_KEY_F4
},
67 {"F5", GRUB_TERM_KEY_F5
},
68 {"F6", GRUB_TERM_KEY_F6
},
69 {"F7", GRUB_TERM_KEY_F7
},
70 {"F8", GRUB_TERM_KEY_F8
},
71 {"F9", GRUB_TERM_KEY_F9
},
72 {"F10", GRUB_TERM_KEY_F10
},
73 {"F11", GRUB_TERM_KEY_F11
},
74 {"F12", GRUB_TERM_KEY_F12
},
75 {"F13", GRUB_TERM_KEY_F1
| GRUB_TERM_SHIFT
},
76 {"F14", GRUB_TERM_KEY_F2
| GRUB_TERM_SHIFT
},
77 {"F15", GRUB_TERM_KEY_F3
| GRUB_TERM_SHIFT
},
78 {"F16", GRUB_TERM_KEY_F4
| GRUB_TERM_SHIFT
},
79 {"F17", GRUB_TERM_KEY_F5
| GRUB_TERM_SHIFT
},
80 {"F18", GRUB_TERM_KEY_F6
| GRUB_TERM_SHIFT
},
81 {"F19", GRUB_TERM_KEY_F7
| GRUB_TERM_SHIFT
},
82 {"F20", GRUB_TERM_KEY_F8
| GRUB_TERM_SHIFT
},
83 {"F21", GRUB_TERM_KEY_F9
| GRUB_TERM_SHIFT
},
84 {"F22", GRUB_TERM_KEY_F10
| GRUB_TERM_SHIFT
},
85 {"F23", GRUB_TERM_KEY_F11
| GRUB_TERM_SHIFT
},
86 {"F24", GRUB_TERM_KEY_F12
| GRUB_TERM_SHIFT
},
87 {"Console_13", GRUB_TERM_KEY_F1
| GRUB_TERM_ALT
},
88 {"Console_14", GRUB_TERM_KEY_F2
| GRUB_TERM_ALT
},
89 {"Console_15", GRUB_TERM_KEY_F3
| GRUB_TERM_ALT
},
90 {"Console_16", GRUB_TERM_KEY_F4
| GRUB_TERM_ALT
},
91 {"Console_17", GRUB_TERM_KEY_F5
| GRUB_TERM_ALT
},
92 {"Console_18", GRUB_TERM_KEY_F6
| GRUB_TERM_ALT
},
93 {"Console_19", GRUB_TERM_KEY_F7
| GRUB_TERM_ALT
},
94 {"Console_20", GRUB_TERM_KEY_F8
| GRUB_TERM_ALT
},
95 {"Console_21", GRUB_TERM_KEY_F9
| GRUB_TERM_ALT
},
96 {"Console_22", GRUB_TERM_KEY_F10
| GRUB_TERM_ALT
},
97 {"Console_23", GRUB_TERM_KEY_F11
| GRUB_TERM_ALT
},
98 {"Console_24", GRUB_TERM_KEY_F12
| GRUB_TERM_ALT
},
99 {"Console_25", GRUB_TERM_KEY_F1
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
100 {"Console_26", GRUB_TERM_KEY_F2
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
101 {"Console_27", GRUB_TERM_KEY_F3
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
102 {"Console_28", GRUB_TERM_KEY_F4
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
103 {"Console_29", GRUB_TERM_KEY_F5
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
104 {"Console_30", GRUB_TERM_KEY_F6
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
105 {"Console_31", GRUB_TERM_KEY_F7
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
106 {"Console_32", GRUB_TERM_KEY_F8
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
107 {"Console_33", GRUB_TERM_KEY_F9
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
108 {"Console_34", GRUB_TERM_KEY_F10
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
109 {"Console_35", GRUB_TERM_KEY_F11
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
110 {"Console_36", GRUB_TERM_KEY_F12
| GRUB_TERM_SHIFT
| GRUB_TERM_ALT
},
112 {"Insert", GRUB_TERM_KEY_INSERT
},
113 {"Down", GRUB_TERM_KEY_DOWN
},
114 {"Up", GRUB_TERM_KEY_UP
},
115 {"Home", GRUB_TERM_KEY_HOME
},
116 {"End", GRUB_TERM_KEY_END
},
117 {"Right", GRUB_TERM_KEY_RIGHT
},
118 {"Left", GRUB_TERM_KEY_LEFT
},
121 /* "Undead" keys since no dead key support in GRUB. */
122 {"dead_acute", '\''},
123 {"dead_circumflex", '^'},
126 {"dead_diaeresis", '"'},
128 /* Following ones don't provide any useful symbols for shell. */
133 {"dead_doubleacute", 0},
135 /* NumLock not supported yet. */
136 {"KP_0", GRUB_TERM_KEY_INSERT
},
137 {"KP_1", GRUB_TERM_KEY_END
},
138 {"KP_2", GRUB_TERM_KEY_DOWN
},
139 {"KP_3", GRUB_TERM_KEY_NPAGE
},
140 {"KP_4", GRUB_TERM_KEY_LEFT
},
142 {"KP_6", GRUB_TERM_KEY_RIGHT
},
143 {"KP_7", GRUB_TERM_KEY_HOME
},
144 {"KP_8", GRUB_TERM_KEY_UP
},
145 {"KP_9", GRUB_TERM_KEY_PPAGE
},
146 {"KP_Period", GRUB_TERM_KEY_DC
},
148 /* Unused in GRUB. */
153 {"Scroll_Forward", 0},
154 {"Scroll_Backward", 0},
173 {"Show_Registers", 0},
174 {"Control_backslash", 0},
177 /* Keys currently not remappable. */
194 fprintf (stderr
, "Try `%s --help' for more information.\n", program_name
);
197 Usage: %s [OPTIONS] LAYOUT\n\
198 -o, --output set output base name file. Default is LAYOUT.gkb\n\
199 -h, --help display this message and exit.\n\
200 -V, --version print version information and exit.\n\
201 -v, --verbose print verbose messages.\n\
203 Report bugs to <%s>.\n", program_name
, PACKAGE_BUGREPORT
);
209 add_special_keys (struct grub_keyboard_layout
*layout
)
212 layout
->keyboard_map
[101] = GRUB_TERM_KEY_UP
;
213 layout
->keyboard_map
[102] = GRUB_TERM_KEY_DOWN
;
214 layout
->keyboard_map
[103] = GRUB_TERM_KEY_LEFT
;
215 layout
->keyboard_map
[104] = GRUB_TERM_KEY_RIGHT
;
223 for (i
= 0; console_grub_equivalences
[i
].layout
!= NULL
; i
++)
224 if (strcmp (code
, console_grub_equivalences
[i
].layout
) == 0)
225 return console_grub_equivalences
[i
].grub
;
227 fprintf (stderr
, "Unknown key %s\n", code
);
233 get_grub_code (char *layout_code
)
237 if (strncmp (layout_code
, "U+", sizeof ("U+") - 1) == 0)
238 sscanf (layout_code
, "U+%x", &code
);
239 else if (strncmp (layout_code
, "+U+", sizeof ("+U+") - 1) == 0)
240 sscanf (layout_code
, "+U+%x", &code
);
242 code
= lookup (layout_code
);
247 write_file (FILE *out
, struct grub_keyboard_layout
*layout
)
249 grub_uint32_t version
;
252 version
= grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION
);
254 for (i
= 0; i
< ARRAY_SIZE (layout
->keyboard_map
); i
++)
255 layout
->keyboard_map
[i
] = grub_cpu_to_le32(layout
->keyboard_map
[i
]);
257 for (i
= 0; i
< ARRAY_SIZE (layout
->keyboard_map_shift
); i
++)
258 layout
->keyboard_map_shift
[i
]
259 = grub_cpu_to_le32(layout
->keyboard_map_shift
[i
]);
261 for (i
= 0; i
< ARRAY_SIZE (layout
->keyboard_map_l3
); i
++)
262 layout
->keyboard_map_l3
[i
]
263 = grub_cpu_to_le32(layout
->keyboard_map_l3
[i
]);
265 for (i
= 0; i
< ARRAY_SIZE (layout
->keyboard_map_shift_l3
); i
++)
266 layout
->keyboard_map_shift_l3
[i
]
267 = grub_cpu_to_le32(layout
->keyboard_map_shift_l3
[i
]);
269 fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC
, 1,
270 GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE
, out
);
271 fwrite (&version
, sizeof (version
), 1, out
);
272 fwrite (layout
, 1, sizeof (*layout
), out
);
276 write_keymaps (FILE *in
, FILE *out
)
278 struct grub_keyboard_layout layout
;
282 memset (&layout
, 0, sizeof (layout
));
284 /* Process the ckbcomp output and prepare the layouts. */
286 while (fgets (line
, sizeof (line
), in
))
288 if (strncmp (line
, "keycode", sizeof ("keycode") - 1) == 0)
296 sscanf (line
, "keycode %u = %60s %60s %60s %60s", &keycode
,
297 normal
, shift
, normalalt
, shiftalt
);
298 if (keycode
< GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE
)
300 layout
.keyboard_map
[keycode
] = get_grub_code (normal
);
301 layout
.keyboard_map_shift
[keycode
] = get_grub_code (shift
);
302 layout
.keyboard_map_l3
[keycode
] = get_grub_code (normalalt
);
303 layout
.keyboard_map_shift_l3
[keycode
]
304 = get_grub_code (shiftalt
);
312 fprintf (stderr
, "ERROR: no keycodes found. Check output of %s.\n",
317 add_special_keys (&layout
);
319 write_file (out
, &layout
);
323 main (int argc
, char *argv
[])
326 char *infile_name
= NULL
;
327 char *outfile_name
= NULL
;
330 set_program_name (argv
[0]);
334 /* Check for options. */
337 int c
= getopt_long (argc
, argv
, "o:i:hVv", options
, 0);
349 infile_name
= optarg
;
353 outfile_name
= optarg
;
357 printf ("%s (%s) %s\n", program_name
, PACKAGE_NAME
,
372 in
= fopen (infile_name
, "r");
377 grub_util_error ("Couldn't open input file: %s\n", strerror (errno
));
380 out
= fopen (outfile_name
, "wb");
388 grub_util_error ("Couldn't open output file: %s\n", strerror (errno
));
391 write_keymaps (in
, out
);