Re: [PATCH 1/8] usb/gadget: uvc: move descriptors to their only user

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Laurent, hi Michael,

W dniu 28.11.2013 22:59, Michael Grzeschik pisze:
On Thu, Nov 28, 2013 at 10:53:03PM +0100, Laurent Pinchart wrote:
On Thursday 28 November 2013 08:43:35 Andrzej Pietrasiewicz wrote:
A bunch of descriptors is defined in webcam.c. They are used only
by f_uvc. Move them to their only user.

The reason why descriptors are located in webcam.c and not f_uvc.c is that I
wanted to separate the code in a generic part (f_uvc.c) and an application-
specific part (webcam.c). This allows instantiating a UVC function with
different parameters, depending on the application, with minimum changes to
the code. webcam.c is merely sample code that shows how to instantiate a UVC
function. With this patch the list of formats and controls become hardcoded in
the function driver.

How could we solve this problem with configfs ?

I would suggest that we move away from static descriptor description to
dynamic description from the userspace. We need a similar mechanism like
in functionfs to describe the supported endpoints and their formats. As
this is limited by the application above anyway. Would this also be
possible by configfs?



What FunctionFS does is that it accepts a stream of bytes and parses it;
it is expected that the said stream has particular structure understood
by FunctionFS.

Taking exactly the same approach with configfs seems counterintuitive
to how configfs is meant to be used: we should be creating things
explicitly (and step by step) instead of passing a (long) string of bytes.
[BTW passing the descriptors by creating directories and writing to files
in configfs is the main idea behind FunctionFS 2 I talked about during
LinuxCon in New Orleans.]

That said, it is not unconceivable to achieve the same effect using the
"proper" configfs way. However, this calls for some thought.

How many descriptors are there?
How many resolutions is the webcam gadget meant to support?
The descriptors so far in webcam.c form some hierarchy. Is the hierarchy
always the same? What can change? What are mandatory parts and what is
optional?

From what it looks like there has to be a way to specify some
configuration data (descriptors) and to specify associations between
them, e.g. there are some descriptions of, say, three resolutions and they
need to be associated with some higher-level descriptors, but for different
USB speeds the choice of resolutions is different. There are also some
format descriptors (yuv, MJPEG), there is some control header and so on.

With configfs we basically have three options for the user to create
things:

1) create a directory (its contents is predefined and unchangeable
at runtime)
2) write to a file (a file has to exist and be a member of some
directory like "1)" created  earlier)
3) create a symbolic link

Ad 1) This is used for example to create gadget's configurations,
to create gadget's functions and to create each gadget in the first
place
Ad 2) This is used for example to specify some parameters, like
MAC address or streaming_interval
Ad 3) This is used for assigning functions to configurations

What I can think of is that there is a predefined set of kinds
of descriptors we might want to create. It has to be this way,
since there has to be some configfs handling code specific to
each kind of directory/file/symbolic link we create.

For each descriptor the user creates a separate directory.
In the directory there are files which correspond to each
configurable member of the descriptor. What are configurable
members of possible descriptors?

Example

$ cd $CONFIGFS_ROOT/usb_gadget/g1/functions/uvc.1
(formats is a default group/directory so the user need not
create it)
$ cd formats
$ mkdir yuv
$ cd yuv
$ ls
guidFormat	bBitsPerPixel	bDefaultFrameIndex	bAspectRatioX
bAspectRatioY

(perhaps some more; I don't know what is constant and what can be set
by the user)

and there e.g.:
$ echo "Y,U,V,2,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71" \
guidFormat

(any better way to pass this kind of information?)

Then the user creates "streaming classes" (whatever they are):
(streaming_classes is a default group/directory so the user need not
create it)

$ cd $CONFIGFS_ROOT/usb_gadget/g1/functions/uvc.1
$ cd streaming_classes
$ mkdir fs hs ss
$ cd fs
$ ln -s $CONFIGFS_ROOT/usb_gadget/g1/functions/uvc.1/formats/yuv
$ ls
yuv -> ../../formats/yuv

(and similar follows for high and super speeds)

$ find -ls $CONFIGFS_ROOT/usb_gadget/g1/functions/uvc.1

