[U-Boot] [PATCH] Enable high speed support for USB device framework and usbtty

Amit Virdi
2012-02-27T09:35:53Z

From: Vipin KUMAR <vipin.kumar@st.com>

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 | 8 +++++++
drivers/serial/usbtty.c | 50 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/serial/usbtty.h | 4 +++
drivers/usb/gadget/core.c | 14 ++++++++++++
drivers/usb/gadget/ep0.c | 24 ++++++++++++++++++---
include/usbdescriptors.h | 15 +++++++++++++
include/usbdevice.h | 24 ++++++++++++++++++++-
7 files changed, 133 insertions(+), 6 deletions(-)

diff --git a/README b/README
index eba6378..d54bb68 100644
--- a/README
+++ b/README
@@ -1165,6 +1165,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..0374c7d 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 = 1; i <= NUM_ENDPOINTS; i++) {
+ if (((ep_descriptor_ptrs[i - 1]->bmAttributes &
+ USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK)
+ && is_usbd_high_speed()) {
+
+ ep_descriptor_ptrs[i - 1]->wMaxPacketSize =
+ CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE;
+ }
+
+ endpoint_instance[i].tx_packetSize =
+ ep_descriptor_ptrs[i - 1]->wMaxPacketSize;
+ endpoint_instance[i].rcv_packetSize =
+ ep_descriptor_ptrs[i - 1]->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..b2212b4 100644
--- a/drivers/usb/gadget/core.c
+++ b/drivers/usb/gadget/core.c
@@ -212,6 +212,20 @@ struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_i
return (device->device_descriptor);
}

+#if defined(CONFIG_USBD_HS)
+/**
+ * usbd_device_qualifier_descriptor
+ * @device: which device
+ * @port: which port
+ *
+ * Return the specified qualifier descriptor for the specified device.
+ */
+struct usb_qualifier_descriptor *usbd_device_qualifier_descriptor(
+ struct usb_device_instance *device, int port)
+{
+ return device->qualifier_descriptor;
+}
+#endif

/**
* usbd_device_configuration_descriptor
diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c
index 22499d3..ba8f906 100644
--- a/drivers/usb/gadget/ep0.c
+++ b/drivers/usb/gadget/ep0.c
@@ -338,12 +338,28 @@ 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;
+
+ qualifier_descriptor = usbd_device_qualifier_descriptor
+ (device, port);
+ 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..e3eb748 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,19 @@ 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)
+struct usb_qualifier_descriptor *usbd_device_qualifier_descriptor(
+ struct usb_device_instance *, int);
+/*
+ * 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);
--
1.7.2.2