[1998] 2009-02-21 Robert Millan <[email protected]>

Robert Millan <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 1998
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=1998
Author:   robertmh
Date:     2009-02-21 14:55:06 +0000 (Sat, 21 Feb 2009)

Log Message:
-----------
2009-02-21  Robert Millan  <[email protected]>

        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.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/DISTLIST
    trunk/grub2/conf/i386-pc.mk
    trunk/grub2/conf/i386-pc.rmk

Added Paths:
-----------
    trunk/grub2/term/usb_keyboard.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2009-02-21 12:41:18 UTC (rev 1997)
+++ trunk/grub2/ChangeLog	2009-02-21 14:55:06 UTC (rev 1998)
@@ -1,3 +1,13 @@
+2009-02-21  Robert Millan  <[email protected]>
+
+	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.
+
 2009-02-14  Vladimir Serbinenko  <[email protected]>
 
 	Corrected wrong declaration

Modified: trunk/grub2/DISTLIST
===================================================================
--- trunk/grub2/DISTLIST	2009-02-21 12:41:18 UTC (rev 1997)
+++ trunk/grub2/DISTLIST	2009-02-21 14:55:06 UTC (rev 1998)
@@ -425,6 +425,7 @@
 term/gfxterm.c
 term/terminfo.c
 term/tparm.c
+term/usb_keyboard.c
 term/efi/console.c
 term/i386/vga_common.c
 term/i386/pc/at_keyboard.c

Modified: trunk/grub2/conf/i386-pc.mk
===================================================================
--- trunk/grub2/conf/i386-pc.mk	2009-02-21 12:41:18 UTC (rev 1997)
+++ trunk/grub2/conf/i386-pc.mk	2009-02-21 14:55:06 UTC (rev 1998)
@@ -980,7 +980,7 @@
 	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 ata_pthru.mod hdparm.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
@@ -3054,6 +3054,63 @@
 usbms_mod_CFLAGS = $(COMMON_CFLAGS)
 usbms_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For usb_keyboard.mod
+usb_keyboard_mod_SOURCES = term/usb_keyboard.c
+CLEANFILES += usb_keyboard.mod mod-usb_keyboard.o mod-usb_keyboard.c pre-usb_keyboard.o usb_keyboard_mod-term_usb_keyboard.o und-usb_keyboard.lst
+ifneq ($(usb_keyboard_mod_EXPORTS),no)
+CLEANFILES += def-usb_keyboard.lst
+DEFSYMFILES += def-usb_keyboard.lst
+endif
+MOSTLYCLEANFILES += usb_keyboard_mod-term_usb_keyboard.d
+UNDSYMFILES += und-usb_keyboard.lst
+
+usb_keyboard.mod: pre-usb_keyboard.o mod-usb_keyboard.o $(TARGET_OBJ2ELF)
+	-rm -f $@
+	$(TARGET_CC) $(usb_keyboard_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-usb_keyboard.o mod-usb_keyboard.o
+	if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-usb_keyboard.o: $(usb_keyboard_mod_DEPENDENCIES) usb_keyboard_mod-term_usb_keyboard.o
+	-rm -f $@
+	$(TARGET_CC) $(usb_keyboard_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ usb_keyboard_mod-term_usb_keyboard.o
+
+mod-usb_keyboard.o: mod-usb_keyboard.c
+	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -c -o $@ $<
+
+mod-usb_keyboard.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+	sh $(srcdir)/genmodsrc.sh 'usb_keyboard' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(usb_keyboard_mod_EXPORTS),no)
+def-usb_keyboard.lst: pre-usb_keyboard.o
+	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 usb_keyboard/' > $@
+endif
+
+und-usb_keyboard.lst: pre-usb_keyboard.o
+	echo 'usb_keyboard' > $@
+	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+usb_keyboard_mod-term_usb_keyboard.o: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES)
+	$(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -MD -c -o $@ $<
+-include usb_keyboard_mod-term_usb_keyboard.d
+
+CLEANFILES += cmd-usb_keyboard_mod-term_usb_keyboard.lst fs-usb_keyboard_mod-term_usb_keyboard.lst partmap-usb_keyboard_mod-term_usb_keyboard.lst
+COMMANDFILES += cmd-usb_keyboard_mod-term_usb_keyboard.lst
+FSFILES += fs-usb_keyboard_mod-term_usb_keyboard.lst
+PARTMAPFILES += partmap-usb_keyboard_mod-term_usb_keyboard.lst
+
+cmd-usb_keyboard_mod-term_usb_keyboard.lst: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES) gencmdlist.sh
+	set -e; 	  $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh usb_keyboard > $@ || (rm -f $@; exit 1)
+
+fs-usb_keyboard_mod-term_usb_keyboard.lst: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES) genfslist.sh
+	set -e; 	  $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh usb_keyboard > $@ || (rm -f $@; exit 1)
+
+partmap-usb_keyboard_mod-term_usb_keyboard.lst: term/usb_keyboard.c $(term/usb_keyboard.c_DEPENDENCIES) genpartmaplist.sh
+	set -e; 	  $(TARGET_CC) -Iterm -I$(srcdir)/term $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(usb_keyboard_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh usb_keyboard > $@ || (rm -f $@; exit 1)
+
+
+usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For pxe.mod
 pxe_mod_SOURCES = fs/i386/pc/pxe.c
 CLEANFILES += pxe.mod mod-pxe.o mod-pxe.c pre-pxe.o pxe_mod-fs_i386_pc_pxe.o und-pxe.lst

Modified: trunk/grub2/conf/i386-pc.rmk
===================================================================
--- trunk/grub2/conf/i386-pc.rmk	2009-02-21 12:41:18 UTC (rev 1997)
+++ trunk/grub2/conf/i386-pc.rmk	2009-02-21 14:55:06 UTC (rev 1998)
@@ -173,7 +173,7 @@
 	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 ata_pthru.mod hdparm.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
@@ -335,6 +335,11 @@
 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)

Added: trunk/grub2/term/usb_keyboard.c
===================================================================
--- trunk/grub2/term/usb_keyboard.c	                        (rev 0)
+++ trunk/grub2/term/usb_keyboard.c	2009-02-21 14:55:06 UTC (rev 1998)
@@ -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>
+
+
+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);
+}
+
+
+
+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);
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.