diff mbox

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

Message ID 1330335353-32164-1-git-send-email-amit.virdi@st.com
State Accepted
Delegated to: Marek Vasut
Headers show

Commit Message

Amit Virdi Feb. 27, 2012, 9:35 a.m. UTC
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(-)

Comments

Marek Vasut Feb. 27, 2012, 11:41 a.m. UTC | #1
> 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++) {

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);
Amit Virdi Feb. 29, 2012, 10:03 a.m. UTC | #2
Hello Marek,

+#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.
>

Ok.

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

Well... usbd_device_qualifier_descriptor can't be static as the function 
is called from another file (ep0.c). However, since it is used only for 
EP0, it can be omitted for the time being keeping in mind we might need 
to define it in future (if the need arises). What do you think?

> Otherwise seems ok
>

Thanks
Amit Virdi
Marek Vasut Feb. 29, 2012, 9:24 p.m. UTC | #3
> Hello Marek,
> 
> +#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.
> 
> Ok.
> 
> >> +			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?
> 
> Well... usbd_device_qualifier_descriptor can't be static as the function
> is called from another file (ep0.c). However, since it is used only for
> EP0, it can be omitted for the time being keeping in mind we might need
> to define it in future (if the need arises). What do you think?

What do you mean. If this is called from ep0.c, it has to be exported and that's 
how it is. On the other hand, if ep0.c already has access to the "device", it 
can directly access the device_descriptor field, which is I believe expressive 
enough.

Thanks for your good work so far, keep it up!

M
> 
> > Otherwise seems ok
> 
> Thanks
> Amit Virdi
Amit Virdi March 2, 2012, 5:54 a.m. UTC | #4
Hi Marek,

>>>> +#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?
>>
>> Well... usbd_device_qualifier_descriptor can't be static as the function
>> is called from another file (ep0.c). However, since it is used only for
>> EP0, it can be omitted for the time being keeping in mind we might need
>> to define it in future (if the need arises). What do you think?
>
> What do you mean. If this is called from ep0.c, it has to be exported and that's
> how it is. On the other hand, if ep0.c already has access to the "device", it
> can directly access the device_descriptor field, which is I believe expressive
> enough.
>

Yes, ep0.c has direct access to the "device" field. I'll omit the 
usbd_device_qualifier_descriptor function in V2.

Thanks
Amit Virdi
Marek Vasut March 2, 2012, 10:41 a.m. UTC | #5
> Hi Marek,
> 
> >>>> +#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?
> >> 
> >> Well... usbd_device_qualifier_descriptor can't be static as the function
> >> is called from another file (ep0.c). However, since it is used only for
> >> EP0, it can be omitted for the time being keeping in mind we might need
> >> to define it in future (if the need arises). What do you think?
> > 
> > What do you mean. If this is called from ep0.c, it has to be exported and
> > that's how it is. On the other hand, if ep0.c already has access to the
> > "device", it can directly access the device_descriptor field, which is I
> > believe expressive enough.
> 
> Yes, ep0.c has direct access to the "device" field. I'll omit the
> usbd_device_qualifier_descriptor function in V2.
> 

Thank you :-)

M
Marek Vasut March 18, 2012, 10:57 p.m. UTC | #6
Hi,

> > 
> > Yes, ep0.c has direct access to the "device" field. I'll omit the
> > usbd_device_qualifier_descriptor function in V2.
> 

How's V2 going?

Best regards,
Marek Vasut
Shiraz Hashim March 19, 2012, 9:31 a.m. UTC | #7
Hi Marek,

On Mon, Mar 19, 2012 at 06:57:29AM +0800, Marek Vasut wrote:
> Hi,
> 
> > > 
> > > Yes, ep0.c has direct access to the "device" field. I'll omit the
> > > usbd_device_qualifier_descriptor function in V2.
> > 
> 
> How's V2 going?

Unfortunately Amit is not well and he is taking rest. He would resume
on this from next week.

--
regards
Shiraz
Marek Vasut March 19, 2012, 10:28 a.m. UTC | #8
Dear Shiraz Hashim,

> Hi Marek,
> 
> On Mon, Mar 19, 2012 at 06:57:29AM +0800, Marek Vasut wrote:
> > Hi,
> > 
> > > > Yes, ep0.c has direct access to the "device" field. I'll omit the
> > > > usbd_device_qualifier_descriptor function in V2.
> > 
> > How's V2 going?
> 
> Unfortunately Amit is not well and he is taking rest. He would resume
> on this from next week.
> 

Please forward him that I wish him getting better ASAP.

Best regards,
Marek Vasut
Amit Virdi March 26, 2012, 4:46 a.m. UTC | #9
On 3/19/2012 3:58 PM, Marek Vasut wrote:
> Dear Shiraz Hashim,
>
>> Hi Marek,
>>
>> On Mon, Mar 19, 2012 at 06:57:29AM +0800, Marek Vasut wrote:
>>> Hi,
>>>
>>>>> Yes, ep0.c has direct access to the "device" field. I'll omit the
>>>>> usbd_device_qualifier_descriptor function in V2.
>>>
>>> How's V2 going?
>>
>> Unfortunately Amit is not well and he is taking rest. He would resume
>> on this from next week.
>>
>
> Please forward him that I wish him getting better ASAP.
>

Thanks for your wishes Marek, I'm well now and back to office!
I shall finish sending V2 of all the patches I have sent till date, 
within a couple of days.

Best Regards
Amit Virdi
Marek Vasut March 26, 2012, 10:41 a.m. UTC | #10
Dear Amit Virdi,

> On 3/19/2012 3:58 PM, Marek Vasut wrote:
> > Dear Shiraz Hashim,
> > 
> >> Hi Marek,
> >> 
> >> On Mon, Mar 19, 2012 at 06:57:29AM +0800, Marek Vasut wrote:
> >>> Hi,
> >>> 
> >>>>> Yes, ep0.c has direct access to the "device" field. I'll omit the
> >>>>> usbd_device_qualifier_descriptor function in V2.
> >>> 
> >>> How's V2 going?
> >> 
> >> Unfortunately Amit is not well and he is taking rest. He would resume
> >> on this from next week.
> > 
> > Please forward him that I wish him getting better ASAP.
> 
> Thanks for your wishes Marek, I'm well now and back to office!
> I shall finish sending V2 of all the patches I have sent till date,
> within a couple of days.
> 

Good to see you back. Thanks for your efforts ;-)

Best regards,
Marek Vasut
diff mbox

Patch

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