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

Marek Vasut marek.vasut at gmail.com
Mon Feb 27 12:41:06 CET 2012


> From: Vipin KUMAR <vipin.kumar at 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 at st.com>
> Signed-off-by: Amit Virdi <amit.virdi at 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++) {

Start with i = 0 and end with i < NUM_ENDPOINTS to avoid these i-1 below. Then 
fix those [i] with [i+1], there's less of those.

> +			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)

Make this static, but do you really need this function at all?

Otherwise seems ok

> +{
> +	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);


More information about the U-Boot mailing list