31004e6
From 771516d92320eccf7c517ec6481c257b564bf5dd Mon Sep 17 00:00:00 2001
a5bd9f6
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
a5bd9f6
Date: Fri, 1 Feb 2013 21:49:29 +0100
f74b50e
Subject: [PATCH 150/482] 	Implement USBDebug (full USB stack variant).
a5bd9f6
a5bd9f6
---
a5bd9f6
 ChangeLog                                |  4 ++
a5bd9f6
 grub-core/Makefile.core.def              |  6 +++
a5bd9f6
 grub-core/bus/usb/serial/common.c        | 11 ++--
a5bd9f6
 grub-core/bus/usb/serial/ftdi.c          |  4 +-
a5bd9f6
 grub-core/bus/usb/serial/pl2303.c        |  4 +-
a5bd9f6
 grub-core/bus/usb/serial/usbdebug_late.c | 93 ++++++++++++++++++++++++++++++++
a5bd9f6
 grub-core/bus/usb/usb.c                  |  2 +
a5bd9f6
 include/grub/usbdesc.h                   |  9 ++++
a5bd9f6
 include/grub/usbserial.h                 |  7 ++-
a5bd9f6
 9 files changed, 134 insertions(+), 6 deletions(-)
a5bd9f6
 create mode 100644 grub-core/bus/usb/serial/usbdebug_late.c
a5bd9f6
a5bd9f6
diff --git a/ChangeLog b/ChangeLog
a5bd9f6
index 4141f6a..2e681c1 100644
a5bd9f6
--- a/ChangeLog
a5bd9f6
+++ b/ChangeLog
a5bd9f6
@@ -1,5 +1,9 @@
a5bd9f6
 2013-02-01  Vladimir Serbinenko  <phcoder@gmail.com>
a5bd9f6
 
a5bd9f6
+	Implement USBDebug (full USB stack variant).
a5bd9f6
+
a5bd9f6
+2013-02-01  Vladimir Serbinenko  <phcoder@gmail.com>
a5bd9f6
+
a5bd9f6
 	* grub-core/commands/lsacpi.c: Show more info. Hide some boring parts
a5bd9f6
 	unless they have unexpected values.
a5bd9f6
 
a5bd9f6
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
a5bd9f6
index 4609a4b..c006abf 100644
a5bd9f6
--- a/grub-core/Makefile.core.def
a5bd9f6
+++ b/grub-core/Makefile.core.def
a5bd9f6
@@ -448,6 +448,12 @@ module = {
a5bd9f6
 };
a5bd9f6
 
a5bd9f6
 module = {
a5bd9f6
+  name = usbserial_usbdebug;
a5bd9f6
+  common = bus/usb/serial/usbdebug_late.c;
a5bd9f6
+  enable = usb;
a5bd9f6
+};
a5bd9f6
+
a5bd9f6
+module = {
a5bd9f6
   name = uhci;
a5bd9f6
   common = bus/usb/uhci.c;
a5bd9f6
   enable = x86;
a5bd9f6
diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c
a5bd9f6
index 9530259..06f2b0e 100644
a5bd9f6
--- a/grub-core/bus/usb/serial/common.c
a5bd9f6
+++ b/grub-core/bus/usb/serial/common.c
a5bd9f6
@@ -42,7 +42,8 @@ static int usbnum = 0;
a5bd9f6
 
a5bd9f6
 int
a5bd9f6
 grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
a5bd9f6
-		       struct grub_serial_driver *driver)
a5bd9f6
+		       struct grub_serial_driver *driver, int in_endp,
a5bd9f6
+		       int out_endp)
a5bd9f6
 {
a5bd9f6
   struct grub_serial_port *port;
a5bd9f6
   int j;
a5bd9f6
@@ -73,12 +74,16 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
a5bd9f6
       struct grub_usb_desc_endp *endp;
a5bd9f6
       endp = &usbdev->config[0].interf[interfno].descendp[j];
a5bd9f6
 
a5bd9f6
-      if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
a5bd9f6
+      if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2
a5bd9f6
+	  && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING
a5bd9f6
+	      || in_endp == endp->endp_addr))
a5bd9f6
 	{
a5bd9f6
 	  /* Bulk IN endpoint.  */
a5bd9f6
 	  port->in_endp = endp;
a5bd9f6
 	}
a5bd9f6
-      else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
a5bd9f6
+      else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2
a5bd9f6
+	       && (out_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING
a5bd9f6
+		   || out_endp == endp->endp_addr))
a5bd9f6
 	{
a5bd9f6
 	  /* Bulk OUT endpoint.  */
a5bd9f6
 	  port->out_endp = endp;
a5bd9f6
diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c
a5bd9f6
index 15ea8fb..e94fd27 100644
a5bd9f6
--- a/grub-core/bus/usb/serial/ftdi.c
a5bd9f6
+++ b/grub-core/bus/usb/serial/ftdi.c
a5bd9f6
@@ -193,7 +193,9 @@ grub_ftdi_attach (grub_usb_device_t usbdev, int configno, int interfno)
a5bd9f6
     return 0;
a5bd9f6
 
a5bd9f6
   return grub_usbserial_attach (usbdev, configno, interfno,
a5bd9f6
-				&grub_ftdi_driver);
a5bd9f6
+				&grub_ftdi_driver,
a5bd9f6
+				GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING,
a5bd9f6
+				GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING);
a5bd9f6
 }
