Enable high speed support for USB device framework and usbtty
authorVipin KUMAR <vipin.kumar@st.com>
Mon, 26 Mar 2012 10:08:06 +0000 (15:38 +0530)
committerMarek Vasut <marek.vasut@gmail.com>
Wed, 28 Mar 2012 14:31:08 +0000 (16:31 +0200)
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 <vipin.kumar@st.com>
Signed-off-by: Amit Virdi <amit.virdi@st.com>
README
drivers/serial/usbtty.c
drivers/serial/usbtty.h
drivers/usb/gadget/core.c
drivers/usb/gadget/ep0.c
include/usbdescriptors.h
include/usbdevice.h

diff --git a/README b/README
index b69a3b6f6edc96c58491249d0f6665d07ea31987..0ab689257eba10011bd9a5f6fbfdd5e29641d7ca 100644 (file)
--- 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.
index a263b2c1fc593ea015f685c6f3ace3806e6f01c8..e47cb9a9e724bbb560a3b0f42f0c844dd0bcb867 100644 (file)
@@ -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:
index 60347d7884dff2232a6e75e493af7b5b7f04095a..eb670dad9322e41b395a974d83cef41de75e230a 100644 (file)
 #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
index 4f2ebab9e2ab9afefb5326756c9e6e8ea16416a3..46ab3f67f880015a4ba554f8ba446cfe009bb2b9 100644 (file)
@@ -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
index 22499d36bfe20213cbe063065a37c8bcd7260675..aa8f91600d70bf7252e8aae21873923065ccba9f 100644 (file)
@@ -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;
        }
index 2dec3b93d65438cfc5c16ec4a1f04ee62a469ac7..de1069f0ea9a6dcd0622edbc955208c1c4d669c0 100644 (file)
@@ -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 */
index 41716364b314dcb040a2aa3a003d41718c5f9c8b..3edaf8bcc268a66212cb56a3dac8d67b4a9aae4b 100644 (file)
@@ -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
 
 
 /*
@@ -565,6 +573,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);
 
@@ -657,8 +668,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);