From 771516d92320eccf7c517ec6481c257b564bf5dd Mon Sep 17 00:00:00 2001
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Date: Fri, 1 Feb 2013 21:49:29 +0100
Subject: [PATCH 150/482] Implement USBDebug (full USB stack variant).
---
ChangeLog | 4 ++
grub-core/Makefile.core.def | 6 +++
grub-core/bus/usb/serial/common.c | 11 ++--
grub-core/bus/usb/serial/ftdi.c | 4 +-
grub-core/bus/usb/serial/pl2303.c | 4 +-
grub-core/bus/usb/serial/usbdebug_late.c | 93 ++++++++++++++++++++++++++++++++
grub-core/bus/usb/usb.c | 2 +
include/grub/usbdesc.h | 9 ++++
include/grub/usbserial.h | 7 ++-
9 files changed, 134 insertions(+), 6 deletions(-)
create mode 100644 grub-core/bus/usb/serial/usbdebug_late.c
diff --git a/ChangeLog b/ChangeLog
index 4141f6a..2e681c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2013-02-01 Vladimir Serbinenko <phcoder@gmail.com>
+ Implement USBDebug (full USB stack variant).
+
+2013-02-01 Vladimir Serbinenko <phcoder@gmail.com>
+
* grub-core/commands/lsacpi.c: Show more info. Hide some boring parts
unless they have unexpected values.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 4609a4b..c006abf 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -448,6 +448,12 @@ module = {
};
module = {
+ name = usbserial_usbdebug;
+ common = bus/usb/serial/usbdebug_late.c;
+ enable = usb;
+};
+
+module = {
name = uhci;
common = bus/usb/uhci.c;
enable = x86;
diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c
index 9530259..06f2b0e 100644
--- a/grub-core/bus/usb/serial/common.c
+++ b/grub-core/bus/usb/serial/common.c
@@ -42,7 +42,8 @@ static int usbnum = 0;
int
grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
- struct grub_serial_driver *driver)
+ struct grub_serial_driver *driver, int in_endp,
+ int out_endp)
{
struct grub_serial_port *port;
int j;
@@ -73,12 +74,16 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
struct grub_usb_desc_endp *endp;
endp = &usbdev->config[0].interf[interfno].descendp[j];
- if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
+ if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2
+ && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING
+ || in_endp == endp->endp_addr))
{
/* Bulk IN endpoint. */
port->in_endp = endp;
}
- else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
+ else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2
+ && (out_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING
+ || out_endp == endp->endp_addr))
{
/* Bulk OUT endpoint. */
port->out_endp = endp;
diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c
index 15ea8fb..e94fd27 100644
--- a/grub-core/bus/usb/serial/ftdi.c
+++ b/grub-core/bus/usb/serial/ftdi.c
@@ -193,7 +193,9 @@ grub_ftdi_attach (grub_usb_device_t usbdev, int configno, int interfno)
return 0;
return grub_usbserial_attach (usbdev, configno, interfno,
- &grub_ftdi_driver);
+ &grub_ftdi_driver,
+ GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING,
+ GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING);
}
static struct grub_usb_attach_desc attach_hook =
diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c
index 5433763..f46c6ac 100644
--- a/grub-core/bus/usb/serial/pl2303.c
+++ b/grub-core/bus/usb/serial/pl2303.c
@@ -208,7 +208,9 @@ grub_pl2303_attach (grub_usb_device_t usbdev, int configno, int interfno)
return 0;
return grub_usbserial_attach (usbdev, configno, interfno,
- &grub_pl2303_driver);
+ &grub_pl2303_driver,
+ GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING,
+ GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING);
}
static struct grub_usb_attach_desc attach_hook =
diff --git a/grub-core/bus/usb/serial/usbdebug_late.c b/grub-core/bus/usb/serial/usbdebug_late.c
new file mode 100644
index 0000000..23526e1
--- /dev/null
+++ b/grub-core/bus/usb/serial/usbdebug_late.c
@@ -0,0 +1,93 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2013 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/serial.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/usb.h>
+#include <grub/usbserial.h>
+#include <grub/i18n.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+
+/* Fetch a key. */
+static int
+usbdebug_late_hw_fetch (struct grub_serial_port *port)
+{
+ return grub_usbserial_fetch (port, 0);
+}
+
+/* Put a character. */
+static void
+usbdebug_late_hw_put (struct grub_serial_port *port, const int c)
+{
+ char cc = c;
+
+ grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc);
+}
+
+static grub_err_t
+usbdebug_late_hw_configure (struct grub_serial_port *port __attribute__ ((unused)),
+ struct grub_serial_config *config __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_serial_driver grub_usbdebug_late_driver =
+ {
+ .configure = usbdebug_late_hw_configure,
+ .fetch = usbdebug_late_hw_fetch,
+ .put = usbdebug_late_hw_put,
+ .fini = grub_usbserial_fini
+ };
+
+static int
+grub_usbdebug_late_attach (grub_usb_device_t usbdev, int configno, int interfno)
+{
+ grub_usb_err_t err;
+ struct grub_usb_desc_debug debugdesc;
+
+ err = grub_usb_get_descriptor (usbdev, GRUB_USB_DESCRIPTOR_DEBUG, configno,
+ sizeof (debugdesc), (char *) &debugdesc);
+ if (err)
+ return 0;
+
+ return grub_usbserial_attach (usbdev, configno, interfno,
+ &grub_usbdebug_late_driver,
+ debugdesc.in_endp, debugdesc.out_endp);
+}
+
+static struct grub_usb_attach_desc attach_hook =
+{
+ .class = 0xff,
+ .hook = grub_usbdebug_late_attach
+};
+
+GRUB_MOD_INIT(usbserial_usbdebug_late)
+{
+ grub_usb_register_attach_hook_class (&attach_hook);
+}
+
+GRUB_MOD_FINI(usbserial_usbdebug_late)
+{
+ grub_serial_unregister_driver (&grub_usbdebug_late_driver);
+ grub_usb_unregister_attach_hook_class (&attach_hook);
+}
diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
index 5df08e9..41d8010 100644
--- a/grub-core/bus/usb/usb.c
+++ b/grub-core/bus/usb/usb.c
@@ -309,6 +309,8 @@ void grub_usb_device_attach (grub_usb_device_t dev)
grub_print_error ();
grub_dl_load ("usbserial_pl2303");
grub_print_error ();
+ grub_dl_load ("usbserial_usbdebug");
+ grub_print_error ();
break;
}
}
diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
index 84b723a..7d14152 100644
--- a/include/grub/usbdesc.h
+++ b/include/grub/usbdesc.h
@@ -28,6 +28,7 @@ typedef enum {
GRUB_USB_DESCRIPTOR_STRING,
GRUB_USB_DESCRIPTOR_INTERFACE,
GRUB_USB_DESCRIPTOR_ENDPOINT,
+ GRUB_USB_DESCRIPTOR_DEBUG = 10,
GRUB_USB_DESCRIPTOR_HUB = 0x29
} grub_usb_descriptor_t;
@@ -111,6 +112,14 @@ struct grub_usb_desc_str
grub_uint16_t str[0];
} __attribute__ ((packed));
+struct grub_usb_desc_debug
+{
+ grub_uint8_t length;
+ grub_uint8_t type;
+ grub_uint8_t in_endp;
+ grub_uint8_t out_endp;
+} __attribute__ ((packed));
+
struct grub_usb_usb_hubdesc
{
grub_uint8_t length;
diff --git a/include/grub/usbserial.h b/include/grub/usbserial.h
index 7420125..f81f97a 100644
--- a/include/grub/usbserial.h
+++ b/include/grub/usbserial.h
@@ -27,7 +27,12 @@ void grub_usbserial_detach (grub_usb_device_t usbdev, int configno,
int
grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
- struct grub_serial_driver *driver);
+ struct grub_serial_driver *driver, int in_endp,
+ int out_endp);
+enum
+ {
+ GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING = -1
+ };
int
grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size);
--
1.8.2.1