a5bd9f6
 
a5bd9f6
 static struct grub_usb_attach_desc attach_hook =
a5bd9f6
diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c
a5bd9f6
index 5433763..f46c6ac 100644
a5bd9f6
--- a/grub-core/bus/usb/serial/pl2303.c
a5bd9f6
+++ b/grub-core/bus/usb/serial/pl2303.c
a5bd9f6
@@ -208,7 +208,9 @@ grub_pl2303_attach (grub_usb_device_t usbdev, int configno, int interfno)
a5bd9f6
     return 0;
a5bd9f6
 
a5bd9f6
   return grub_usbserial_attach (usbdev, configno, interfno,
a5bd9f6
-				&grub_pl2303_driver);
a5bd9f6
+				&grub_pl2303_driver,
a5bd9f6
+				GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING,
a5bd9f6
+				GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING);
a5bd9f6
 }
a5bd9f6
 
a5bd9f6
 static struct grub_usb_attach_desc attach_hook =
a5bd9f6
diff --git a/grub-core/bus/usb/serial/usbdebug_late.c b/grub-core/bus/usb/serial/usbdebug_late.c
a5bd9f6
new file mode 100644
a5bd9f6
index 0000000..23526e1
a5bd9f6
--- /dev/null
a5bd9f6
+++ b/grub-core/bus/usb/serial/usbdebug_late.c
a5bd9f6
@@ -0,0 +1,93 @@
a5bd9f6
+/*
a5bd9f6
+ *  GRUB  --  GRand Unified Bootloader
a5bd9f6
+ *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2013  Free Software Foundation, Inc.
a5bd9f6
+ *
a5bd9f6
+ *  GRUB is free software: you can redistribute it and/or modify
a5bd9f6
+ *  it under the terms of the GNU General Public License as published by
a5bd9f6
+ *  the Free Software Foundation, either version 3 of the License, or
a5bd9f6
+ *  (at your option) any later version.
a5bd9f6
+ *
a5bd9f6
+ *  GRUB is distributed in the hope that it will be useful,
a5bd9f6
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
a5bd9f6
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
a5bd9f6
+ *  GNU General Public License for more details.
a5bd9f6
+ *
a5bd9f6
+ *  You should have received a copy of the GNU General Public License
a5bd9f6
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
a5bd9f6
+ */
a5bd9f6
+
a5bd9f6
+#include <grub/serial.h>
a5bd9f6
+#include <grub/types.h>
a5bd9f6
+#include <grub/dl.h>
a5bd9f6
+#include <grub/misc.h>
a5bd9f6
+#include <grub/mm.h>
a5bd9f6
+#include <grub/usb.h>
a5bd9f6
+#include <grub/usbserial.h>
a5bd9f6
+#include <grub/i18n.h>
a5bd9f6
+
a5bd9f6
+GRUB_MOD_LICENSE ("GPLv3+");
a5bd9f6
+
a5bd9f6
+
a5bd9f6
+/* Fetch a key.  */
a5bd9f6
+static int
a5bd9f6
+usbdebug_late_hw_fetch (struct grub_serial_port *port)
a5bd9f6
+{
a5bd9f6
+  return grub_usbserial_fetch (port, 0);
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
+/* Put a character.  */
a5bd9f6
+static void
a5bd9f6
+usbdebug_late_hw_put (struct grub_serial_port *port, const int c)
a5bd9f6
+{
a5bd9f6
+  char cc = c;
a5bd9f6
+
a5bd9f6
+  grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc);
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
+static grub_err_t
a5bd9f6
+usbdebug_late_hw_configure (struct grub_serial_port *port __attribute__ ((unused)),
a5bd9f6
+			    struct grub_serial_config *config __attribute__ ((unused)))
a5bd9f6
+{
a5bd9f6
+  return GRUB_ERR_NONE;
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
+static struct grub_serial_driver grub_usbdebug_late_driver =
a5bd9f6
+  {
a5bd9f6
+    .configure = usbdebug_late_hw_configure,
a5bd9f6
+    .fetch = usbdebug_late_hw_fetch,
a5bd9f6
+    .put = usbdebug_late_hw_put,
a5bd9f6
+    .fini = grub_usbserial_fini
a5bd9f6
+  };
a5bd9f6
+
a5bd9f6
+static int
a5bd9f6
+grub_usbdebug_late_attach (grub_usb_device_t usbdev, int configno, int interfno)
a5bd9f6
+{
a5bd9f6
+  grub_usb_err_t err;
a5bd9f6
+  struct grub_usb_desc_debug debugdesc;
a5bd9f6
+
a5bd9f6
+  err = grub_usb_get_descriptor (usbdev, GRUB_USB_DESCRIPTOR_DEBUG, configno,
a5bd9f6
+				 sizeof (debugdesc), (char *) &debugdesc);
a5bd9f6
+  if (err)
a5bd9f6
+    return 0;
a5bd9f6
+
a5bd9f6
+  return grub_usbserial_attach (usbdev, configno, interfno,
a5bd9f6
+				&grub_usbdebug_late_driver,
a5bd9f6
+				debugdesc.in_endp, debugdesc.out_endp);
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
+static struct grub_usb_attach_desc attach_hook =
a5bd9f6
+{
a5bd9f6
+  .class = 0xff,
a5bd9f6
+  .hook = grub_usbdebug_late_attach
a5bd9f6
+};
a5bd9f6
+
a5bd9f6
+GRUB_MOD_INIT(usbserial_usbdebug_late)
a5bd9f6
+{
a5bd9f6
+  grub_usb_register_attach_hook_class (&attach_hook);
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
+GRUB_MOD_FINI(usbserial_usbdebug_late)
a5bd9f6
+{
a5bd9f6
+  grub_serial_unregister_driver (&grub_usbdebug_late_driver);
a5bd9f6
+  grub_usb_unregister_attach_hook_class (&attach_hook);
a5bd9f6
+}
a5bd9f6
diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
a5bd9f6
index 5df08e9..41d8010 100644
a5bd9f6
--- a/grub-core/bus/usb/usb.c
a5bd9f6
+++ b/grub-core/bus/usb/usb.c
a5bd9f6
@@ -309,6 +309,8 @@ void grub_usb_device_attach (grub_usb_device_t dev)
a5bd9f6
 	  grub_print_error ();
a5bd9f6
 	  grub_dl_load ("usbserial_pl2303");
a5bd9f6
 	  grub_print_error ();
a5bd9f6
+	  grub_dl_load ("usbserial_usbdebug");
a5bd9f6
+	  grub_print_error ();
a5bd9f6
 	  break;
a5bd9f6
 	}
a5bd9f6
     }
a5bd9f6
diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
a5bd9f6
index 84b723a..7d14152 100644
a5bd9f6
--- a/include/grub/usbdesc.h
a5bd9f6
+++ b/include/grub/usbdesc.h
a5bd9f6
@@ -28,6 +28,7 @@ typedef enum {
a5bd9f6
   GRUB_USB_DESCRIPTOR_STRING,
a5bd9f6
   GRUB_USB_DESCRIPTOR_INTERFACE,
a5bd9f6
   GRUB_USB_DESCRIPTOR_ENDPOINT,
a5bd9f6
+  GRUB_USB_DESCRIPTOR_DEBUG = 10,
a5bd9f6
   GRUB_USB_DESCRIPTOR_HUB = 0x29
a5bd9f6
 } grub_usb_descriptor_t;
a5bd9f6
 
a5bd9f6
@@ -111,6 +112,14 @@ struct grub_usb_desc_str
a5bd9f6
   grub_uint16_t str[0];
a5bd9f6
 } __attribute__ ((packed));
a5bd9f6
 
a5bd9f6
+struct grub_usb_desc_debug
a5bd9f6
+{
a5bd9f6
+  grub_uint8_t length;
a5bd9f6
+  grub_uint8_t type;
a5bd9f6
+  grub_uint8_t in_endp;
a5bd9f6
+  grub_uint8_t out_endp;
a5bd9f6
+} __attribute__ ((packed));
a5bd9f6
+
a5bd9f6
 struct grub_usb_usb_hubdesc
a5bd9f6
 {
a5bd9f6
   grub_uint8_t length;
a5bd9f6
diff --git a/include/grub/usbserial.h b/include/grub/usbserial.h
a5bd9f6
index 7420125..f81f97a 100644
a5bd9f6
--- a/include/grub/usbserial.h
a5bd9f6
+++ b/include/grub/usbserial.h
a5bd9f6
@@ -27,7 +27,12 @@ void grub_usbserial_detach (grub_usb_device_t usbdev, int configno,
a5bd9f6
 
a5bd9f6
 int
a5bd9f6
 grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
a5bd9f6
-		       struct grub_serial_driver *driver);
a5bd9f6
+		       struct grub_serial_driver *driver, int in_endp,
a5bd9f6
+		       int out_endp);
a5bd9f6
+enum
a5bd9f6
+  {
a5bd9f6
+    GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING = -1
a5bd9f6
+  };
a5bd9f6
 int
a5bd9f6
 grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size);
a5bd9f6
 
a5bd9f6
-- 
31004e6
1.8.2.1
a5bd9f6