From patchwork Mon Mar 26 10:08:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Virdi X-Patchwork-Id: 148684 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 54BB5B6F98 for ; Mon, 26 Mar 2012 21:08:41 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6B6EB2810A; Mon, 26 Mar 2012 12:08:38 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 42EP0RHAFORn; Mon, 26 Mar 2012 12:08:37 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B4D6928103; Mon, 26 Mar 2012 12:08:28 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B64CF28103 for ; Mon, 26 Mar 2012 12:08:25 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id A1Ue0xTPifjJ for ; Mon, 26 Mar 2012 12:08:24 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from eu1sys200aog113.obsmtp.com (eu1sys200aog113.obsmtp.com [207.126.144.135]) by theia.denx.de (Postfix) with ESMTPS id 5A5FB28102 for ; Mon, 26 Mar 2012 12:08:19 +0200 (CEST) Received: from beta.dmz-ap.st.com ([138.198.100.35]) (using TLSv1) by eu1sys200aob113.postini.com ([207.126.147.11]) with SMTP ID DSNKT3BAD3TTcnaA2AlH4ALrqenbC53IlcXK@postini.com; Mon, 26 Mar 2012 10:08:22 UTC Received: from zeta.dmz-ap.st.com (ns6.st.com [138.198.234.13]) by beta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 3422F16D; Mon, 26 Mar 2012 09:59:48 +0000 (GMT) Received: from Webmail-ap.st.com (eapex1hubcas4.st.com [10.80.176.69]) by zeta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 69874166E; Mon, 26 Mar 2012 10:08:12 +0000 (GMT) Received: from localhost (10.199.7.86) by Webmail-ap.st.com (10.80.176.7) with Microsoft SMTP Server (TLS) id 8.3.192.1; Mon, 26 Mar 2012 18:07:16 +0800 From: Amit Virdi To: Date: Mon, 26 Mar 2012 15:38:06 +0530 Message-ID: <1332756486-19245-1-git-send-email-amit.virdi@st.com> X-Mailer: git-send-email 1.7.2.2 MIME-Version: 1.0 Cc: Amit Virdi , sr@denx.de, spear-devel@list.st.com Subject: [U-Boot] [PATCH V2] Enable high speed support for USB device framework and usbtty X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Vipin KUMAR This patch adds the support for high speed in usb device framework and usbtty driver. This feature has been kept within a macro CONFIG_USBD_HS, so the board configuration files have to define this macro to enable high speed support. Along with that specific peripheral drivers also need to define a function to let the framework know that the enumeration has happened at high speed. This function prototype is "int is_usbd_high_speed(void)" Signed-off-by: Vipin Kumar Signed-off-by: Amit Virdi --- README | 8 +++++++ drivers/serial/usbtty.c | 50 ++++++++++++++++++++++++++++++++++++++++++++- drivers/serial/usbtty.h | 4 +++ drivers/usb/gadget/core.c | 1 - drivers/usb/gadget/ep0.c | 23 +++++++++++++++++--- include/usbdescriptors.h | 15 +++++++++++++ include/usbdevice.h | 22 ++++++++++++++++++- 7 files changed, 116 insertions(+), 7 deletions(-) diff --git a/README b/README index b69a3b6..0ab6892 100644 --- a/README +++ b/README @@ -1148,6 +1148,14 @@ The following options need to be configured: Define this to have a tty type of device available to talk to the UDC device + CONFIG_USBD_HS + Define this to enable the high speed support for usb + device and usbtty. If this feature is enabled, a routine + int is_usbd_high_speed(void) + also needs to be defined by the driver to dynamically poll + whether the enumeration has succeded at high speed or full + speed. + CONFIG_SYS_CONSOLE_IS_IN_ENV Define this if you want stdin, stdout &/or stderr to be set to usbtty. diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c index 550bc58..148d1a6 100644 --- a/drivers/serial/usbtty.c +++ b/drivers/serial/usbtty.c @@ -133,6 +133,19 @@ static struct usb_device_descriptor device_descriptor = { }; +#if defined(CONFIG_USBD_HS) +static struct usb_qualifier_descriptor qualifier_descriptor = { + .bLength = sizeof(struct usb_qualifier_descriptor), + .bDescriptorType = USB_DT_QUAL, + .bcdUSB = cpu_to_le16(USB_BCD_VERSION), + .bDeviceClass = COMMUNICATIONS_DEVICE_CLASS, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, + .bNumConfigurations = NUM_CONFIGS +}; +#endif + /* * Static CDC ACM specific descriptors */ @@ -638,6 +651,9 @@ static void usbtty_init_instances (void) memset (device_instance, 0, sizeof (struct usb_device_instance)); device_instance->device_state = STATE_INIT; device_instance->device_descriptor = &device_descriptor; +#if defined(CONFIG_USBD_HS) + device_instance->qualifier_descriptor = &qualifier_descriptor; +#endif device_instance->event = usbtty_event_handler; device_instance->cdc_recv_setup = usbtty_cdc_setup; device_instance->bus = bus_instance; @@ -751,6 +767,10 @@ static void usbtty_init_terminal_type(short type) device_descriptor.idProduct = cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM); +#if defined(CONFIG_USBD_HS) + qualifier_descriptor.bDeviceClass = + COMMUNICATIONS_DEVICE_CLASS; +#endif /* Assign endpoint indices */ tx_endpoint = ACM_TX_ENDPOINT; rx_endpoint = ACM_RX_ENDPOINT; @@ -779,7 +799,9 @@ static void usbtty_init_terminal_type(short type) device_descriptor.bDeviceClass = 0xFF; device_descriptor.idProduct = cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL); - +#if defined(CONFIG_USBD_HS) + qualifier_descriptor.bDeviceClass = 0xFF; +#endif /* Assign endpoint indices */ tx_endpoint = GSERIAL_TX_ENDPOINT; rx_endpoint = GSERIAL_RX_ENDPOINT; @@ -932,6 +954,9 @@ static int usbtty_configured (void) static void usbtty_event_handler (struct usb_device_instance *device, usb_device_event_t event, int data) { +#if defined(CONFIG_USBD_HS) + int i; +#endif switch (event) { case DEVICE_RESET: case DEVICE_BUS_INACTIVE: @@ -942,6 +967,29 @@ static void usbtty_event_handler (struct usb_device_instance *device, break; case DEVICE_ADDRESS_ASSIGNED: +#if defined(CONFIG_USBD_HS) + /* + * is_usbd_high_speed routine needs to be defined by + * specific gadget driver + * It returns TRUE if device enumerates at High speed + * Retuns FALSE otherwise + */ + for (i = 0; i < NUM_ENDPOINTS; i++) { + if (((ep_descriptor_ptrs[i]->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK) + && is_usbd_high_speed()) { + + ep_descriptor_ptrs[i]->wMaxPacketSize = + CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE; + } + + endpoint_instance[i + 1].tx_packetSize = + ep_descriptor_ptrs[i]->wMaxPacketSize; + endpoint_instance[i + 1].rcv_packetSize = + ep_descriptor_ptrs[i]->wMaxPacketSize; + } +#endif usbtty_init_endpoints (); default: diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h index 6731c38..bd3bcbc 100644 --- a/drivers/serial/usbtty.h +++ b/drivers/serial/usbtty.h @@ -72,6 +72,10 @@ #define CONFIG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE #define CONFIG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE +#if defined(CONFIG_USBD_HS) +#define CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE UDC_BULK_HS_PACKET_SIZE +#endif + #define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS #define USBTTY_BCD_DEVICE 0x00 diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c index 4f2ebab..46ab3f6 100644 --- a/drivers/usb/gadget/core.c +++ b/drivers/usb/gadget/core.c @@ -212,7 +212,6 @@ struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_i return (device->device_descriptor); } - /** * usbd_device_configuration_descriptor * @device: which device diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c index 22499d3..aa8f916 100644 --- a/drivers/usb/gadget/ep0.c +++ b/drivers/usb/gadget/ep0.c @@ -338,12 +338,27 @@ static int ep0_get_descriptor (struct usb_device_instance *device, } break; case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: +#if defined(CONFIG_USBD_HS) { - /* If a USB device supports both a full speed and low speed operation - * we must send a Device_Qualifier descriptor here - */ - return -1; + struct usb_qualifier_descriptor *qualifier_descriptor = + device->qualifier_descriptor; + + if (!qualifier_descriptor) + return -1; + + /* copy descriptor for this device */ + copy_config(urb, qualifier_descriptor, + sizeof(struct usb_qualifier_descriptor), + max); + } + dbg_ep0(3, "copied qualifier descriptor, actual_length: 0x%x", + urb->actual_length); +#else + return -1; +#endif + break; + default: return -1; } diff --git a/include/usbdescriptors.h b/include/usbdescriptors.h index 2dec3b9..de1069f 100644 --- a/include/usbdescriptors.h +++ b/include/usbdescriptors.h @@ -241,6 +241,21 @@ struct usb_device_descriptor { u8 bNumConfigurations; } __attribute__ ((packed)); +#if defined(CONFIG_USBD_HS) +struct usb_qualifier_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize0; + u8 bNumConfigurations; + u8 breserved; +} __attribute__ ((packed)); +#endif + struct usb_string_descriptor { u8 bLength; u8 bDescriptorType; /* 0x03 */ diff --git a/include/usbdevice.h b/include/usbdevice.h index 9eb8849..7037efd 100644 --- a/include/usbdevice.h +++ b/include/usbdevice.h @@ -210,6 +210,10 @@ struct usb_bus_instance; #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 +#if defined(CONFIG_USBD_HS) +#define USB_DT_QUAL 0x06 +#endif + #define USB_DT_HID (USB_TYPE_CLASS | 0x01) #define USB_DT_REPORT (USB_TYPE_CLASS | 0x02) #define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) @@ -291,7 +295,11 @@ struct usb_bus_instance; * USB Spec Release number */ +#if defined(CONFIG_USBD_HS) +#define USB_BCD_VERSION 0x0200 +#else #define USB_BCD_VERSION 0x0110 +#endif /* @@ -567,6 +575,9 @@ struct usb_device_instance { /* generic */ char *name; struct usb_device_descriptor *device_descriptor; /* per device descriptor */ +#if defined(CONFIG_USBD_HS) + struct usb_qualifier_descriptor *qualifier_descriptor; +#endif void (*event) (struct usb_device_instance *device, usb_device_event_t event, int data); @@ -659,8 +670,17 @@ struct usb_class_report_descriptor *usbd_device_class_report_descriptor_index( s struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *, int, int, int, int, int); int usbd_device_endpoint_transfersize (struct usb_device_instance *, int, int, int, int, int); struct usb_string_descriptor *usbd_get_string (u8); -struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *, int); +struct usb_device_descriptor *usbd_device_device_descriptor(struct + usb_device_instance *, int); +#if defined(CONFIG_USBD_HS) +/* + * is_usbd_high_speed routine needs to be defined by specific gadget driver + * It returns TRUE if device enumerates at High speed + * Retuns FALSE otherwise + */ +int is_usbd_high_speed(void); +#endif int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint); void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad); void usbd_tx_complete (struct usb_endpoint_instance *endpoint);