./trace
./streaming_interval
./streaming_maxpacket
./streaming_maxburst
./formats
./formats/yuv
./formats/yuv/guidFormat
./formats/yuv/bBitsPerPixel
./formats/yuv/bDefaultFrameIndex
./formats/yuv/bAspectRatioX
./formats/yuv/bAspectRatioY
./streaming_classes
./streaming_classes/fs
./streaming_classes/fs/yuv -> ../../formats/yuv
./streaming_classes/hs
./streaming_classes/ss

and so on.

Does this look sane to you?

Some other questions and issues:

Can a uvc function be used more than once in a gadget?
That is, we have a device with TWO cameras and want to stream
video from both at the same time. If this is the case,
can the functions have completely different sets of descriptors?

Can functions have some default values for required descriptors?
That is, when the user does

$ mkdir $CONFIGFS_ROOT/usb_gadget/g1/functions/uvc.1

and then does all the usual gadget stuff (vendor, product id,
configuration(s), strings), can the function be used as-is
to successfully bind the gadget? What kinds of descriptors
are required in order for the uvc function to be at least "bindable"?
The consequence is that the bind function will have to be extended
to check if we have all the required descriptors to successfully bind.

Are there any dependent descriptors? That is, if some is specified,
some other has to accompany it or the function is incomplete?

To summarize, I suggest the way described above for passing the
descriptors. To implement it, I need help to tell me
"what is what of what" as far as uvc descriptors are concerned.

Thanks,

Andrzej


Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
  drivers/usb/gadget/f_uvc.c  |  271 ++++++++++++++++++++++++++++++++++++----
  drivers/usb/gadget/f_uvc.h  |    7 +-
  drivers/usb/gadget/webcam.c |  243 +--------------------------------------
  3 files changed, 252 insertions(+), 269 deletions(-)

diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c
index e2a1f50..ac0ac82 100644
--- a/drivers/usb/gadget/f_uvc.c
+++ b/drivers/usb/gadget/f_uvc.c
@@ -29,21 +29,255 @@
  #include "uvc.h"

  unsigned int uvc_gadget_trace_param;
