From: Robert Millan <rmh@aybabtu.com>
To: grub-devel@gnu.org
Cc: coreboot@coreboot.org, marco@gnu.org
Subject: [PATCH] USB keyboard
Date: Sun, 8 Feb 2009 20:53:23 +0100 [thread overview]
Message-ID: <20090208195323.GA3425@thorin> (raw)
[-- Attachment #1: Type: text/plain, Size: 405 bytes --]
Hi,
This patch implements USB keyboard support. It is based on work by Marco
Gerards, to which I made some adjustments, synced with trunk, and fixed a
pair of bugs.
--
Robert Millan
The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
how) you may access your data; but nobody's threatening your freedom: we
still allow you to remove your data and not access it at all."
[-- Attachment #2: usb_keyboard.diff --]
[-- Type: text/x-diff, Size: 7851 bytes --]
2009-02-08 Robert Millan <rmh@aybabtu.com>
Implement USB keyboard support (based on patch by Marco Gerards)
* conf/i386-pc.rmk (pkglib_MODULES): Add `usb_keyboard.mod'.
(usb_keyboard_mod_SOURCES, usb_keyboard_mod_CFLAGS)
(usb_keyboard_mod_LDFLAGS): New variables.
* term/usb_keyboard.c: New file.
Index: conf/i386-pc.rmk
===================================================================
--- conf/i386-pc.rmk (revision 1982)
+++ conf/i386-pc.rmk (working copy)
@@ -172,7 +172,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod
ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
datehook.mod lsmmap.mod \
- usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod
+ usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -333,6 +333,11 @@ usbms_mod_SOURCES = disk/usbms.c
usbms_mod_CFLAGS = $(COMMON_CFLAGS)
usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For usb_keyboard.mod
+usb_keyboard_mod_SOURCES = term/usb_keyboard.c
+usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
# For pxe.mod
pxe_mod_SOURCES = fs/i386/pc/pxe.c
pxe_mod_CFLAGS = $(COMMON_CFLAGS)
Index: term/usb_keyboard.c
===================================================================
--- term/usb_keyboard.c (revision 0)
+++ term/usb_keyboard.c (revision 0)
@@ -0,0 +1,257 @@
+/* Support for the HID Boot Protocol. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 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
+ * 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/term.h>
+#include <grub/machine/machine.h>
+#include <grub/machine/console.h>
+#include <grub/time.h>
+#include <grub/cpu/io.h>
+#include <grub/misc.h>
+#include <grub/term.h>
+#include <grub/usb.h>
+#include <grub/dl.h>
+#include <grub/time.h>
+
+\f
+static char keyboard_map[128] =
+ {
+ '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
+ '3', '4', '5', '6', '7', '8', '9', '0',
+ '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[',
+ ']', '\\', '#', ';', '\'', '`', ',', '.',
+ '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT,
+ GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP
+ };
+
+static char keyboard_map_shift[128] =
+ {
+ '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
+ '#', '$', '%', '^', '&', '*', '(', ')',
+ '\n', '\0', '\0', '\0', ' ', '_', '+', '{',
+ '}', '|', '#', ':', '"', '`', '<', '>',
+ '?'
+ };
+
+static grub_usb_device_t usbdev;
+
+static void
+grub_usb_hid (void)
+{
+ struct grub_usb_desc_device *descdev;
+
+ auto int usb_iterate (grub_usb_device_t dev);
+ int usb_iterate (grub_usb_device_t dev)
+ {
+ descdev = &dev->descdev;
+
+ grub_dprintf ("usb_keyboard", "%x %x %x\n",
+ descdev->class, descdev->subclass, descdev->protocol);
+
+#if 0
+ if (descdev->class != 0x09
+ || descdev->subclass == 0x01
+ || descdev->protocol != 0x02)
+ return 0;
+#endif
+
+ if (descdev->class != 0 || descdev->subclass != 0 || descdev->protocol != 0)
+ return 0;
+
+ grub_printf ("HID found!\n");
+
+ usbdev = dev;
+
+ return 1;
+ }
+ grub_usb_iterate (usb_iterate);
+
+ /* Place the device in boot mode. */
+ grub_usb_control_msg (usbdev, 0x21, 0x0B, 0, 0, 0, 0);
+
+ /* Reports everytime an event occurs and not more often than that. */
+ grub_usb_control_msg (usbdev, 0x21, 0x0A, 0<<8, 0, 0, 0);
+}
+
+static grub_err_t
+grub_usb_keyboard_getreport (grub_usb_device_t dev, unsigned char *report)
+{
+ return grub_usb_control_msg (dev, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
+ 8, (char *) report);
+}
+
+\f
+
+static int
+grub_usb_keyboard_checkkey (void)
+{
+ unsigned char data[8];
+ int key;
+ int i;
+ grub_err_t err;
+
+ data[2] = 0;
+ for (i = 0; i < 50; i++)
+ {
+ /* Get_Report. */
+ err = grub_usb_keyboard_getreport (usbdev, data);
+
+ if (! err && data[2])
+ break;
+ }
+
+ if (err || !data[2])
+ 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 if the Control or Shift key was pressed. */
+ if (data[0] & 0x01 || data[0] & 0x10)
+ key = keyboard_map[data[2]] - 'a' + 1;
+ else if (data[0] & 0x02 || data[0] & 0x20)
+ key = keyboard_map_shift[data[2]];
+ else
+ key = keyboard_map[data[2]];
+
+ if (key == 0)
+ grub_printf ("Unknown key 0x%x detected\n", data[2]);
+
+#if 0
+ /* Wait until the key is released. */
+ while (!err && data[2])
+ {
+ err = grub_usb_control_msg (usbdev, (1 << 7) | (1 << 5) | 1, 0x01, 0, 0,
+ sizeof (data), (char *) data);
+ grub_dprintf ("usb_keyboard",
+ "report2: 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]);
+ }
+#endif
+
+ grub_errno = GRUB_ERR_NONE;
+
+ return key;
+}
+
+typedef enum
+{
+ GRUB_HIDBOOT_REPEAT_NONE,
+ GRUB_HIDBOOT_REPEAT_FIRST,
+ GRUB_HIDBOOT_REPEAT
+} grub_usb_keyboard_repeat_t;
+
+static int
+grub_usb_keyboard_getkey (void)
+{
+ int key;
+ int key_release;
+ grub_err_t err;
+ unsigned char data[8];
+ grub_uint64_t currtime;
+ int timeout;
+ static grub_usb_keyboard_repeat_t repeat = GRUB_HIDBOOT_REPEAT_NONE;
+
+ again:
+
+ do
+ {
+ key = grub_usb_keyboard_checkkey ();
+ } while (key == -1);
+
+ data[2] = !0; /* Or whatever. */
+ err = 0;
+
+ switch (repeat)
+ {
+ case GRUB_HIDBOOT_REPEAT_NONE:
+ timeout = 100;
+ break;
+ case GRUB_HIDBOOT_REPEAT_FIRST:
+ timeout = 500;
+ break;
+ case GRUB_HIDBOOT_REPEAT:
+ timeout = 50;
+ break;
+ }
+
+ /* Wait until the key is released. */
+ currtime = grub_get_time_ms ();
+ while (!err && data[2])
+ {
+ /* Implement a timeout. */
+ if (grub_get_time_ms () > currtime + timeout)
+ {
+ if (repeat == 0)
+ repeat = 1;
+ else
+ repeat = 2;
+
+ grub_errno = GRUB_ERR_NONE;
+ return key;
+ }
+
+ err = grub_usb_keyboard_getreport (usbdev, data);
+ }
+
+ if (repeat)
+ {
+ repeat = 0;
+ goto again;
+ }
+
+ repeat = 0;
+
+ grub_errno = GRUB_ERR_NONE;
+
+ return key;
+}
+
+static struct grub_term_input grub_usb_keyboard_term =
+ {
+ .name = "usb_keyboard",
+ .checkkey = grub_usb_keyboard_checkkey,
+ .getkey = grub_usb_keyboard_getkey,
+ .next = 0
+ };
+
+GRUB_MOD_INIT(usb_keyboard)
+{
+ (void) mod; /* To stop warning. */
+
+ grub_usb_hid ();
+ grub_term_register_input (&grub_usb_keyboard_term);
+}
+
+GRUB_MOD_FINI(usb_keyboard)
+{
+ grub_term_unregister_input (&grub_usb_keyboard_term);
+}
next reply other threads:[~2009-02-08 19:54 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-08 19:53 Robert Millan [this message]
2009-02-08 20:04 ` [PATCH] USB keyboard step21
2009-02-09 14:09 ` Robert Millan
2009-02-09 14:27 ` step21
2009-02-09 17:23 ` step21
2009-02-21 14:55 ` 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=20090208195323.GA3425@thorin \
--to=rmh@aybabtu.com \
--cc=coreboot@coreboot.org \
--cc=grub-devel@gnu.org \
--cc=marco@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.