From: Colin Watson <cjwatson@ubuntu.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [PATCH] Detect key modifier status in 'sleep --interruptible'
Date: Mon, 24 Aug 2009 23:04:19 +0100 [thread overview]
Message-ID: <20090824220419.GA31998@riva.ucam.org> (raw)
In-Reply-To: <20090824122352.GB18956@thorin>
On Mon, Aug 24, 2009 at 02:23:52PM +0200, Robert Millan wrote:
> I don't have time to test it, but what we want is roughly something like
> this. If you would please test and confirm it's working the way you expected,
> it can be committed.
OK, here's a cleanup that (a) fixes some compilation errors in your
patch and (b) adds USB keyboard support back in. How does this look?
2009-08-24 Colin Watson <cjwatson@ubuntu.com>
2009-08-24 Robert Millan <rmh.grub@aybabtu.com>
Add `getkeystatus' terminal method. Use it in `sleep' to detect
Shift being held down.
* 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_keyboard_getkeystatus): New
function.
(grub_usb_keyboard_term): Set `getkeystatus' member.
* commands/sleep.c (grub_check_keyboard): New function.
(grub_interruptible_millisleep, grub_cmd_sleep): Use
grub_check_keyboard, checking whether Shift is pressed in addition
to checking for Escape.
Index: kern/term.c
===================================================================
--- kern/term.c (revision 2525)
+++ kern/term.c (working copy)
@@ -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)
{
Index: include/grub/term.h
===================================================================
--- include/grub/term.h (revision 2525)
+++ include/grub/term.h (working copy)
@@ -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);
Index: include/grub/i386/pc/memory.h
===================================================================
--- include/grub/i386/pc/memory.h (revision 2525)
+++ include/grub/i386/pc/memory.h (working copy)
@@ -78,8 +78,20 @@
/* 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 keyboard_flag_upper; /* 0x17 */
+ grub_uint8_t unused2[0xf0 - 0x19];
+};
+
struct grub_machine_mmap_entry
{
grub_uint32_t size;
Index: commands/sleep.c
===================================================================
--- commands/sleep.c (revision 2525)
+++ commands/sleep.c (working copy)
@@ -1,7 +1,7 @@
/* sleep.c - Command to wait a specified number of seconds. */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc.
+ * Copyright (C) 2006,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
@@ -43,6 +43,20 @@
grub_printf ("%d ", n);
}
+static int
+grub_check_keyboard (void)
+{
+ int mods = grub_getkeystatus ();
+ if (mods >= 0 && (mods & GRUB_TERM_STATUS_SHIFT) != 0)
+ return 1;
+
+ if (grub_checkkey () >= 0 &&
+ GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC)
+ return 1;
+
+ return 0;
+}
+
/* Based on grub_millisleep() from kern/generic/millisleep.c. */
static int
grub_interruptible_millisleep (grub_uint32_t ms)
@@ -52,8 +66,7 @@
start = grub_get_time_ms ();
while (grub_get_time_ms () - start < ms)
- if (grub_checkkey () >= 0 &&
- GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC)
+ if (grub_check_keyboard ())
return 1;
return 0;
@@ -74,7 +87,7 @@
if (n == 0)
{
/* Either `0' or broken input. */
- return 0;
+ return grub_check_keyboard ();
}
xy = grub_getxy ();
Index: term/i386/pc/console.c
===================================================================
--- term/i386/pc/console.c (revision 2525)
+++ term/i386/pc/console.c (working copy)
@@ -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,35 @@
* 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;
+
+static int
+grub_console_getkeystatus (void)
+{
+ grub_uint8_t status = bios_data_area->keyboard_flag_lower;
+ int mods = 0;
+
+ if (status & 0x03)
+ mods |= GRUB_TERM_STATUS_SHIFT;
+ if (status & 0x04)
+ mods |= GRUB_TERM_STATUS_CTRL;
+ if (status & 0x08)
+ 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 =
Index: term/usb_keyboard.c
===================================================================
--- term/usb_keyboard.c (revision 2526)
+++ term/usb_keyboard.c (working copy)
@@ -238,11 +238,55 @@
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;
+
+ 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);
+
+ 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
};
--
Colin Watson [cjwatson@ubuntu.com]
next prev parent reply other threads:[~2009-08-24 22:04 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-12 15:35 [PATCH] Detect key modifier status in 'sleep --interruptible' Colin Watson
2009-08-12 16:10 ` Vladimir 'phcoder' Serbinenko
2009-08-12 16:15 ` Vladimir 'phcoder' Serbinenko
2009-08-12 22:14 ` Colin Watson
2009-08-13 20:52 ` Robert Millan
2009-08-13 21:15 ` Colin Watson
2009-08-23 22:46 ` Vladimir 'phcoder' Serbinenko
2009-08-23 22:56 ` Robert Millan
2009-08-23 23:00 ` Vladimir 'phcoder' Serbinenko
2009-08-23 23:03 ` Robert Millan
2009-08-23 23:05 ` Vladimir 'phcoder' Serbinenko
2009-08-25 19:26 ` Robert Millan
2009-08-24 9:24 ` Colin Watson
2009-08-24 12:23 ` Robert Millan
2009-08-24 12:44 ` Robert Millan
2009-08-24 13:27 ` Colin Watson
2009-08-24 14:28 ` Robert Millan
2009-08-24 16:23 ` Colin Watson
2009-08-24 16:56 ` Colin Watson
2009-08-24 17:03 ` Colin Watson
2009-08-24 22:04 ` Colin Watson [this message]
2009-08-24 22:41 ` Robert Millan
2009-08-24 23:02 ` Colin Watson
2009-08-26 15:33 ` Colin Watson
2009-08-26 18:39 ` Robert Millan
2009-08-26 20:26 ` Colin Watson
2009-08-28 12:44 ` Robert Millan
2009-08-28 13:20 ` Colin Watson
2009-08-24 12:56 ` Robert Millan
2009-08-13 20:46 ` Robert Millan
2009-08-23 22:27 ` Robert Millan
2009-08-23 22:41 ` Vladimir 'phcoder' Serbinenko
2009-08-23 22:57 ` Robert Millan
2009-08-24 9:11 ` Colin Watson
2009-08-24 11:57 ` Robert Millan
2009-08-24 12:50 ` Vladimir 'phcoder' Serbinenko
2009-08-24 12:58 ` Michal Suchanek
2009-08-24 14:29 ` Robert Millan
2009-08-24 12:59 ` Colin Watson
2009-08-24 13:27 ` Robert Millan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090824220419.GA31998@riva.ucam.org \
--to=cjwatson@ubuntu.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.