+DECLARE_UVC_HEADER_DESCRIPTOR(1);
+
+static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
+	.bLength		= UVC_DT_HEADER_SIZE(1),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VC_HEADER,
+	.bcdUVC			= cpu_to_le16(0x0100),
+	.wTotalLength		= 0, /* dynamic */
+	.dwClockFrequency	= cpu_to_le32(48000000),
+	.bInCollection		= 0, /* dynamic */
+	.baInterfaceNr[0]	= 0, /* dynamic */
+};
+
+static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
+	.bLength		= UVC_DT_CAMERA_TERMINAL_SIZE(3),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VC_INPUT_TERMINAL,
+	.bTerminalID		= 1,
+	.wTerminalType		= cpu_to_le16(0x0201),
+	.bAssocTerminal		= 0,
+	.iTerminal		= 0,
+	.wObjectiveFocalLengthMin	= cpu_to_le16(0),
+	.wObjectiveFocalLengthMax	= cpu_to_le16(0),
+	.wOcularFocalLength		= cpu_to_le16(0),
+	.bControlSize		= 3,
+	.bmControls[0]		= 2,
+	.bmControls[1]		= 0,
+	.bmControls[2]		= 0,
+};
+
+static const struct uvc_processing_unit_descriptor uvc_processing = {
+	.bLength		= UVC_DT_PROCESSING_UNIT_SIZE(2),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VC_PROCESSING_UNIT,
+	.bUnitID		= 2,
+	.bSourceID		= 1,
+	.wMaxMultiplier		= cpu_to_le16(16*1024),
+	.bControlSize		= 2,
+	.bmControls[0]		= 1,
+	.bmControls[1]		= 0,
+	.iProcessing		= 0,
+};
+
+static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
+	.bLength		= UVC_DT_OUTPUT_TERMINAL_SIZE,
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VC_OUTPUT_TERMINAL,
+	.bTerminalID		= 3,
+	.wTerminalType		= cpu_to_le16(0x0101),
+	.bAssocTerminal		= 0,
+	.bSourceID		= 2,
+	.iTerminal		= 0,
+};
+
+DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
+
+static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
+	.bLength		= UVC_DT_INPUT_HEADER_SIZE(1, 2),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_INPUT_HEADER,
+	.bNumFormats		= 2,
+	.wTotalLength		= 0, /* dynamic */
+	.bEndpointAddress	= 0, /* dynamic */
+	.bmInfo			= 0,
+	.bTerminalLink		= 3,
+	.bStillCaptureMethod	= 0,
+	.bTriggerSupport	= 0,
+	.bTriggerUsage		= 0,
+	.bControlSize		= 1,
+	.bmaControls[0][0]	= 0,
+	.bmaControls[1][0]	= 4,
+};
+
+static const struct uvc_format_uncompressed uvc_format_yuv = {
+	.bLength		= UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_FORMAT_UNCOMPRESSED,
+	.bFormatIndex		= 1,
+	.bNumFrameDescriptors	= 2,
+	.guidFormat		=
+		{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
+		 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
+	.bBitsPerPixel		= 16,
+	.bDefaultFrameIndex	= 1,
+	.bAspectRatioX		= 0,
+	.bAspectRatioY		= 0,
+	.bmInterfaceFlags	= 0,
+	.bCopyProtect		= 0,
+};
+
+DECLARE_UVC_FRAME_UNCOMPRESSED(1);
+DECLARE_UVC_FRAME_UNCOMPRESSED(3);
+
+static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
+	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
+	.bFrameIndex		= 1,
+	.bmCapabilities		= 0,
+	.wWidth			= cpu_to_le16(640),
+	.wHeight		= cpu_to_le16(360),
+	.dwMinBitRate		= cpu_to_le32(18432000),
+	.dwMaxBitRate		= cpu_to_le32(55296000),
+	.dwMaxVideoFrameBufferSize	= cpu_to_le32(460800),
+	.dwDefaultFrameInterval	= cpu_to_le32(666666),
+	.bFrameIntervalType	= 3,
+	.dwFrameInterval[0]	= cpu_to_le32(666666),
+	.dwFrameInterval[1]	= cpu_to_le32(1000000),
+	.dwFrameInterval[2]	= cpu_to_le32(5000000),
+};
+
+static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
+	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
+	.bFrameIndex		= 2,
+	.bmCapabilities		= 0,
+	.wWidth			= cpu_to_le16(1280),
+	.wHeight		= cpu_to_le16(720),
+	.dwMinBitRate		= cpu_to_le32(29491200),
+	.dwMaxBitRate		= cpu_to_le32(29491200),
+	.dwMaxVideoFrameBufferSize	= cpu_to_le32(1843200),
+	.dwDefaultFrameInterval	= cpu_to_le32(5000000),
+	.bFrameIntervalType	= 1,
+	.dwFrameInterval[0]	= cpu_to_le32(5000000),
+};
+
+static const struct uvc_format_mjpeg uvc_format_mjpg = {
+	.bLength		= UVC_DT_FORMAT_MJPEG_SIZE,
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_FORMAT_MJPEG,
+	.bFormatIndex		= 2,
+	.bNumFrameDescriptors	= 2,
+	.bmFlags		= 0,
+	.bDefaultFrameIndex	= 1,
+	.bAspectRatioX		= 0,
+	.bAspectRatioY		= 0,
+	.bmInterfaceFlags	= 0,
+	.bCopyProtect		= 0,
+};

  /*-------------------------------------------------------------------------
*/ +DECLARE_UVC_FRAME_MJPEG(1);
+DECLARE_UVC_FRAME_MJPEG(3);
+
+static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
+	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(3),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
+	.bFrameIndex		= 1,
+	.bmCapabilities		= 0,
+	.wWidth			= cpu_to_le16(640),
+	.wHeight		= cpu_to_le16(360),
+	.dwMinBitRate		= cpu_to_le32(18432000),
+	.dwMaxBitRate		= cpu_to_le32(55296000),
+	.dwMaxVideoFrameBufferSize	= cpu_to_le32(460800),
+	.dwDefaultFrameInterval	= cpu_to_le32(666666),
+	.bFrameIntervalType	= 3,
+	.dwFrameInterval[0]	= cpu_to_le32(666666),
+	.dwFrameInterval[1]	= cpu_to_le32(1000000),
+	.dwFrameInterval[2]	= cpu_to_le32(5000000),
+};

  /* module parameters specific to the Video streaming endpoint */
  static unsigned int streaming_interval = 1;
  module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(streaming_interval, "1 - 16");
