@@ -589,6 +589,9 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
struct usb_string *us;
+ struct uvc_processing_unit_descriptor *pd;
+ struct uvc_descriptor_header **ctl_cls;
+ struct uvc_header_descriptor *desc;
unsigned int max_packet_mult;
unsigned int max_packet_size;
struct usb_ep *ep;
@@ -598,6 +601,15 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvcg_info(f, "%s()\n", __func__);
opts = fi_to_f_uvc_opts(f->fi);
+
+ /* Handle the length of Processing Unit for different UVC versions */
+ ctl_cls = opts->uvc_ss_control_cls;
+ desc = (struct uvc_header_descriptor *)ctl_cls[0];
+ if (desc) {
+ pd = &opts->uvc_processing;
+ pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(desc->bcdUVC, 3);
+ }
+
/* Sanity check the streaming endpoint module parameters.
*/
opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U);
@@ -814,15 +826,16 @@ static struct usb_function_instance *uvc_alloc_inst(void)
cd->bmControls[2] = 0;
pd = &opts->uvc_processing;
- pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(2);
+ pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(UVC_VERSION_DEFAULT, 3);
pd->bDescriptorType = USB_DT_CS_INTERFACE;
pd->bDescriptorSubType = UVC_VC_PROCESSING_UNIT;
pd->bUnitID = 2;
pd->bSourceID = 1;
pd->wMaxMultiplier = cpu_to_le16(16*1024);
- pd->bControlSize = 2;
+ pd->bControlSize = 3;
pd->bmControls[0] = 1;
pd->bmControls[1] = 0;
+ pd->bmControls[2] = 0;
pd->iProcessing = 0;
pd->bmVideoStandards = 0;
@@ -231,7 +231,7 @@ static struct config_item *uvcg_control_header_make(struct config_group *group,
h->desc.bLength = UVC_DT_HEADER_SIZE(1);
h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
h->desc.bDescriptorSubType = UVC_VC_HEADER;
- h->desc.bcdUVC = cpu_to_le16(0x0110);
+ h->desc.bcdUVC = cpu_to_le16(UVC_VERSION_DEFAULT);
h->desc.dwClockFrequency = cpu_to_le32(48000000);
config_item_init_type_name(&h->item, name, &uvcg_control_header_type);
@@ -90,7 +90,7 @@ 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(0x0110),
+ .bcdUVC = cpu_to_le16(UVC_VERSION_DEFAULT),
.wTotalLength = 0, /* dynamic */
.dwClockFrequency = cpu_to_le32(48000000),
.bInCollection = 0, /* dynamic */
@@ -115,15 +115,16 @@ static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
};
static const struct uvc_processing_unit_descriptor uvc_processing = {
- .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2),
+ .bLength = UVC_DT_PROCESSING_UNIT_SIZE(UVC_VERSION_DEFAULT, 3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_PROCESSING_UNIT,
.bUnitID = 2,
.bSourceID = 1,
.wMaxMultiplier = cpu_to_le16(16*1024),
- .bControlSize = 2,
+ .bControlSize = 3,
.bmControls[0] = 1,
.bmControls[1] = 0,
+ .bmControls[2] = 0,
.iProcessing = 0,
.bmVideoStandards = 0,
};
@@ -21,6 +21,12 @@
* UVC constants
*/
+/* UVC Protocol Version */
+#define UVC_VERSION_1_0 0x0100
+#define UVC_VERSION_1_1 0x0110
+#define UVC_VERSION_1_5 0x0150
+#define UVC_VERSION_DEFAULT UVC_VERSION_1_1
+
/* A.2. Video Interface Subclass Codes */
#define UVC_SC_UNDEFINED 0x00
#define UVC_SC_VIDEOCONTROL 0x01
@@ -104,6 +110,9 @@
#define UVC_CT_ROLL_ABSOLUTE_CONTROL 0x0f
#define UVC_CT_ROLL_RELATIVE_CONTROL 0x10
#define UVC_CT_PRIVACY_CONTROL 0x11
+#define UVC_CT_FOCUS_SIMPLE_CONTROL 0x12
+#define UVC_CT_WINDOW_CONTROL 0x13
+#define UVC_CT_REGION_OF_INTEREST_CONTROL 0x14
/* A.9.5. Processing Unit Control Selectors */
#define UVC_PU_CONTROL_UNDEFINED 0x00
@@ -125,6 +134,7 @@
#define UVC_PU_HUE_AUTO_CONTROL 0x10
#define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
#define UVC_PU_ANALOG_LOCK_STATUS_CONTROL 0x12
+#define UVC_PU_CONTRAST_AUTO_CONTROL 0x13
/* A.9.7. VideoStreaming Interface Control Selectors */
#define UVC_VS_CONTROL_UNDEFINED 0x00
@@ -300,12 +310,14 @@ struct uvc_processing_unit_descriptor {
__u8 bSourceID;
__le16 wMaxMultiplier;
__u8 bControlSize;
- __u8 bmControls[2];
+ __u8 bmControls[3];
__u8 iProcessing;
+ /* UVC 1.1 adds the following member */
__u8 bmVideoStandards;
} __attribute__((__packed__));
-#define UVC_DT_PROCESSING_UNIT_SIZE(n) (10+(n))
+#define UVC_DT_PROCESSING_UNIT_SIZE(v, n) ((__u8) \
+ (((v) == UVC_VERSION_1_0) ? (9+(n)) : ((10+(n)))))
/* 3.7.2.6. Extension Unit Descriptor */
struct uvc_extension_unit_descriptor {
@@ -447,13 +459,24 @@ struct uvc_streaming_control {
__u16 wDelay;
__u32 dwMaxVideoFrameSize;
__u32 dwMaxPayloadTransferSize;
+ /* UVC 1.1 adds the following members */
__u32 dwClockFrequency;
__u8 bmFramingInfo;
__u8 bPreferedVersion;
__u8 bMinVersion;
__u8 bMaxVersion;
+ /* UVC 1.5 adds the following members */
+ __u8 bUsage;
+ __u8 bBitDepthLuma;
+ __u8 bmSettings;
+ __u8 bMaxNumberOfRefFramesPlus1;
+ __u16 bmRateControlModes;
+ __u16 bmLayoutPerStream[4];
} __attribute__((__packed__));
+#define UVC_STREAMING_CONTROL_SIZE(v) \
+ (((v) == UVC_VERSION_1_0) ? 26 : (((v) == UVC_VERSION_1_1) ? 34 : 48))
+
/* Uncompressed Payload - 3.1.1. Uncompressed Video Format Descriptor */
struct uvc_format_uncompressed {
__u8 bLength;