Signed-off-by: Sven Schnelle <svens@xxxxxxxxxxxxxx> --- drivers/usb/gadget/dbgp.c | 86 +++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 80 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index 8beefdd..22a8007 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -13,6 +13,8 @@ #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> +#include "config.c" + /* See comments in "zero.c" */ #include "epautoconf.c" @@ -66,6 +68,41 @@ static struct usb_endpoint_descriptor o_desc = { .bEndpointAddress = USB_DIR_OUT, }; + +static struct usb_config_descriptor config_desc = { + .bLength = sizeof config_desc, + .bDescriptorType = USB_DT_CONFIG, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, + .wTotalLength = __constant_cpu_to_le16( + sizeof(struct usb_config_descriptor)), +}; + +static struct usb_interface_descriptor intf_desc = { + .bLength = sizeof intf_desc, + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, +}; + +static struct usb_qualifier_descriptor dev_qualifier = { + .bLength = sizeof dev_qualifier, + .bDescriptorType = USB_DT_DEVICE_QUALIFIER, + .bcdUSB = cpu_to_le16(0x0200), + .bDeviceClass = USB_CLASS_VENDOR_SPEC, + .bNumConfigurations = 1 +}; + +static const struct usb_descriptor_header *function[11] = { + (struct usb_descriptor_header *) &intf_desc, + (struct usb_descriptor_header *) &i_desc, + (struct usb_descriptor_header *) &o_desc, + NULL +}; + #ifdef CONFIG_USB_G_DBGP_PRINTK static int dbgp_consume(char *buf, unsigned len) { @@ -349,6 +386,7 @@ static int dbgp_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) { struct usb_request *req = dbgp.req; + struct usb_config_descriptor *buf; u8 request = ctrl->bRequest; u16 value = le16_to_cpu(ctrl->wValue); u16 length = le16_to_cpu(ctrl->wLength); @@ -358,7 +396,8 @@ static int dbgp_setup(struct usb_gadget *gadget, gadget->ep0->driver_data = gadget; - if (request == USB_REQ_GET_DESCRIPTOR) { + switch (request) { + case USB_REQ_GET_DESCRIPTOR: switch (value>>8) { case USB_DT_DEVICE: dev_dbg(&dbgp.gadget->dev, "setup: desc device\n"); @@ -371,12 +410,43 @@ static int dbgp_setup(struct usb_gadget *gadget, len = sizeof dbg_desc; data = &dbg_desc; break; + case USB_DT_CONFIG: + if ((value & 0xff) > 0) + return -EINVAL; + + buf = (struct usb_config_descriptor *)req->buf; + len = usb_gadget_config_buf(&config_desc, buf, 256, + function); + buf->bDescriptorType = value >> 8; + break; +#ifdef CONFIG_USB_GADGET_DUALSPEED + case USB_DT_DEVICE_QUALIFIER: + if (!gadget->is_dualspeed) + break; + /* + * assumes ep0 uses the same value for both + * speeds + */ + dev_qualifier.bMaxPacketSize0 = gadget->ep0->maxpacket; + len = min(length, (u16) sizeof dev_qualifier); + data = &dev_qualifier; + break; + + case USB_DT_OTHER_SPEED_CONFIG: + if (!gadget->is_dualspeed) + break; + /* FALLTHROUGH */ +#endif /* CONFIG_USB_GADGET_DUALSPEED */ + default: goto fail; } - err = 0; - } else if (request == USB_REQ_SET_FEATURE && - value == USB_DEVICE_DEBUG_MODE) { + break; + + case USB_REQ_SET_FEATURE: + if (value != USB_DEVICE_DEBUG_MODE) + goto fail; + dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n"); #ifdef CONFIG_USB_G_DBGP_PRINTK err = dbgp_enable_ep(); @@ -385,9 +455,13 @@ static int dbgp_setup(struct usb_gadget *gadget, #endif if (err < 0) goto fail; - } else - goto fail; + break; + case USB_REQ_SET_CONFIGURATION: + break; + default: + goto fail; +} req->length = min(length, len); req->zero = len < req->length; if (data && req->length) -- 1.7.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html