diff --git a/commands/keylayouts.c b/commands/keylayouts.c index bfe30d2ab..b7aee7fab 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -28,6 +28,115 @@ #include #include +static struct grub_keyboard_layout layout_us = { + .at = { + .keyboard_map = { + /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', + /* 0x08 */ '7', '8', '9', '0', + /* 0x0c */ '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, + /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', + /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', + /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', + /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, + /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, + /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, + /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, + /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, + /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, + /* 0x4e */ '+', GRUB_TERM_KEY_END, + /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, + /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, + /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', + /* 0x60 */ '\0', '\0', '\0', '\0', + /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, + /* 0x68 */ GRUB_TERM_KEY_RIGHT + }, + .keyboard_map_shift = { + '\0', '\0', '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '\0', '\0', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', + [0x56] = '|' + } + } +}; + +static struct grub_keyboard_layout *grub_current_layout = &layout_us; + +static int +map_key_core (int code, int status, int *alt_gr_consumed) +{ + *alt_gr_consumed = 0; + + if (status & GRUB_TERM_STATUS_RALT) + { + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + { + if (grub_current_layout->at.keyboard_map_shift_l3[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->at.keyboard_map_shift_l3[code]; + } + else if (grub_current_layout->at.keyboard_map_shift[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->at.keyboard_map_l3[code] + | GRUB_TERM_SHIFT; + } + } + else if (grub_current_layout->at.keyboard_map_shift[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->at.keyboard_map_l3[code]; + } + } + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + { + if (grub_current_layout->at.keyboard_map_shift[code]) + return grub_current_layout->at.keyboard_map_shift[code]; + else + return grub_current_layout->at.keyboard_map[code] | GRUB_TERM_SHIFT; + } + else + return grub_current_layout->at.keyboard_map[code]; +} + +unsigned +grub_term_map_key (int code, int status) +{ + int alt_gr_consumed; + int key; + + key = map_key_core (code, status, &alt_gr_consumed); + + if (key == 0 || key == GRUB_TERM_SHIFT) + grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); + + if (status & GRUB_TERM_STATUS_CAPS) + { + if ((key >= 'a') && (key <= 'z')) + key += 'A' - 'a'; + else if ((key >= 'A') && (key <= 'Z')) + key += 'a' - 'A'; + } + + if ((status & GRUB_TERM_STATUS_LALT) || + ((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed)) + key |= GRUB_TERM_ALT; + if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL)) + key |= GRUB_TERM_CTRL; + + return key; +} + static grub_err_t grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -110,6 +219,23 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), newmap->at.keyboard_map_shift_l3[i] = grub_le_to_cpu32(newmap->at.keyboard_map_shift_l3[i]); + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map); i++) + newmap->usb.keyboard_map[i] = grub_le_to_cpu32(newmap->usb.keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_shift); i++) + newmap->usb.keyboard_map_shift[i] + = grub_le_to_cpu32(newmap->usb.keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_l3); i++) + newmap->usb.keyboard_map_l3[i] + = grub_le_to_cpu32(newmap->usb.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_shift_l3); i++) + newmap->usb.keyboard_map_shift_l3[i] + = grub_le_to_cpu32(newmap->usb.keyboard_map_shift_l3[i]); + + grub_current_layout = newmap; + return GRUB_ERR_NONE; fail: @@ -131,6 +257,5 @@ GRUB_MOD_INIT(keylayouts) GRUB_MOD_FINI(keylayouts) { - grub_current_layout = NULL; grub_unregister_command (cmd); } diff --git a/commands/keystatus.c b/commands/keystatus.c index 9db92b942..9c7ab84b0 100644 --- a/commands/keystatus.c +++ b/commands/keystatus.c @@ -56,11 +56,11 @@ grub_cmd_keystatus (grub_extcmd_t cmd, int mods; if (state[0].set) - expect_mods |= GRUB_TERM_STATUS_SHIFT; + expect_mods |= (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT); if (state[1].set) - expect_mods |= GRUB_TERM_STATUS_CTRL; + expect_mods |= (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL); if (state[2].set) - expect_mods |= GRUB_TERM_STATUS_ALT; + expect_mods |= (GRUB_TERM_STATUS_LALT | GRUB_TERM_STATUS_RALT); grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index 2d6e3d54c..6d4b620c2 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,28 +21,24 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 4 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 5 #define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 -struct grub_keyboard_layout +struct grub_keyboard_layout_kbd { - struct - { - grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - } at; - struct - { - grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - } usb; + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; }; -struct grub_keyboard_layout *EXPORT_VAR (grub_current_layout); +struct grub_keyboard_layout +{ + struct grub_keyboard_layout_kbd at; + struct grub_keyboard_layout_kbd usb; +}; + +unsigned grub_term_map_key (int code, int status); #endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/include/grub/term.h b/include/grub/term.h index 036e8caaa..de430d66f 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -110,9 +110,15 @@ grub_term_color_state; /* Bitmasks for modifier keys returned by grub_getkeystatus. */ -#define GRUB_TERM_STATUS_SHIFT (1 << 0) -#define GRUB_TERM_STATUS_CTRL (1 << 1) -#define GRUB_TERM_STATUS_ALT (1 << 2) +#define GRUB_TERM_STATUS_RSHIFT (1 << 0) +#define GRUB_TERM_STATUS_LSHIFT (1 << 1) +#define GRUB_TERM_STATUS_RCTRL (1 << 2) +#define GRUB_TERM_STATUS_RALT (1 << 3) +#define GRUB_TERM_STATUS_SCROLL (1 << 4) +#define GRUB_TERM_STATUS_NUM (1 << 5) +#define GRUB_TERM_STATUS_CAPS (1 << 6) +#define GRUB_TERM_STATUS_LCTRL (1 << 8) +#define GRUB_TERM_STATUS_LALT (1 << 9) /* Menu-related geometrical constants. */ diff --git a/kern/term.c b/kern/term.c index 04d20364a..6ddf63208 100644 --- a/kern/term.c +++ b/kern/term.c @@ -22,13 +22,11 @@ #include #include #include -#include struct grub_term_output *grub_term_outputs_disabled; struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; -struct grub_keyboard_layout *grub_current_layout; /* Put a Unicode character. */ static void diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 492075115..054dc9805 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -22,64 +22,18 @@ #include #include #include +#include static short at_keyboard_status = 0; +static int extended_pending = 0; static int pending_key = -1; -#define KEYBOARD_STATUS_SHIFT_L (1 << 0) -#define KEYBOARD_STATUS_SHIFT_R (1 << 1) -#define KEYBOARD_STATUS_ALT_L (1 << 2) -#define KEYBOARD_STATUS_ALT_R (1 << 3) -#define KEYBOARD_STATUS_CTRL_L (1 << 4) -#define KEYBOARD_STATUS_CTRL_R (1 << 5) -#define KEYBOARD_STATUS_CAPS_LOCK (1 << 6) -#define KEYBOARD_STATUS_NUM_LOCK (1 << 7) -#define KEYBOARD_STATUS_EXTENDED (1 << 8) - static grub_uint8_t led_status; #define KEYBOARD_LED_SCROLL (1 << 0) #define KEYBOARD_LED_NUM (1 << 1) #define KEYBOARD_LED_CAPS (1 << 2) -static const unsigned keyboard_map[128] = -{ - /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - /* 0x08 */ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', - /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, - /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, - /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, - /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, - /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, - /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, - /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, - /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, - /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, - /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, - /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, - /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', - /* 0x60 */ '\0', '\0', '\0', '\0', - /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, - /* 0x68 */ GRUB_TERM_KEY_RIGHT -}; - -static unsigned keyboard_map_shift[128] = -{ - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', - [0x56] = '|' -}; - static grub_uint8_t grub_keyboard_controller_orig; static void @@ -122,45 +76,41 @@ grub_keyboard_isr (grub_uint8_t key) switch (KEYBOARD_SCANCODE (key)) { case SHIFT_L: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L; + at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT; break; case SHIFT_R: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R; + at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT; break; case CTRL: - at_keyboard_status |= KEYBOARD_STATUS_CTRL_L; + at_keyboard_status |= GRUB_TERM_STATUS_LCTRL; break; case ALT: - if (at_keyboard_status & KEYBOARD_STATUS_EXTENDED) - at_keyboard_status |= KEYBOARD_STATUS_ALT_R; + if (extended_pending) + at_keyboard_status |= GRUB_TERM_STATUS_RALT; else - at_keyboard_status |= KEYBOARD_STATUS_ALT_L; + at_keyboard_status |= GRUB_TERM_STATUS_LALT; break; } else switch (KEYBOARD_SCANCODE (key)) { case SHIFT_L: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L; + at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; break; case SHIFT_R: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R; + at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT; break; case CTRL: - at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L; + at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL; break; case ALT: - if (at_keyboard_status & KEYBOARD_STATUS_EXTENDED) - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_R; + if (extended_pending) + at_keyboard_status &= ~GRUB_TERM_STATUS_RALT; else - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L; + at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; break; } - if (key == 0xe0) - at_keyboard_status |= KEYBOARD_STATUS_EXTENDED; - else - at_keyboard_status &= ~KEYBOARD_STATUS_EXTENDED; - + extended_pending = (key == 0xe0); } /* If there is a raw key pending, return it; otherwise return -1. */ @@ -177,11 +127,12 @@ grub_keyboard_getkey (void) return (KEYBOARD_SCANCODE (key)); } + /* If there is a character pending, return it; otherwise return -1. */ static int grub_at_keyboard_getkey_noblock (void) { - int code, key; + int code; code = grub_keyboard_getkey (); if (code == -1) return -1; @@ -194,66 +145,34 @@ grub_at_keyboard_getkey_noblock (void) /* Caps lock sends scan code twice. Get the second one and discard it. */ while (grub_keyboard_getkey () == -1); - at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK; + at_keyboard_status ^= GRUB_TERM_STATUS_CAPS; led_status ^= KEYBOARD_LED_CAPS; keyboard_controller_led (led_status); #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); #endif - key = -1; - break; + return -1; case NUM_LOCK: /* Num lock sends scan code twice. Get the second one and discard it. */ while (grub_keyboard_getkey () == -1); - at_keyboard_status ^= KEYBOARD_STATUS_NUM_LOCK; + at_keyboard_status ^= GRUB_TERM_STATUS_NUM; led_status ^= KEYBOARD_LED_NUM; keyboard_controller_led (led_status); #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); #endif - key = -1; - break; + return -1; case SCROLL_LOCK: - /* For scroll lock we don't keep track of status. Only update its led. */ + at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL; led_status ^= KEYBOARD_LED_SCROLL; keyboard_controller_led (led_status); - key = -1; - break; + return -1; default: - if (at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L - | KEYBOARD_STATUS_SHIFT_R)) - { - if (keyboard_map_shift[code]) - key = keyboard_map_shift[code]; - else - key = keyboard_map[code] | GRUB_TERM_SHIFT; - } - else - key = keyboard_map[code]; - - if (key == 0) - grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); - - if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK) - { - if ((key >= 'a') && (key <= 'z')) - key += 'A' - 'a'; - else if ((key >= 'A') && (key <= 'Z')) - key += 'a' - 'A'; - } - - if (at_keyboard_status & KEYBOARD_STATUS_ALT_L) - key |= GRUB_TERM_ALT; - if (at_keyboard_status & KEYBOARD_STATUS_ALT_R) - key |= GRUB_TERM_ALT; - if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L - | KEYBOARD_STATUS_CTRL_R)) - key |= GRUB_TERM_CTRL; + return grub_term_map_key (code, at_keyboard_status); } - return key; } static int diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 74df4c27f..009647c4c 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -24,25 +24,11 @@ static const struct grub_machine_bios_data_area *bios_data_area = (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; -#define KEYBOARD_LEFT_SHIFT (1 << 0) -#define KEYBOARD_RIGHT_SHIFT (1 << 1) -#define KEYBOARD_CTRL (1 << 2) -#define KEYBOARD_ALT (1 << 3) - static int grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) { - grub_uint8_t status = bios_data_area->keyboard_flag_lower; - int mods = 0; - - if (status & (KEYBOARD_LEFT_SHIFT | KEYBOARD_RIGHT_SHIFT)) - mods |= GRUB_TERM_STATUS_SHIFT; - if (status & KEYBOARD_CTRL) - mods |= GRUB_TERM_STATUS_CTRL; - if (status & KEYBOARD_ALT) - mods |= GRUB_TERM_STATUS_ALT; - - return mods; + /* conveniently GRUB keystatus is modelled after BIOS one. */ + return bios_data_area->keyboard_flag_lower & ~0x80; } static struct grub_term_input grub_console_term_input = diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 3432f700c..f35cc4b65 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -163,7 +163,7 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) /* Check if the Shift key was pressed. */ if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT - || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) { if (keyboard_map_shift[data[2]]) key = keyboard_map_shift[data[2]]; @@ -323,12 +323,18 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unu data[4], data[5], data[6], data[7]); /* Check Shift, Control, and Alt status. */ - if (data[0] & 0x02 || data[0] & 0x20) - mods |= GRUB_TERM_STATUS_SHIFT; - if (data[0] & 0x01 || data[0] & 0x10) - mods |= GRUB_TERM_STATUS_CTRL; - if (data[0] & 0x04 || data[0] & 0x40) - mods |= GRUB_TERM_STATUS_ALT; + if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT) + mods |= GRUB_TERM_STATUS_LSHIFT; + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + mods |= GRUB_TERM_STATUS_RSHIFT; + if (data[0] & GRUB_USB_KEYBOARD_LEFT_CTRL) + mods |= GRUB_TERM_STATUS_LCTRL; + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_CTRL) + mods |= GRUB_TERM_STATUS_RCTRL; + if (data[0] & GRUB_USB_KEYBOARD_LEFT_ALT) + mods |= GRUB_TERM_STATUS_LALT; + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_ALT) + mods |= GRUB_TERM_STATUS_RALT; grub_errno = GRUB_ERR_NONE; diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 9aca88cb1..43aa745a5 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -46,6 +46,26 @@ struct console_grub_equivalence grub_uint32_t grub; }; +static int at_to_usb_map[128] = +{ + 0, 41, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 45, 46, 42, 43, + 20, 26, 8, 21, 23, 28, 24, 12, + 18, 19, 47, 48, 40, 0, 4, 22, + 7, 9, 10, 11, 13, 14, 15, 51, + 52, 53, 0, 49, 29, 27, 6, 25, + 5, 17, 16, 54, 55, 56, 0, 0, + 0, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 74, + 82, 78, 45, 80, 0, 79, 0, 77, + 81, 75, 0, 76, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + static struct console_grub_equivalence console_grub_equivalences[] = { {"KP_1", '1'}, {"KP_2", '2'}, @@ -85,7 +105,26 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); exit (status); } -char +void +add_special_keys (struct grub_keyboard_layout *layout) +{ + layout->at.keyboard_map[71] = GRUB_TERM_KEY_HOME; + layout->at.keyboard_map[72] = GRUB_TERM_KEY_UP; + layout->at.keyboard_map[73] = GRUB_TERM_KEY_NPAGE; + layout->at.keyboard_map[75] = GRUB_TERM_KEY_LEFT; + layout->at.keyboard_map[77] = GRUB_TERM_KEY_RIGHT; + layout->at.keyboard_map[79] = GRUB_TERM_KEY_END; + layout->at.keyboard_map[80] = GRUB_TERM_KEY_DOWN; + layout->at.keyboard_map[81] = GRUB_TERM_KEY_PPAGE; + layout->at.keyboard_map[83] = GRUB_TERM_KEY_DC; + + layout->at.keyboard_map[101] = GRUB_TERM_KEY_UP; + layout->at.keyboard_map[102] = GRUB_TERM_KEY_DOWN; + layout->at.keyboard_map[103] = GRUB_TERM_KEY_LEFT; + layout->at.keyboard_map[104] = GRUB_TERM_KEY_RIGHT; +} + +static char lookup (char *code) { int i; @@ -97,7 +136,7 @@ lookup (char *code) return '\0'; } -unsigned int +static unsigned int get_grub_code (char *layout_code) { unsigned int code; @@ -111,9 +150,8 @@ get_grub_code (char *layout_code) return code; } -void -write_file (char* filename, grub_uint32_t *keyboard_map, - grub_uint32_t *keyboard_map_alt) +static void +write_file (char* filename, struct grub_keyboard_layout *layout) { FILE *fp_output; grub_uint32_t version; @@ -121,11 +159,35 @@ write_file (char* filename, grub_uint32_t *keyboard_map, version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); - for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) - keyboard_map[i] = grub_cpu_to_le32 (keyboard_map[i]); + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map); i++) + layout->at.keyboard_map[i] = grub_cpu_to_le32(layout->at.keyboard_map[i]); - for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) - keyboard_map_alt[i] = grub_cpu_to_le32 (keyboard_map_alt[i]); + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_shift); i++) + layout->at.keyboard_map_shift[i] + = grub_cpu_to_le32(layout->at.keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_l3); i++) + layout->at.keyboard_map_l3[i] + = grub_cpu_to_le32(layout->at.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_shift_l3); i++) + layout->at.keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->at.keyboard_map_shift_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map); i++) + layout->usb.keyboard_map[i] = grub_cpu_to_le32(layout->usb.keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_shift); i++) + layout->usb.keyboard_map_shift[i] + = grub_cpu_to_le32(layout->usb.keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_l3); i++) + layout->usb.keyboard_map_l3[i] + = grub_cpu_to_le32(layout->usb.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_shift_l3); i++) + layout->usb.keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->usb.keyboard_map_shift_l3[i]); fp_output = fopen (filename, "w"); @@ -138,23 +200,19 @@ write_file (char* filename, grub_uint32_t *keyboard_map, fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, fp_output); fwrite (&version, sizeof (version), 1, fp_output); - fwrite (keyboard_map, sizeof (keyboard_map[0]), - GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); - fwrite (keyboard_map_alt, sizeof (keyboard_map_alt[0]), - GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); + fwrite (layout, 1, sizeof (*layout), fp_output); fclose (fp_output); } -void +static void write_keymaps (char *keymap, char *file_basename) { - grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - + struct grub_keyboard_layout layout; char line[2048]; pid_t pid; int pipe_communication[2]; int ok; + unsigned i; FILE *fp_pipe; @@ -182,7 +240,7 @@ write_keymaps (char *keymap, char *file_basename) close (pipe_communication[1]); fp_pipe = fdopen (pipe_communication[0], "r"); - memset (keyboard_map, 0, sizeof (keyboard_map)); + memset (&layout, 0, sizeof (layout)); /* Process the ckbcomp output and prepare the layouts. */ ok = 0; @@ -198,9 +256,30 @@ write_keymaps (char *keymap, char *file_basename) sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode, normal, shift, normalalt, shiftalt); + if (keycode < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + layout.at.keyboard_map[keycode] = get_grub_code (normal); + layout.at.keyboard_map_shift[keycode] = get_grub_code (shift); + layout.at.keyboard_map_l3[keycode] = get_grub_code (normalalt); + layout.at.keyboard_map_shift_l3[keycode] + = get_grub_code (shiftalt); + ok = 1; + } } } + for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) + { + layout.usb.keyboard_map[at_to_usb_map[i]] = layout.at.keyboard_map[i]; + layout.usb.keyboard_map_shift[at_to_usb_map[i]] + = layout.at.keyboard_map_shift[i]; + layout.usb.keyboard_map_l3[at_to_usb_map[i]] + = layout.at.keyboard_map_l3[i]; + layout.usb.keyboard_map_shift_l3[at_to_usb_map[i]] + = layout.at.keyboard_map_shift_l3[i]; + } + + if (ok == 0) { fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n", @@ -208,7 +287,9 @@ write_keymaps (char *keymap, char *file_basename) exit (1); } - write_file (file_basename, keyboard_map, keyboard_map_alt); + add_special_keys (&layout); + + write_file (file_basename, &layout); } int