+static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
+	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(1),
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
+	.bFrameIndex		= 2,
+	.bmCapabilities		= 0,
+	.wWidth			= cpu_to_le16(1280),
+	.wHeight		= cpu_to_le16(720),
+	.dwMinBitRate		= cpu_to_le32(29491200),
+	.dwMaxBitRate		= cpu_to_le32(29491200),
+	.dwMaxVideoFrameBufferSize	= cpu_to_le32(1843200),
+	.dwDefaultFrameInterval	= cpu_to_le32(5000000),
+	.bFrameIntervalType	= 1,
+	.dwFrameInterval[0]	= cpu_to_le32(5000000),
+};

  static unsigned int streaming_maxpacket = 1024;
  module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
+static const struct uvc_color_matching_descriptor uvc_color_matching = {
+	.bLength		= UVC_DT_COLOR_MATCHING_SIZE,
+	.bDescriptorType	= USB_DT_CS_INTERFACE,
+	.bDescriptorSubType	= UVC_VS_COLORFORMAT,
+	.bColorPrimaries	= 1,
+	.bTransferCharacteristics	= 1,
+	.bMatrixCoefficients	= 4,
+};
+
+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,
+	(const struct uvc_descriptor_header *) &uvc_output_terminal,
+	NULL,
+};

  static unsigned int streaming_maxburst;
  module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
+static const struct uvc_descriptor_header * const uvc_fs_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,
+};
+
+static const struct uvc_descriptor_header * const uvc_hs_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,
+};
+
+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,
+};

  /*
--------------------------------------------------------------------------
* Function descriptors
@@ -744,12 +978,7 @@ error:
   * calling @uvc_cleanup() before module unload.
   */
  int __init
