From 771516d92320eccf7c517ec6481c257b564bf5dd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 1 Feb 2013 21:49:29 +0100 Subject: [PATCH 150/471] 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 + Implement USBDebug (full USB stack variant). + +2013-02-01 Vladimir Serbinenko + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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