]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Hook AT keyboard mapping
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 19 Aug 2010 13:00:31 +0000 (15:00 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 19 Aug 2010 13:00:31 +0000 (15:00 +0200)
commands/keylayouts.c
commands/keystatus.c
include/grub/keyboard_layouts.h
include/grub/term.h
kern/term.c
term/at_keyboard.c
term/i386/pc/console.c
term/usb_keyboard.c
util/grub-mklayouts.c

index bfe30d2abc314cd5e427b37a38ae07762e97c174..b7aee7fab849679cd79adfb0505c99eceac1db96 100644 (file)
 #include <grub/gzio.h>
 #include <grub/i18n.h>
 
+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);
 }
index 9db92b942fec82c8f264aef24b88373f845ac8ce..9c7ab84b05dbadad39d3427505431853827544a4 100644 (file)
@@ -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);
 
index 2d6e3d54ccabc88e5de42641e21ba7959d0cdeca..6d4b620c2a75c9b5dd834d6e3d5ec80783a083db 100644 (file)
 
 #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_kbd
+{
+  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
 {
-  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;
+  struct grub_keyboard_layout_kbd at;
+  struct grub_keyboard_layout_kbd usb;
 };
 
-struct grub_keyboard_layout *EXPORT_VAR (grub_current_layout);
+unsigned grub_term_map_key (int code, int status);
 
 #endif /* GRUB_KEYBOARD_LAYOUTS  */
index 036e8caaab8c41a64648478f0309041a28969161..de430d66f0b4ddc0b9c0289ea85d8fffdba7424e 100644 (file)
@@ -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.  */
 
index 04d20364a5172205715777797cc0f882d36e2a6b..6ddf632089b70f1a0ef3f96cd637457a631b697c 100644 (file)
 #include <grub/misc.h>
 #include <grub/env.h>
 #include <grub/time.h>
-#include <grub/keyboard_layouts.h>
 
 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
index 492075115445b4e324f7fc5e91491794f14cd499..054dc9805b70b517a86c0d6ed3f17bdb525d360a 100644 (file)
 #include <grub/cpu/io.h>
 #include <grub/misc.h>
 #include <grub/term.h>
+#include <grub/keyboard_layouts.h>
 
 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
index 74df4c27fe54c36db71fee250553c0aa7eda8cab..009647c4c6c0d8945c4c01c2886cd894adb27911 100644 (file)
 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 =
index 3432f700c4eb86ce6a732023c1bc02cf1dd10f79..f35cc4b65ea6fa5777b23bccc2bc019a32ee6d7f 100644 (file)
@@ -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;
 
index 9aca88cb13551d7ece350822233707c75613f554..43aa745a5b935d83ffd5050ed1b4df78bfc8dcf6 100644 (file)
@@ -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