-uvc_bind_config(struct usb_configuration *c,
-		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)
+uvc_bind_config(struct usb_configuration *c)
  {
  	struct uvc_device *uvc;
  	int ret = 0;
@@ -767,31 +996,31 @@ uvc_bind_config(struct usb_configuration *c,
  	uvc->state = UVC_STATE_DISCONNECTED;

  	/* Validate the descriptors. */
-	if (fs_control == NULL || fs_control[0] == NULL ||
-	    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	if (uvc_fs_control_cls[0] == NULL ||
+	    uvc_fs_control_cls[0]->bDescriptorSubType != UVC_VC_HEADER)
  		goto error;

-	if (ss_control == NULL || ss_control[0] == NULL ||
-	    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+	if (uvc_ss_control_cls[0] == NULL ||
+	    uvc_ss_control_cls[0]->bDescriptorSubType != UVC_VC_HEADER)
  		goto error;

-	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
-	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	if (uvc_fs_streaming_cls[0] == NULL ||
+	    uvc_fs_streaming_cls[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
  		goto error;

-	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
-	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	if (uvc_hs_streaming_cls[0] == NULL ||
+	    uvc_hs_streaming_cls[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
  		goto error;

-	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
-	    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+	if (uvc_ss_streaming_cls[0] == NULL ||
+	    uvc_ss_streaming_cls[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
  		goto error;

-	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;
+	uvc->desc.fs_control = uvc_fs_control_cls;
+	uvc->desc.ss_control = uvc_ss_control_cls;
+	uvc->desc.fs_streaming = uvc_fs_streaming_cls;
+	uvc->desc.hs_streaming = uvc_hs_streaming_cls;
+	uvc->desc.ss_streaming = uvc_ss_streaming_cls;

  	/* String descriptors are global, we only need to allocate string IDs
  	 * for the first UVC function. UVC functions beyond the first (if any)
diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h
index ec52752..edfe772 100644
--- a/drivers/usb/gadget/f_uvc.h
+++ b/drivers/usb/gadget/f_uvc.h
@@ -16,12 +16,7 @@
  #include <linux/usb/composite.h>
  #include <linux/usb/video.h>

-int uvc_bind_config(struct usb_configuration *c,
-		    const struct uvc_descriptor_header * const *fs_control,
-		    const struct uvc_descriptor_header * const *hs_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);
+int uvc_bind_config(struct usb_configuration *c);

  #endif /* _F_UVC_H_ */

diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index 8cef1e6..df809e7 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -80,245 +80,6 @@ static struct usb_device_descriptor
webcam_device_descriptor = { .bNumConfigurations	= 0, /* dynamic */
  };

-DECLARE_UVC_HEADER_DESCRIPTOR(1);
-
-static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
-	.bLength		= UVC_DT_HEADER_SIZE(1),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VC_HEADER,
-	.bcdUVC			= cpu_to_le16(0x0100),
-	.wTotalLength		= 0, /* dynamic */
-	.dwClockFrequency	= cpu_to_le32(48000000),
-	.bInCollection		= 0, /* dynamic */
-	.baInterfaceNr[0]	= 0, /* dynamic */
-};
-
-static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
-	.bLength		= UVC_DT_CAMERA_TERMINAL_SIZE(3),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VC_INPUT_TERMINAL,
-	.bTerminalID		= 1,
-	.wTerminalType		= cpu_to_le16(0x0201),
-	.bAssocTerminal		= 0,
-	.iTerminal		= 0,
-	.wObjectiveFocalLengthMin	= cpu_to_le16(0),
-	.wObjectiveFocalLengthMax	= cpu_to_le16(0),
-	.wOcularFocalLength		= cpu_to_le16(0),
-	.bControlSize		= 3,
-	.bmControls[0]		= 2,
-	.bmControls[1]		= 0,
-	.bmControls[2]		= 0,
-};
-
-static const struct uvc_processing_unit_descriptor uvc_processing = {
-	.bLength		= UVC_DT_PROCESSING_UNIT_SIZE(2),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VC_PROCESSING_UNIT,
-	.bUnitID		= 2,
-	.bSourceID		= 1,
-	.wMaxMultiplier		= cpu_to_le16(16*1024),
-	.bControlSize		= 2,
-	.bmControls[0]		= 1,
-	.bmControls[1]		= 0,
-	.iProcessing		= 0,
-};
-
-static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
-	.bLength		= UVC_DT_OUTPUT_TERMINAL_SIZE,
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VC_OUTPUT_TERMINAL,
-	.bTerminalID		= 3,
-	.wTerminalType		= cpu_to_le16(0x0101),
-	.bAssocTerminal		= 0,
-	.bSourceID		= 2,
-	.iTerminal		= 0,
-};
-
-DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
-
-static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
-	.bLength		= UVC_DT_INPUT_HEADER_SIZE(1, 2),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_INPUT_HEADER,
-	.bNumFormats		= 2,
-	.wTotalLength		= 0, /* dynamic */
-	.bEndpointAddress	= 0, /* dynamic */
-	.bmInfo			= 0,
-	.bTerminalLink		= 3,
-	.bStillCaptureMethod	= 0,
-	.bTriggerSupport	= 0,
-	.bTriggerUsage		= 0,
-	.bControlSize		= 1,
-	.bmaControls[0][0]	= 0,
-	.bmaControls[1][0]	= 4,
-};
-
-static const struct uvc_format_uncompressed uvc_format_yuv = {
-	.bLength		= UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_FORMAT_UNCOMPRESSED,
-	.bFormatIndex		= 1,
-	.bNumFrameDescriptors	= 2,
-	.guidFormat		=
-		{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
-		 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
-	.bBitsPerPixel		= 16,
-	.bDefaultFrameIndex	= 1,
-	.bAspectRatioX		= 0,
-	.bAspectRatioY		= 0,
-	.bmInterfaceFlags	= 0,
-	.bCopyProtect		= 0,
-};
-
-DECLARE_UVC_FRAME_UNCOMPRESSED(1);
-DECLARE_UVC_FRAME_UNCOMPRESSED(3);
-
-static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
-	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
-	.bFrameIndex		= 1,
-	.bmCapabilities		= 0,
-	.wWidth			= cpu_to_le16(640),
-	.wHeight		= cpu_to_le16(360),
-	.dwMinBitRate		= cpu_to_le32(18432000),
-	.dwMaxBitRate		= cpu_to_le32(55296000),
-	.dwMaxVideoFrameBufferSize	= cpu_to_le32(460800),
-	.dwDefaultFrameInterval	= cpu_to_le32(666666),
-	.bFrameIntervalType	= 3,
-	.dwFrameInterval[0]	= cpu_to_le32(666666),
-	.dwFrameInterval[1]	= cpu_to_le32(1000000),
-	.dwFrameInterval[2]	= cpu_to_le32(5000000),
-};
-
-static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
-	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
-	.bFrameIndex		= 2,
-	.bmCapabilities		= 0,
-	.wWidth			= cpu_to_le16(1280),
-	.wHeight		= cpu_to_le16(720),
-	.dwMinBitRate		= cpu_to_le32(29491200),
-	.dwMaxBitRate		= cpu_to_le32(29491200),
-	.dwMaxVideoFrameBufferSize	= cpu_to_le32(1843200),
-	.dwDefaultFrameInterval	= cpu_to_le32(5000000),
-	.bFrameIntervalType	= 1,
-	.dwFrameInterval[0]	= cpu_to_le32(5000000),
-};
-
-static const struct uvc_format_mjpeg uvc_format_mjpg = {
-	.bLength		= UVC_DT_FORMAT_MJPEG_SIZE,
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_FORMAT_MJPEG,
-	.bFormatIndex		= 2,
-	.bNumFrameDescriptors	= 2,
-	.bmFlags		= 0,
-	.bDefaultFrameIndex	= 1,
-	.bAspectRatioX		= 0,
-	.bAspectRatioY		= 0,
-	.bmInterfaceFlags	= 0,
-	.bCopyProtect		= 0,
-};
-
-DECLARE_UVC_FRAME_MJPEG(1);
-DECLARE_UVC_FRAME_MJPEG(3);
-
-static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
-	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(3),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
-	.bFrameIndex		= 1,
-	.bmCapabilities		= 0,
-	.wWidth			= cpu_to_le16(640),
-	.wHeight		= cpu_to_le16(360),
-	.dwMinBitRate		= cpu_to_le32(18432000),
-	.dwMaxBitRate		= cpu_to_le32(55296000),
-	.dwMaxVideoFrameBufferSize	= cpu_to_le32(460800),
-	.dwDefaultFrameInterval	= cpu_to_le32(666666),
-	.bFrameIntervalType	= 3,
-	.dwFrameInterval[0]	= cpu_to_le32(666666),
-	.dwFrameInterval[1]	= cpu_to_le32(1000000),
-	.dwFrameInterval[2]	= cpu_to_le32(5000000),
-};
-
-static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
-	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(1),
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
-	.bFrameIndex		= 2,
-	.bmCapabilities		= 0,
-	.wWidth			= cpu_to_le16(1280),
-	.wHeight		= cpu_to_le16(720),
-	.dwMinBitRate		= cpu_to_le32(29491200),
-	.dwMaxBitRate		= cpu_to_le32(29491200),
-	.dwMaxVideoFrameBufferSize	= cpu_to_le32(1843200),
-	.dwDefaultFrameInterval	= cpu_to_le32(5000000),
-	.bFrameIntervalType	= 1,
-	.dwFrameInterval[0]	= cpu_to_le32(5000000),
-};
-
-static const struct uvc_color_matching_descriptor uvc_color_matching = {
-	.bLength		= UVC_DT_COLOR_MATCHING_SIZE,
-	.bDescriptorType	= USB_DT_CS_INTERFACE,
-	.bDescriptorSubType	= UVC_VS_COLORFORMAT,
-	.bColorPrimaries	= 1,
-	.bTransferCharacteristics	= 1,
-	.bMatrixCoefficients	= 4,
-};
-
-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,
-	(const struct uvc_descriptor_header *) &uvc_output_terminal,
-	NULL,
-};
-
-static const struct uvc_descriptor_header * const uvc_fs_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,
-};
-
-static const struct uvc_descriptor_header * const uvc_hs_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,
-};
-
-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
   */
@@ -326,9 +87,7 @@ static const struct uvc_descriptor_header * const
uvc_ss_streaming_cls[] = { static int __init
  webcam_config_bind(struct usb_configuration *c)
  {
-	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);
+	return uvc_bind_config(c);
  }

  static struct usb_configuration webcam_config_driver = {
--
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux