commit-grub
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[2539] 2009-08-28 Colin Watson <address@hidden>


From: Colin Watson
Subject: [2539] 2009-08-28 Colin Watson <address@hidden>
Date: Fri, 28 Aug 2009 13:20:34 +0000

Revision: 2539
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2539
Author:   cjwatson
Date:     2009-08-28 13:20:34 +0000 (Fri, 28 Aug 2009)
Log Message:
-----------
2009-08-28  Colin Watson  <address@hidden>
2009-08-28  Robert Millan  <address@hidden>

        Add `getkeystatus' terminal method.  Add a new `keystatus' command
        to query it.

        * include/grub/term.h (GRUB_TERM_STATUS_SHIFT,
        GRUB_TERM_STATUS_CTRL, GRUB_TERM_STATUS_ALT): Definitions for
        modifier key bitmasks.
        (struct grub_term_input): Add `getkeystatus' member.
        (grub_getkeystatus): Add prototype.
        * kern/term.c (grub_getkeystatus): New function.

        * include/grub/i386/pc/memory.h
        (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR): New macro.
        (struct grub_machine_bios_data_area): Define necessary parts of BIOS
        Data Area layout.
        * term/i386/pc/console.c (grub_console_getkeystatus): New function.
        (grub_console_term_input): Set `getkeystatus' member.
        * term/usb_keyboard.c (grub_usb_hid): Macroify HID protocol
        constants.
        (grub_usb_keyboard_getreport): Likewise.
        (grub_usb_keyboard_checkkey): Likewise.
        (grub_usb_keyboard_getkeystatus): New function.
        (grub_usb_keyboard_term): Set `getkeystatus' member.

        * commands/keystatus.c: New file.
        * conf/common.rmk (pkglib_MODULES): Add keystatus.mod.
        (keystatus_mod_SOURCES): New variable.
        (keystatus_mod_CFLAGS): Likewise.
        (keystatus_mod_LDFLAGS): Likewise.
        * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add
        commands/keystatus.c.
        * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
        * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
        * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
        * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
        * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
        * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
        * DISTLIST: Add commands/keystatus.c.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/conf/common.rmk
    trunk/grub2/conf/i386-coreboot.rmk
    trunk/grub2/conf/i386-efi.rmk
    trunk/grub2/conf/i386-ieee1275.rmk
    trunk/grub2/conf/i386-pc.rmk
    trunk/grub2/conf/powerpc-ieee1275.rmk
    trunk/grub2/conf/sparc64-ieee1275.rmk
    trunk/grub2/conf/x86_64-efi.rmk
    trunk/grub2/include/grub/i386/pc/memory.h
    trunk/grub2/include/grub/term.h
    trunk/grub2/kern/term.c
    trunk/grub2/term/i386/pc/console.c
    trunk/grub2/term/usb_keyboard.c

Added Paths:
-----------
    trunk/grub2/commands/keystatus.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog       2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/ChangeLog       2009-08-28 13:20:34 UTC (rev 2539)
@@ -1,3 +1,44 @@
+2009-08-28  Colin Watson  <address@hidden>
+2009-08-28  Robert Millan  <address@hidden>
+
+       Add `getkeystatus' terminal method.  Add a new `keystatus' command
+       to query it.
+
+       * include/grub/term.h (GRUB_TERM_STATUS_SHIFT,
+       GRUB_TERM_STATUS_CTRL, GRUB_TERM_STATUS_ALT): Definitions for
+       modifier key bitmasks.
+       (struct grub_term_input): Add `getkeystatus' member.
+       (grub_getkeystatus): Add prototype.
+       * kern/term.c (grub_getkeystatus): New function.
+
+       * include/grub/i386/pc/memory.h
+       (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR): New macro.
+       (struct grub_machine_bios_data_area): Define necessary parts of BIOS
+       Data Area layout.
+       * term/i386/pc/console.c (grub_console_getkeystatus): New function.
+       (grub_console_term_input): Set `getkeystatus' member.
+       * term/usb_keyboard.c (grub_usb_hid): Macroify HID protocol
+       constants.
+       (grub_usb_keyboard_getreport): Likewise.
+       (grub_usb_keyboard_checkkey): Likewise.
+       (grub_usb_keyboard_getkeystatus): New function.
+       (grub_usb_keyboard_term): Set `getkeystatus' member.
+
+       * commands/keystatus.c: New file.
+       * conf/common.rmk (pkglib_MODULES): Add keystatus.mod.
+       (keystatus_mod_SOURCES): New variable.
+       (keystatus_mod_CFLAGS): Likewise.
+       (keystatus_mod_LDFLAGS): Likewise.
+       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add
+       commands/keystatus.c.
+       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise.
+       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
+       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
+       * DISTLIST: Add commands/keystatus.c.
+
 2009-08-28  Vladimir Serbinenko  <address@hidden>
 
        Split befs.mod and afs.mod into *_be.mod and *.mod

Added: trunk/grub2/commands/keystatus.c
===================================================================
--- trunk/grub2/commands/keystatus.c                            (rev 0)
+++ trunk/grub2/commands/keystatus.c    2009-08-28 13:20:34 UTC (rev 2539)
@@ -0,0 +1,81 @@
+/* keystatus.c - Command to check key modifier status.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/extcmd.h>
+#include <grub/term.h>
+
+static const struct grub_arg_option options[] =
+  {
+    {"shift", 's', 0, "check Shift key", 0, 0},
+    {"ctrl", 'c', 0, "check Control key", 0, 0},
+    {"alt", 'a', 0, "check Alt key", 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+#define grub_cur_term_input    grub_term_get_current_input ()
+
+static grub_err_t
+grub_cmd_keystatus (grub_extcmd_t cmd,
+                   int argc __attribute__ ((unused)),
+                   char **args __attribute__ ((unused)))
+{
+  struct grub_arg_list *state = cmd->state;
+  int expect_mods = 0;
+  int mods;
+
+  if (state[0].set)
+    expect_mods |= GRUB_TERM_STATUS_SHIFT;
+  if (state[1].set)
+    expect_mods |= GRUB_TERM_STATUS_CTRL;
+  if (state[2].set)
+    expect_mods |= GRUB_TERM_STATUS_ALT;
+
+  /* Without arguments, just check whether getkeystatus is supported at
+     all.  */
+  if (!grub_cur_term_input->getkeystatus)
+    return grub_error (GRUB_ERR_TEST_FAILURE, "false");
+  grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods);
+  if (!expect_mods)
+    return 0;
+
+  mods = grub_getkeystatus ();
+  grub_dprintf ("keystatus", "mods: %d\n", mods);
+  if (mods >= 0 && (mods & expect_mods) != 0)
+    return 0;
+  else
+    return grub_error (GRUB_ERR_TEST_FAILURE, "false");
+}
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT(keystatus)
+{
+  cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus,
+                             GRUB_COMMAND_FLAG_BOTH,
+                             "keystatus [--shift|--ctrl|--alt]",
+                             "Check key modifier status",
+                             options);
+}
+
+GRUB_MOD_FINI(keystatus)
+{
+  grub_unregister_extcmd (cmd);
+}

Modified: trunk/grub2/conf/common.rmk
===================================================================
--- trunk/grub2/conf/common.rmk 2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/conf/common.rmk 2009-08-28 13:20:34 UTC (rev 2539)
@@ -375,7 +375,8 @@
        terminfo.mod test.mod blocklist.mod hexdump.mod         \
        read.mod sleep.mod loadenv.mod crc.mod parttool.mod     \
        msdospart.mod memrw.mod normal.mod sh.mod lua.mod       \
-       gptsync.mod true.mod probe.mod password.mod
+       gptsync.mod true.mod probe.mod password.mod             \
+       keystatus.mod
 
 # For password.mod.
 password_mod_SOURCES = commands/password.c
@@ -522,6 +523,11 @@
 probe_mod_CFLAGS = $(COMMON_CFLAGS)
 probe_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For keystatus.mod.
+keystatus_mod_SOURCES = commands/keystatus.c
+keystatus_mod_CFLAGS = $(COMMON_CFLAGS)
+keystatus_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For normal.mod.
 normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
        normal/auth.c normal/autofs.c normal/handler.c \

Modified: trunk/grub2/conf/i386-coreboot.rmk
===================================================================
--- trunk/grub2/conf/i386-coreboot.rmk  2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/conf/i386-coreboot.rmk  2009-08-28 13:20:34 UTC (rev 2539)
@@ -110,7 +110,7 @@
        commands/handler.c commands/ls.c commands/test.c                \
        commands/search.c commands/blocklist.c commands/hexdump.c       \
        commands/gptsync.c commands/probe.c commands/xnu_uuid.c         \
-       commands/password.c                                             \
+       commands/password.c commands/keystatus.c                        \
        lib/hexdump.c commands/i386/cpuid.c                             \
        disk/host.c disk/loopback.c                                     \
        \

Modified: trunk/grub2/conf/i386-efi.rmk
===================================================================
--- trunk/grub2/conf/i386-efi.rmk       2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/conf/i386-efi.rmk       2009-08-28 13:20:34 UTC (rev 2539)
@@ -37,7 +37,7 @@
        commands/configfile.c commands/help.c                           \
        commands/handler.c commands/ls.c commands/test.c                \
        commands/search.c commands/hexdump.c lib/hexdump.c              \
-       commands/halt.c commands/reboot.c                               \
+       commands/halt.c commands/reboot.c commands/keystatus.c          \
        commands/i386/cpuid.c                                           \
        commands/password.c                                             \
        disk/loopback.c                                                 \

Modified: trunk/grub2/conf/i386-ieee1275.rmk
===================================================================
--- trunk/grub2/conf/i386-ieee1275.rmk  2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/conf/i386-ieee1275.rmk  2009-08-28 13:20:34 UTC (rev 2539)
@@ -66,7 +66,7 @@
        lib/hexdump.c commands/halt.c commands/reboot.c                 \
        commands/gptsync.c commands/probe.c  commands/xnu_uuid.c        \
        commands/i386/cpuid.c   \
-       commands/password.c                                             \
+       commands/password.c commands/keystatus.c                        \
        disk/host.c disk/loopback.c                                     \
        \
        fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \

Modified: trunk/grub2/conf/i386-pc.rmk
===================================================================
--- trunk/grub2/conf/i386-pc.rmk        2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/conf/i386-pc.rmk        2009-08-28 13:20:34 UTC (rev 2539)
@@ -124,7 +124,7 @@
        lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c         \
        commands/gptsync.c commands/probe.c commands/xnu_uuid.c         \
        commands/i386/cpuid.c   \
-       commands/password.c                                             \
+       commands/password.c commands/keystatus.c                        \
        disk/host.c disk/loopback.c disk/scsi.c                         \
        fs/fshelp.c     \
        \

Modified: trunk/grub2/conf/powerpc-ieee1275.rmk
===================================================================
--- trunk/grub2/conf/powerpc-ieee1275.rmk       2009-08-28 13:01:26 UTC (rev 
2538)
+++ trunk/grub2/conf/powerpc-ieee1275.rmk       2009-08-28 13:20:34 UTC (rev 
2539)
@@ -46,7 +46,7 @@
        commands/ls.c commands/blocklist.c commands/hexdump.c           \
        lib/hexdump.c commands/halt.c commands/reboot.c                 \
        commands/gptsync.c commands/probe.c commands/xnu_uuid.c         \
-       commands/password.c                                             \
+       commands/password.c commands/keystatus.c                        \
        disk/loopback.c                                                 \
        \
        fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \

Modified: trunk/grub2/conf/sparc64-ieee1275.rmk
===================================================================
--- trunk/grub2/conf/sparc64-ieee1275.rmk       2009-08-28 13:01:26 UTC (rev 
2538)
+++ trunk/grub2/conf/sparc64-ieee1275.rmk       2009-08-28 13:20:34 UTC (rev 
2539)
@@ -104,7 +104,7 @@
        commands/ls.c commands/blocklist.c commands/hexdump.c           \
        lib/hexdump.c commands/halt.c commands/reboot.c                 \
        commands/gptsync.c commands/probe.c commands/xnu_uuid.c         \
-       commands/password.c                                             \
+       commands/password.c commands/keystatus.c                        \
        disk/loopback.c                                                 \
        \
        fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \

Modified: trunk/grub2/conf/x86_64-efi.rmk
===================================================================
--- trunk/grub2/conf/x86_64-efi.rmk     2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/conf/x86_64-efi.rmk     2009-08-28 13:20:34 UTC (rev 2539)
@@ -37,7 +37,7 @@
        commands/search.c commands/hexdump.c lib/hexdump.c              \
        commands/halt.c commands/reboot.c                               \
        commands/i386/cpuid.c                                           \
-       commands/password.c                                             \
+       commands/password.c commands/keystatus.c                        \
        disk/loopback.c                                                 \
        \
        fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c                 \

Modified: trunk/grub2/include/grub/i386/pc/memory.h
===================================================================
--- trunk/grub2/include/grub/i386/pc/memory.h   2009-08-28 13:01:26 UTC (rev 
2538)
+++ trunk/grub2/include/grub/i386/pc/memory.h   2009-08-28 13:20:34 UTC (rev 
2539)
@@ -78,8 +78,19 @@
 /* The data segment of the pseudo real mode.  */
 #define GRUB_MEMORY_MACHINE_PSEUDO_REAL_DSEG   0x20
 
+#define GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR        0x400
+
 #ifndef ASM_FILE
 
+/* See http://heim.ifi.uio.no/~stanisls/helppc/bios_data_area.html for a
+   description of the BIOS Data Area layout.  */
+struct grub_machine_bios_data_area
+{
+  grub_uint8_t unused1[0x17];
+  grub_uint8_t keyboard_flag_lower; /* 0x17 */ 
+  grub_uint8_t unused2[0xf0 - 0x18];
+};
+
 struct grub_machine_mmap_entry
 {
   grub_uint32_t size;

Modified: trunk/grub2/include/grub/term.h
===================================================================
--- trunk/grub2/include/grub/term.h     2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/include/grub/term.h     2009-08-28 13:20:34 UTC (rev 2539)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2003,2005,2007,2008  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2003,2005,2007,2008,2009  Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -72,6 +72,12 @@
 #define GRUB_TERM_NEED_INIT    (1 << 16)
 
 
+/* 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)
+
+
 /* Unicode characters for fancy graphics.  */
 #define GRUB_TERM_DISP_LEFT    0x2190
 #define GRUB_TERM_DISP_UP      0x2191
@@ -157,6 +163,9 @@
 
   /* Get a character.  */
   int (*getkey) (void);
+
+  /* Get keyboard modifier status.  */
+  int (*getkeystatus) (void);
 };
 typedef struct grub_term_input *grub_term_input_t;
 
@@ -275,6 +284,7 @@
 grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code);
 int EXPORT_FUNC(grub_getkey) (void);
 int EXPORT_FUNC(grub_checkkey) (void);
+int EXPORT_FUNC(grub_getkeystatus) (void);
 grub_uint16_t EXPORT_FUNC(grub_getwh) (void);
 grub_uint16_t EXPORT_FUNC(grub_getxy) (void);
 void EXPORT_FUNC(grub_gotoxy) (grub_uint8_t x, grub_uint8_t y);

Modified: trunk/grub2/kern/term.c
===================================================================
--- trunk/grub2/kern/term.c     2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/kern/term.c     2009-08-28 13:20:34 UTC (rev 2539)
@@ -140,6 +140,15 @@
   return (grub_cur_term_input->checkkey) ();
 }
 
+int
+grub_getkeystatus (void)
+{
+  if (grub_cur_term_input->getkeystatus)
+    return (grub_cur_term_input->getkeystatus) ();
+  else
+    return 0;
+}
+
 grub_uint16_t
 grub_getxy (void)
 {

Modified: trunk/grub2/term/i386/pc/console.c
===================================================================
--- trunk/grub2/term/i386/pc/console.c  2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/term/i386/pc/console.c  2009-08-28 13:20:34 UTC (rev 2539)
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2003,2005,2007,2008  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2003,2005,2007,2008,2009  Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -16,15 +16,40 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <grub/machine/memory.h>
 #include <grub/machine/console.h>
 #include <grub/term.h>
 #include <grub/types.h>
 
+static const struct grub_machine_bios_data_area *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 (void)
+{
+  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;
+}
+
 static struct grub_term_input grub_console_term_input =
   {
     .name = "console",
     .checkkey = grub_console_checkkey,
     .getkey = grub_console_getkey,
+    .getkeystatus = grub_console_getkeystatus,
   };
 
 static struct grub_term_output grub_console_term_output =

Modified: trunk/grub2/term/usb_keyboard.c
===================================================================
--- trunk/grub2/term/usb_keyboard.c     2009-08-28 13:01:26 UTC (rev 2538)
+++ trunk/grub2/term/usb_keyboard.c     2009-08-28 13:20:34 UTC (rev 2539)
@@ -58,6 +58,19 @@
 
 static grub_usb_device_t usbdev;
 
+/* Valid values for bmRequestType.  See HID definition version 1.11 section
+   7.2.  */
+#define USB_HID_HOST_TO_DEVICE 0x21
+#define USB_HID_DEVICE_TO_HOST 0x61
+
+/* Valid values for bRequest.  See HID definition version 1.11 section 7.2. */
+#define USB_HID_GET_REPORT     0x01
+#define USB_HID_GET_IDLE       0x02
+#define USB_HID_GET_PROTOCOL   0x03
+#define USB_HID_SET_REPORT     0x09
+#define USB_HID_SET_IDLE       0x0A
+#define USB_HID_SET_PROTOCOL   0x0B
+
 static void
 grub_usb_hid (void)
 {
@@ -90,17 +103,19 @@
   grub_usb_iterate (usb_iterate);
 
   /* Place the device in boot mode.  */
-  grub_usb_control_msg (usbdev, 0x21, 0x0B, 0, 0, 0, 0);
+  grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_PROTOCOL,
+                       0, 0, 0, 0);
 
   /* Reports every time an event occurs and not more often than that.  */
-  grub_usb_control_msg (usbdev, 0x21, 0x0A, 0<<8, 0, 0, 0);
+  grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE,
+                       0<<8, 0, 0, 0);
 }
 
 static grub_err_t
 grub_usb_keyboard_getreport (grub_usb_device_t dev, grub_uint8_t *report)
 {
-  return grub_usb_control_msg (dev, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
-                              8, (char *) report);
+  return grub_usb_control_msg (dev, USB_HID_DEVICE_TO_HOST, USB_HID_GET_REPORT,
+                              0, 0, 8, (char *) report);
 }
 
 
@@ -151,7 +166,8 @@
   /* Wait until the key is released.  */
   while (!err && data[2])
     {
-      err = grub_usb_control_msg (usbdev, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
+      err = grub_usb_control_msg (usbdev, USB_HID_DEVICE_TO_HOST,
+                                 USB_HID_GET_REPORT, 0, 0,
                                  sizeof (data), (char *) data);
       grub_dprintf ("usb_keyboard",
                    "report2: 0x%02x 0x%02x 0x%02x 0x%02x"
@@ -238,11 +254,67 @@
   return key;
 }
 
+static int
+grub_usb_keyboard_getkeystatus (void)
+{
+  grub_uint8_t data[8];
+  int mods = 0;
+  grub_err_t err;
+  grub_uint64_t currtime;
+  int timeout = 50;
+
+  /* Set idle time to the minimum offered by the spec (4 milliseconds) so
+     that we can find out the current state.  */
+  grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE,
+                       0<<8, 0, 0, 0);
+
+  currtime = grub_get_time_ms ();
+  do
+    {
+      /* Get_Report.  */
+      err = grub_usb_keyboard_getreport (usbdev, data);
+
+      /* Implement a timeout.  */
+      if (grub_get_time_ms () > currtime + timeout)
+       break;
+    }
+  while (err || !data[0]);
+
+  /* Go back to reporting every time an event occurs and not more often than
+     that.  */
+  grub_usb_control_msg (usbdev, USB_HID_HOST_TO_DEVICE, USB_HID_SET_IDLE,
+                       0<<8, 0, 0, 0);
+
+  /* We allowed a while for modifiers to show up in the report, but it is
+     not an error if they never did.  */
+  if (err)
+    return -1;
+
+  grub_dprintf ("usb_keyboard",
+               "report: 0x%02x 0x%02x 0x%02x 0x%02x"
+               " 0x%02x 0x%02x 0x%02x 0x%02x\n",
+               data[0], data[1], data[2], data[3],
+               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;
+
+  grub_errno = GRUB_ERR_NONE;
+
+  return mods;
+}
+
 static struct grub_term_input grub_usb_keyboard_term =
   {
     .name = "usb_keyboard",
     .checkkey = grub_usb_keyboard_checkkey,
     .getkey = grub_usb_keyboard_getkey,
+    .getkeystatus = grub_usb_keyboard_getkeystatus,
     .next = 0
   };
 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]