2009-08-28 Colin Watson <cjwatson@ubuntu.com>
2009-08-28 Robert Millan <rmh.grub@aybabtu.com> 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.
This commit is contained in:
parent
6e2a90859a
commit
4cbe67e509
15 changed files with 270 additions and 15 deletions
|
@ -58,6 +58,19 @@ static char keyboard_map_shift[128] =
|
|||
|
||||
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_hid (void)
|
|||
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 @@ grub_usb_keyboard_checkkey (void)
|
|||
/* 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 @@ grub_usb_keyboard_getkey (void)
|
|||
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
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue