From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Bhupesh Sharma <bhupesh.sharma@st.com>
Cc: linux-usb@vger.kernel.org, balbi@ti.com,
linux-media@vger.kernel.org, gregkh@linuxfoundation.org
Subject: Re: [PATCH 3/5] usb: gadget/uvc: Add super-speed support to UVC webcam gadget
Date: Fri, 08 Jun 2012 17:52:43 +0200 [thread overview]
Message-ID: <1524353.hc44KZEWdu@avalon> (raw)
In-Reply-To: <7da845d1b4ea9f8d716b7b218f03f9611e7ce97d.1338543124.git.bhupesh.sharma@st.com>
Hi Bhupesh,
Thanks for the patch.
As Felipe has already applied the patch to his public tree, I'll send
incremental cleanup patches. Here's my review nonetheless, with a question
which I'd like to know your opinion about to write the cleanup patches.
On Friday 01 June 2012 15:08:56 Bhupesh Sharma wrote:
> This patch adds super-speed support to UVC webcam gadget.
>
> Also in this patch:
> - We add the configurability to pass bInterval, bMaxBurst, mult
> factors for video streaming endpoint (ISOC IN) through module
> parameters.
>
> - We use config_ep_by_speed helper routine to configure video
> streaming endpoint.
>
> Signed-off-by: Bhupesh Sharma <bhupesh.sharma@st.com>
> ---
> drivers/usb/gadget/f_uvc.c | 241 +++++++++++++++++++++++++++++++++++-----
> drivers/usb/gadget/f_uvc.h | 8 +-
> drivers/usb/gadget/uvc.h | 4 +-
> drivers/usb/gadget/webcam.c | 29 +++++-
> 4 files changed, 247 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
> index dd7d7a9..2a8bf06 100644
> --- a/drivers/usb/gadget/f_uvc.c
> +++ b/drivers/usb/gadget/f_uvc.c
> @@ -29,6 +29,25 @@
>
> unsigned int uvc_gadget_trace_param;
>
> +/*-------------------------------------------------------------------------
> */ +
> +/* module parameters specific to the Video streaming endpoint */
> +static unsigned streaming_interval = 1;
> +module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
> +MODULE_PARM_DESC(streaming_interval, "1 - 16");
> +
> +static unsigned streaming_maxpacket = 1024;
unsigned int please.
> +module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
> +MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
> +
> +static unsigned streaming_mult;
> +module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
> +MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
I'd rather like to integrate this into the streaming_maxpacket parameter, and
compute the multiplier at runtime. This shouldn't be difficult for high speed,
the multiplier for max packet sizes between 1 and 1024 is 1, between 1025 and
2048 is 2 and between 2049 and 3072 is 3.
> +static unsigned streaming_maxburst;
> +module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
> +MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
Do you think maxburst could also be integrated into the streaming_maxpacket
parameter ? Put it another way, can we computer the multiplier and the burst
value from a single maximum number of bytes per service interval, or do they
have to be specified independently ? If using more than one burst, the
wMaxPacketSize value must be 1024 for HS. Only multiples of 1024 higher than
1024 can thus be achieved through different multipler/burst settings.
> +
> /*
> --------------------------------------------------------------------------
> * Function descriptors
> */
> @@ -84,7 +103,7 @@ static struct usb_interface_descriptor uvc_control_intf
> __initdata = { .iInterface = 0,
> };
>
> -static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
> +static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
> .bLength = USB_DT_ENDPOINT_SIZE,
> .bDescriptorType = USB_DT_ENDPOINT,
> .bEndpointAddress = USB_DIR_IN,
> @@ -124,7 +143,7 @@ static struct usb_interface_descriptor
> uvc_streaming_intf_alt1 __initdata = { .iInterface = 0,
> };
>
> -static struct usb_endpoint_descriptor uvc_streaming_ep = {
> +static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
> .bLength = USB_DT_ENDPOINT_SIZE,
> .bDescriptorType = USB_DT_ENDPOINT,
> .bEndpointAddress = USB_DIR_IN,
> @@ -133,15 +152,72 @@ static struct usb_endpoint_descriptor uvc_streaming_ep
> = { .bInterval = 1,
> };
>
> +static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
> + .bLength = USB_DT_ENDPOINT_SIZE,
> + .bDescriptorType = USB_DT_ENDPOINT,
> + .bEndpointAddress = USB_DIR_IN,
> + .bmAttributes = USB_ENDPOINT_XFER_ISOC,
> + .wMaxPacketSize = cpu_to_le16(1024),
> + .bInterval = 1,
wMaxPacketSize and bInterval are now initialized from module parameters, so
I'd leave it to zero and add a comment about it.
> +};
Please keep the indentation style consistent with the rest of the file.
> +
> +/* super speed support */
> +static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
> + .bLength = USB_DT_ENDPOINT_SIZE,
> + .bDescriptorType = USB_DT_ENDPOINT,
> +
> + .bEndpointAddress = USB_DIR_IN,
> + .bmAttributes = USB_ENDPOINT_XFER_INT,
> + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
> + .bInterval = 8,
> +};
The FS/HS/SS control endpoint descriptors are identical, there's no need to
define separate descriptors. You also don't set the SS endpoint number to the
FS endpoint number. As you don't call usb_ep_autoconfig() on the SS endpoint,
I doubt this will work in SS. Have you tested SS support ?
> +
> +static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
> + .bLength = sizeof uvc_ss_control_comp,
> + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
> +
> + /* the following 3 values can be tweaked if necessary */
> + /* .bMaxBurst = 0, */
> + /* .bmAttributes = 0, */
> + .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT),
> +};
> +
> +static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
> + .bLength = USB_DT_ENDPOINT_SIZE,
> + .bDescriptorType = USB_DT_ENDPOINT,
> +
> + .bEndpointAddress = USB_DIR_IN,
> + .bmAttributes = USB_ENDPOINT_XFER_ISOC,
> + .wMaxPacketSize = cpu_to_le16(1024),
> + .bInterval = 4,
> +};
> +
> +static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
> + .bLength = sizeof uvc_ss_streaming_comp,
The kernel coding style uses sizeof(uvc_ss_streaming_comp).
> + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
> +
> + /* the following 3 values can be tweaked if necessary */
> + .bMaxBurst = 0,
> + .bmAttributes = 0,
The two values are commented in uvc_ss_control_comp but not here.
> + .wBytesPerInterval = cpu_to_le16(1024),
> +};
> +
> static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
> (struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
> - (struct usb_descriptor_header *) &uvc_streaming_ep,
> + (struct usb_descriptor_header *) &uvc_fs_streaming_ep,
> NULL,
> };
>
> static const struct usb_descriptor_header * const uvc_hs_streaming[] = {
> (struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
> - (struct usb_descriptor_header *) &uvc_streaming_ep,
> + (struct usb_descriptor_header *) &uvc_hs_streaming_ep,
> + NULL,
> +};
> +
> +static const struct usb_descriptor_header * const uvc_ss_streaming[] = {
> + (struct usb_descriptor_header *) &uvc_streaming_intf_alt1,
> + (struct usb_descriptor_header *) &uvc_ss_streaming_ep,
> + (struct usb_descriptor_header *) &uvc_ss_streaming_comp,
> NULL,
> };
Those structures are missing __initdata
>
> @@ -217,6 +293,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned
> interface, unsigned alt) struct uvc_device *uvc = to_uvc(f);
> struct v4l2_event v4l2_event;
> struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
> + int ret;
>
> INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
>
> @@ -264,7 +341,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned
> interface, unsigned alt) return 0;
>
> if (uvc->video.ep) {
> - uvc->video.ep->desc = &uvc_streaming_ep;
> + ret = config_ep_by_speed(f->config->cdev->gadget,
> + &(uvc->func), uvc->video.ep);
> + if (ret)
> + return ret;
> usb_ep_enable(uvc->video.ep);
> }
>
> @@ -370,9 +450,11 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum
> usb_device_speed speed) {
> struct uvc_input_header_descriptor *uvc_streaming_header;
> struct uvc_header_descriptor *uvc_control_header;
> + const struct uvc_descriptor_header * const *uvc_control_desc;
> const struct uvc_descriptor_header * const *uvc_streaming_cls;
> const struct usb_descriptor_header * const *uvc_streaming_std;
> const struct usb_descriptor_header * const *src;
> + static struct usb_endpoint_descriptor *uvc_control_ep;
This doesn't need to be static.
> struct usb_descriptor_header **dst;
> struct usb_descriptor_header **hdr;
> unsigned int control_size;
> @@ -381,10 +463,29 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum
> usb_device_speed speed) unsigned int bytes;
> void *mem;
>
> - uvc_streaming_cls = (speed == USB_SPEED_FULL)
> - ? uvc->desc.fs_streaming : uvc->desc.hs_streaming;
> - uvc_streaming_std = (speed == USB_SPEED_FULL)
> - ? uvc_fs_streaming : uvc_hs_streaming;
> + switch (speed) {
> + case USB_SPEED_SUPER:
> + uvc_control_desc = uvc->desc.ss_control;
> + uvc_streaming_cls = uvc->desc.ss_streaming;
> + uvc_streaming_std = uvc_ss_streaming;
> + uvc_control_ep = &uvc_ss_control_ep;
> + break;
> +
> + case USB_SPEED_HIGH:
> + uvc_control_desc = uvc->desc.fs_control;
> + uvc_streaming_cls = uvc->desc.hs_streaming;
> + uvc_streaming_std = uvc_hs_streaming;
> + uvc_control_ep = &uvc_fs_control_ep;
> + break;
> +
> + case USB_SPEED_FULL:
> + default:
> + uvc_control_desc = uvc->desc.fs_control;
> + uvc_streaming_cls = uvc->desc.fs_streaming;
> + uvc_streaming_std = uvc_fs_streaming;
> + uvc_control_ep = &uvc_fs_control_ep;
> + break;
> + }
>
> /* Descriptors layout
> *
The comment should be updated with the uvc_ss_control_comp descriptor.
> @@ -402,16 +503,24 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum
> usb_device_speed speed) control_size = 0;
> streaming_size = 0;
> bytes = uvc_iad.bLength + uvc_control_intf.bLength
> - + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
> + + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
> + uvc_streaming_intf_alt0.bLength;
> - n_desc = 5;
>
> - for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src;
> ++src) { + if (speed == USB_SPEED_SUPER) {
> + bytes += uvc_ss_control_comp.bLength;
> + n_desc = 6;
> + } else {
> + n_desc = 5;
> + }
> +
> + for (src = (const struct usb_descriptor_header **)uvc_control_desc;
> + *src; ++src) {
> control_size += (*src)->bLength;
> bytes += (*src)->bLength;
> n_desc++;
> }
> - for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src;
> ++src) { + for (src = (const struct usb_descriptor_header
> **)uvc_streaming_cls; + *src; ++src) {
> streaming_size += (*src)->bLength;
> bytes += (*src)->bLength;
> n_desc++;
> @@ -435,12 +544,15 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum
> usb_device_speed speed)
>
> uvc_control_header = mem;
> UVC_COPY_DESCRIPTORS(mem, dst,
> - (const struct usb_descriptor_header**)uvc->desc.control);
> + (const struct usb_descriptor_header **)uvc_control_desc);
> uvc_control_header->wTotalLength = cpu_to_le16(control_size);
> uvc_control_header->bInCollection = 1;
> uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
>
> - UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
> + UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
> + if (speed == USB_SPEED_SUPER)
> + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
> +
> UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep);
> UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0);
>
> @@ -448,7 +560,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum
> usb_device_speed speed) UVC_COPY_DESCRIPTORS(mem, dst,
> (const struct usb_descriptor_header**)uvc_streaming_cls);
> uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
> - uvc_streaming_header->bEndpointAddress =
> uvc_streaming_ep.bEndpointAddress;
> + uvc_streaming_header->bEndpointAddress =
> + uvc_fs_streaming_ep.bEndpointAddress;
>
> UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
>
> @@ -484,6 +597,7 @@ uvc_function_unbind(struct usb_configuration *c, struct
> usb_function *f)
>
> kfree(f->descriptors);
> kfree(f->hs_descriptors);
> + kfree(f->ss_descriptors);
>
> kfree(uvc);
> }
> @@ -498,8 +612,26 @@ uvc_function_bind(struct usb_configuration *c, struct
> usb_function *f)
>
> INFO(cdev, "uvc_function_bind\n");
>
> + /* sanity check the streaming endpoint module parameters */
> + if (streaming_interval < 1)
> + streaming_interval = 1;
> + if (streaming_interval > 16)
> + streaming_interval = 16;
You can use clamp() instead (although one might argue that it's less
readable).
> + if (streaming_mult > 2)
> + streaming_mult = 2;
> + if (streaming_maxburst > 15)
> + streaming_maxburst = 15;
> +
> + /*
> + * fill in the FS video streaming specific descriptors from the
> + * module parameters
> + */
> + uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
> + 1023 : streaming_maxpacket;
> + uvc_fs_streaming_ep.bInterval = streaming_interval;
> +
> /* Allocate endpoints. */
> - ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
> + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
> if (!ep) {
> INFO(cdev, "Unable to allocate control EP\n");
> goto error;
> @@ -507,7 +639,7 @@ uvc_function_bind(struct usb_configuration *c, struct
> usb_function *f) uvc->control_ep = ep;
> ep->driver_data = uvc;
>
> - ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep);
> + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
This will select an endpoint suitable for FS, but there's no guarantee that
the endpoint will be suitable for FS and HS maximum packet sizes. I think
calling usb_ep_autoconf(_ss) on the endpoint for the highest supported speed
should fix the problem.
> if (!ep) {
> INFO(cdev, "Unable to allocate streaming EP\n");
> goto error;
> @@ -528,9 +660,52 @@ uvc_function_bind(struct usb_configuration *c, struct
> usb_function *f) uvc_streaming_intf_alt1.bInterfaceNumber = ret;
> uvc->streaming_intf = ret;
>
> - /* Copy descriptors. */
> + /* sanity check the streaming endpoint module parameters */
> + if (streaming_maxpacket > 1024)
> + streaming_maxpacket = 1024;
This should be moved above, with the other sanity checks.
> +
> + /* Copy descriptors for FS. */
> f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
> - f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
> +
> + /* support high speed hardware */
> + if (gadget_is_dualspeed(cdev->gadget)) {
> + /*
> + * Fill in the HS descriptors from the module parameters for the
> + * Video Streaming endpoint.
> + * NOTE: We assume that the user knows what they are doing and
> + * won't give parameters that their UDC doesn't support.
> + */
> + uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
> + uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
> + uvc_hs_streaming_ep.bInterval = streaming_interval;
> + uvc_hs_streaming_ep.bEndpointAddress =
> + uvc_fs_streaming_ep.bEndpointAddress;
> +
> + /* Copy descriptors. */
> + f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
> + }
> +
> + /* support super speed hardware */
> + if (gadget_is_superspeed(c->cdev->gadget)) {
> + /*
> + * Fill in the SS descriptors from the module parameters for the
> + * Video Streaming endpoint.
> + * NOTE: We assume that the user knows what they are doing and
> + * won't give parameters that their UDC doesn't support.
> + */
> + uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
> + uvc_ss_streaming_ep.bInterval = streaming_interval;
> + uvc_ss_streaming_comp.bmAttributes = streaming_mult;
> + uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
> + uvc_ss_streaming_comp.wBytesPerInterval =
> + streaming_maxpacket * (streaming_mult + 1) *
> + (streaming_maxburst + 1);
> + uvc_ss_streaming_ep.bEndpointAddress =
> + uvc_fs_streaming_ep.bEndpointAddress;
> +
> + /* Copy descriptors. */
> + f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
> + }
>
> /* Preallocate control endpoint request. */
> uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
> @@ -585,9 +760,11 @@ error:
> */
> int __init
> uvc_bind_config(struct usb_configuration *c,
> - const struct uvc_descriptor_header * const *control,
> + const struct uvc_descriptor_header * const *fs_control,
> + const struct uvc_descriptor_header * const *ss_control,
> const struct uvc_descriptor_header * const *fs_streaming,
> - const struct uvc_descriptor_header * const *hs_streaming)
> + const struct uvc_descriptor_header * const *hs_streaming,
> + const struct uvc_descriptor_header * const *ss_streaming)
> {
> struct uvc_device *uvc;
> int ret = 0;
> @@ -605,21 +782,31 @@ uvc_bind_config(struct usb_configuration *c,
> uvc->state = UVC_STATE_DISCONNECTED;
>
> /* Validate the descriptors. */
> - if (control == NULL || control[0] == NULL ||
> - control[0]->bDescriptorSubType != UVC_VC_HEADER)
> + if (fs_control == NULL || fs_control[0] == NULL ||
> + fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
> + goto error;
> +
> + if (ss_control == NULL || ss_control[0] == NULL ||
> + ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
> goto error;
>
> if (fs_streaming == NULL || fs_streaming[0] == NULL ||
> - fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
> + fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
> goto error;
Please keep the indentation consistent. This change is useless and just makes
the driver coding style inconsistent.
>
> if (hs_streaming == NULL || hs_streaming[0] == NULL ||
> - hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
> + hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
> + goto error;
> +
> + if (ss_streaming == NULL || ss_streaming[0] == NULL ||
> + ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
> goto error;
>
> - uvc->desc.control = control;
> + uvc->desc.fs_control = fs_control;
> + uvc->desc.ss_control = ss_control;
> uvc->desc.fs_streaming = fs_streaming;
> uvc->desc.hs_streaming = hs_streaming;
> + uvc->desc.ss_streaming = ss_streaming;
>
> /* maybe allocate device-global string IDs, and patch descriptors */
> if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
> diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h
> index abf8329..c3d258d 100644
> --- a/drivers/usb/gadget/f_uvc.h
> +++ b/drivers/usb/gadget/f_uvc.h
> @@ -17,9 +17,11 @@
> #include <linux/usb/video.h>
>
> extern int uvc_bind_config(struct usb_configuration *c,
> - const struct uvc_descriptor_header * const *control,
> - const struct uvc_descriptor_header * const *fs_streaming,
> - const struct uvc_descriptor_header * const *hs_streaming);
> + const struct uvc_descriptor_header * const *fs_control,
> + const struct uvc_descriptor_header * const *hs_control,
You're calling the parameter hs_control here and ss_control in the
implementation.
> + const struct uvc_descriptor_header * const *fs_streaming,
> + const struct uvc_descriptor_header * const *hs_streaming,
> + const struct uvc_descriptor_header * const *ss_streaming);
>
> #endif /* _F_UVC_H_ */
>
> diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h
> index bc78c60..d78ea25 100644
> --- a/drivers/usb/gadget/uvc.h
> +++ b/drivers/usb/gadget/uvc.h
> @@ -153,9 +153,11 @@ struct uvc_device
>
> /* Descriptors */
> struct {
> - const struct uvc_descriptor_header * const *control;
> + const struct uvc_descriptor_header * const *fs_control;
> + const struct uvc_descriptor_header * const *ss_control;
> const struct uvc_descriptor_header * const *fs_streaming;
> const struct uvc_descriptor_header * const *hs_streaming;
> + const struct uvc_descriptor_header * const *ss_streaming;
> } desc;
>
> unsigned int control_intf;
> diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
> index 668fe12..120e134 100644
> --- a/drivers/usb/gadget/webcam.c
> +++ b/drivers/usb/gadget/webcam.c
> @@ -272,7 +272,15 @@ static const struct uvc_color_matching_descriptor
> uvc_color_matching = { .bMatrixCoefficients = 4,
> };
>
> -static const struct uvc_descriptor_header * const uvc_control_cls[] = {
> +static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
> + (const struct uvc_descriptor_header *) &uvc_control_header,
> + (const struct uvc_descriptor_header *) &uvc_camera_terminal,
> + (const struct uvc_descriptor_header *) &uvc_processing,
> + (const struct uvc_descriptor_header *) &uvc_output_terminal,
> + NULL,
> +};
> +
> +static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = {
> (const struct uvc_descriptor_header *) &uvc_control_header,
> (const struct uvc_descriptor_header *) &uvc_camera_terminal,
> (const struct uvc_descriptor_header *) &uvc_processing,
uvc_fs_control_cls and uvc_ss_controls_cls are identical and const, we don't
need two copies.
> @@ -304,6 +312,18 @@ static const struct uvc_descriptor_header * const
> uvc_hs_streaming_cls[] = { NULL,
> };
>
> +static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] =
> { + (const struct uvc_descriptor_header *) &uvc_input_header,
> + (const struct uvc_descriptor_header *) &uvc_format_yuv,
> + (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
> + (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
> + (const struct uvc_descriptor_header *) &uvc_format_mjpg,
> + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
> + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
> + (const struct uvc_descriptor_header *) &uvc_color_matching,
> + NULL,
> +};
> +
> /*
> --------------------------------------------------------------------------
> * USB configuration
> */
> @@ -311,8 +331,9 @@ static const struct uvc_descriptor_header * const
> uvc_hs_streaming_cls[] = { static int __init
> webcam_config_bind(struct usb_configuration *c)
> {
> - return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
> - uvc_hs_streaming_cls);
> + return uvc_bind_config(c, uvc_fs_control_cls, uvc_ss_control_cls,
> + uvc_fs_streaming_cls, uvc_hs_streaming_cls,
> + uvc_ss_streaming_cls);
> }
>
> static struct usb_configuration webcam_config_driver = {
> @@ -373,7 +394,7 @@ static struct usb_composite_driver webcam_driver = {
> .name = "g_webcam",
> .dev = &webcam_device_descriptor,
> .strings = webcam_device_strings,
> - .max_speed = USB_SPEED_HIGH,
> + .max_speed = USB_SPEED_SUPER,
> .unbind = webcam_unbind,
> };
--
Regards,
Laurent Pinchart
next prev parent reply other threads:[~2012-06-08 15:52 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-01 9:37 [PATCH 0/5] UVC webcam gadget related changes Bhupesh Sharma
2012-06-01 9:38 ` [PATCH 1/5] usb: gadget/uvc: Fix string descriptor STALL issue when multiple uvc functions are added to a configuration Bhupesh Sharma
2012-06-01 9:38 ` [PATCH 2/5] usb: gadget/uvc: Use macro for interrupt endpoint status size instead of using a MAGIC number Bhupesh Sharma
2012-06-01 9:38 ` [PATCH 3/5] usb: gadget/uvc: Add super-speed support to UVC webcam gadget Bhupesh Sharma
2012-06-08 15:52 ` Laurent Pinchart [this message]
2012-06-09 5:39 ` Bhupesh SHARMA
2012-06-11 7:25 ` Laurent Pinchart
2012-06-15 10:24 ` Bhupesh SHARMA
2012-06-01 9:38 ` [PATCH 4/5] usb: gadget/uvc: Port UVC webcam gadget to use videobuf2 framework Bhupesh Sharma
2012-06-04 15:13 ` Felipe Balbi
2012-06-04 15:21 ` Bhupesh SHARMA
2012-06-04 15:28 ` Felipe Balbi
2012-06-04 15:37 ` Bhupesh SHARMA
2012-06-04 15:40 ` Felipe Balbi
2012-06-04 15:43 ` Bhupesh SHARMA
2012-06-04 16:40 ` Laurent Pinchart
2012-06-04 16:41 ` Felipe Balbi
2012-06-18 10:14 ` Bhupesh SHARMA
2012-06-18 22:50 ` Laurent Pinchart
2012-06-18 22:49 ` Laurent Pinchart
2012-07-03 15:42 ` Bhupesh SHARMA
2012-07-07 11:58 ` Laurent Pinchart
2012-07-25 18:18 ` Bhupesh SHARMA
2012-06-01 9:38 ` [PATCH 5/5] usb: gadget/uvc: Add support for 'USB_GADGET_DELAYED_STATUS' response for a set_intf(alt-set 1) command Bhupesh Sharma
2012-06-18 10:14 ` Bhupesh SHARMA
2012-06-19 21:49 ` Laurent Pinchart
2012-07-03 15:47 ` Bhupesh SHARMA
2012-07-07 13:06 ` Laurent Pinchart
2012-07-25 18:14 ` Bhupesh SHARMA
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1524353.hc44KZEWdu@avalon \
--to=laurent.pinchart@ideasonboard.com \
--cc=balbi@ti.com \
--cc=bhupesh.sharma@st.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).