summary refs log tree commit diff
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c255
-rw-r--r--drivers/media/video/uvc/uvc_driver.c570
-rw-r--r--drivers/media/video/uvc/uvc_isight.c7
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c277
-rw-r--r--drivers/media/video/uvc/uvc_video.c434
-rw-r--r--drivers/media/video/uvc/uvcvideo.h278
6 files changed, 926 insertions, 895 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 36a6ba92df27..c3225a561748 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -34,7 +34,7 @@
 static struct uvc_control_info uvc_ctrls[] = {
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_BRIGHTNESS_CONTROL,
+		.selector	= UVC_PU_BRIGHTNESS_CONTROL,
 		.index		= 0,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -42,7 +42,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_CONTRAST_CONTROL,
+		.selector	= UVC_PU_CONTRAST_CONTROL,
 		.index		= 1,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -50,7 +50,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_HUE_CONTROL,
+		.selector	= UVC_PU_HUE_CONTROL,
 		.index		= 2,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -58,7 +58,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_SATURATION_CONTROL,
+		.selector	= UVC_PU_SATURATION_CONTROL,
 		.index		= 3,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -66,7 +66,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_SHARPNESS_CONTROL,
+		.selector	= UVC_PU_SHARPNESS_CONTROL,
 		.index		= 4,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -74,7 +74,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_GAMMA_CONTROL,
+		.selector	= UVC_PU_GAMMA_CONTROL,
 		.index		= 5,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -82,7 +82,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
 		.index		= 6,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -90,7 +90,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_COMPONENT_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
 		.index		= 7,
 		.size		= 4,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -98,7 +98,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_BACKLIGHT_COMPENSATION_CONTROL,
+		.selector	= UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
 		.index		= 8,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -106,7 +106,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_GAIN_CONTROL,
+		.selector	= UVC_PU_GAIN_CONTROL,
 		.index		= 9,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -114,7 +114,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_POWER_LINE_FREQUENCY_CONTROL,
+		.selector	= UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
 		.index		= 10,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -122,7 +122,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_HUE_AUTO_CONTROL,
+		.selector	= UVC_PU_HUE_AUTO_CONTROL,
 		.index		= 11,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -130,7 +130,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
 		.index		= 12,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -138,7 +138,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
 		.index		= 13,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -146,7 +146,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_DIGITAL_MULTIPLIER_CONTROL,
+		.selector	= UVC_PU_DIGITAL_MULTIPLIER_CONTROL,
 		.index		= 14,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -154,7 +154,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
+		.selector	= UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
 		.index		= 15,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -162,21 +162,21 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_ANALOG_VIDEO_STANDARD_CONTROL,
+		.selector	= UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL,
 		.index		= 16,
 		.size		= 1,
 		.flags		= UVC_CONTROL_GET_CUR,
 	},
 	{
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_ANALOG_LOCK_STATUS_CONTROL,
+		.selector	= UVC_PU_ANALOG_LOCK_STATUS_CONTROL,
 		.index		= 17,
 		.size		= 1,
 		.flags		= UVC_CONTROL_GET_CUR,
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_SCANNING_MODE_CONTROL,
+		.selector	= UVC_CT_SCANNING_MODE_CONTROL,
 		.index		= 0,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -184,7 +184,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_AE_MODE_CONTROL,
+		.selector	= UVC_CT_AE_MODE_CONTROL,
 		.index		= 1,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -193,7 +193,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_AE_PRIORITY_CONTROL,
+		.selector	= UVC_CT_AE_PRIORITY_CONTROL,
 		.index		= 2,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -201,7 +201,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
 		.index		= 3,
 		.size		= 4,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -209,7 +209,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_EXPOSURE_TIME_RELATIVE_CONTROL,
+		.selector	= UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL,
 		.index		= 4,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -217,7 +217,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_FOCUS_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_FOCUS_ABSOLUTE_CONTROL,
 		.index		= 5,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -225,7 +225,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_FOCUS_RELATIVE_CONTROL,
+		.selector	= UVC_CT_FOCUS_RELATIVE_CONTROL,
 		.index		= 6,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -233,7 +233,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_IRIS_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_IRIS_ABSOLUTE_CONTROL,
 		.index		= 7,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -241,7 +241,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_IRIS_RELATIVE_CONTROL,
+		.selector	= UVC_CT_IRIS_RELATIVE_CONTROL,
 		.index		= 8,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -249,7 +249,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_ZOOM_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_ZOOM_ABSOLUTE_CONTROL,
 		.index		= 9,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -257,7 +257,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_ZOOM_RELATIVE_CONTROL,
+		.selector	= UVC_CT_ZOOM_RELATIVE_CONTROL,
 		.index		= 10,
 		.size		= 3,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -265,7 +265,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_PANTILT_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_PANTILT_ABSOLUTE_CONTROL,
 		.index		= 11,
 		.size		= 8,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -273,7 +273,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_PANTILT_RELATIVE_CONTROL,
+		.selector	= UVC_CT_PANTILT_RELATIVE_CONTROL,
 		.index		= 12,
 		.size		= 4,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -281,7 +281,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_ROLL_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_ROLL_ABSOLUTE_CONTROL,
 		.index		= 13,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -289,7 +289,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_ROLL_RELATIVE_CONTROL,
+		.selector	= UVC_CT_ROLL_RELATIVE_CONTROL,
 		.index		= 14,
 		.size		= 2,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
@@ -297,7 +297,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_FOCUS_AUTO_CONTROL,
+		.selector	= UVC_CT_FOCUS_AUTO_CONTROL,
 		.index		= 17,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -305,7 +305,7 @@ static struct uvc_control_info uvc_ctrls[] = {
 	},
 	{
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_PRIVACY_CONTROL,
+		.selector	= UVC_CT_PRIVACY_CONTROL,
 		.index		= 18,
 		.size		= 1,
 		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
@@ -332,13 +332,13 @@ static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
 	__s8 zoom = (__s8)data[0];
 
 	switch (query) {
-	case GET_CUR:
+	case UVC_GET_CUR:
 		return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
 
-	case GET_MIN:
-	case GET_MAX:
-	case GET_RES:
-	case GET_DEF:
+	case UVC_GET_MIN:
+	case UVC_GET_MAX:
+	case UVC_GET_RES:
+	case UVC_GET_DEF:
 	default:
 		return data[2];
 	}
@@ -356,7 +356,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_BRIGHTNESS,
 		.name		= "Brightness",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_BRIGHTNESS_CONTROL,
+		.selector	= UVC_PU_BRIGHTNESS_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -366,7 +366,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_CONTRAST,
 		.name		= "Contrast",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_CONTRAST_CONTROL,
+		.selector	= UVC_PU_CONTRAST_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -376,7 +376,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_HUE,
 		.name		= "Hue",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_HUE_CONTROL,
+		.selector	= UVC_PU_HUE_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -386,7 +386,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_SATURATION,
 		.name		= "Saturation",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_SATURATION_CONTROL,
+		.selector	= UVC_PU_SATURATION_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -396,7 +396,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_SHARPNESS,
 		.name		= "Sharpness",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_SHARPNESS_CONTROL,
+		.selector	= UVC_PU_SHARPNESS_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -406,7 +406,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_GAMMA,
 		.name		= "Gamma",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_GAMMA_CONTROL,
+		.selector	= UVC_PU_GAMMA_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -416,7 +416,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_BACKLIGHT_COMPENSATION,
 		.name		= "Backlight Compensation",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_BACKLIGHT_COMPENSATION_CONTROL,
+		.selector	= UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -426,7 +426,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_GAIN,
 		.name		= "Gain",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_GAIN_CONTROL,
+		.selector	= UVC_PU_GAIN_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -436,7 +436,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_POWER_LINE_FREQUENCY,
 		.name		= "Power Line Frequency",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_POWER_LINE_FREQUENCY_CONTROL,
+		.selector	= UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
 		.size		= 2,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_MENU,
@@ -448,7 +448,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_HUE_AUTO,
 		.name		= "Hue, Auto",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_HUE_AUTO_CONTROL,
+		.selector	= UVC_PU_HUE_AUTO_CONTROL,
 		.size		= 1,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
@@ -458,7 +458,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_EXPOSURE_AUTO,
 		.name		= "Exposure, Auto",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_AE_MODE_CONTROL,
+		.selector	= UVC_CT_AE_MODE_CONTROL,
 		.size		= 4,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_MENU,
@@ -470,7 +470,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_EXPOSURE_AUTO_PRIORITY,
 		.name		= "Exposure, Auto Priority",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_AE_PRIORITY_CONTROL,
+		.selector	= UVC_CT_AE_PRIORITY_CONTROL,
 		.size		= 1,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
@@ -480,7 +480,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_EXPOSURE_ABSOLUTE,
 		.name		= "Exposure (Absolute)",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
 		.size		= 32,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -490,7 +490,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
 		.name		= "White Balance Temperature, Auto",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
 		.size		= 1,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
@@ -500,7 +500,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_WHITE_BALANCE_TEMPERATURE,
 		.name		= "White Balance Temperature",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -510,7 +510,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
 		.name		= "White Balance Component, Auto",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
 		.size		= 1,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
@@ -520,7 +520,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_BLUE_BALANCE,
 		.name		= "White Balance Blue Component",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_COMPONENT_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -530,7 +530,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_RED_BALANCE,
 		.name		= "White Balance Red Component",
 		.entity		= UVC_GUID_UVC_PROCESSING,
-		.selector	= PU_WHITE_BALANCE_COMPONENT_CONTROL,
+		.selector	= UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
 		.size		= 16,
 		.offset		= 16,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -540,7 +540,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_FOCUS_ABSOLUTE,
 		.name		= "Focus (absolute)",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_FOCUS_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_FOCUS_ABSOLUTE_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -550,7 +550,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_FOCUS_AUTO,
 		.name		= "Focus, Auto",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_FOCUS_AUTO_CONTROL,
+		.selector	= UVC_CT_FOCUS_AUTO_CONTROL,
 		.size		= 1,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
@@ -560,7 +560,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_ZOOM_ABSOLUTE,
 		.name		= "Zoom, Absolute",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_ZOOM_ABSOLUTE_CONTROL,
+		.selector	= UVC_CT_ZOOM_ABSOLUTE_CONTROL,
 		.size		= 16,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -570,7 +570,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_ZOOM_CONTINUOUS,
 		.name		= "Zoom, Continuous",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_ZOOM_RELATIVE_CONTROL,
+		.selector	= UVC_CT_ZOOM_RELATIVE_CONTROL,
 		.size		= 0,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
@@ -582,7 +582,7 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 		.id		= V4L2_CID_PRIVACY,
 		.name		= "Privacy",
 		.entity		= UVC_GUID_UVC_CAMERA,
-		.selector	= CT_PRIVACY_CONTROL,
+		.selector	= UVC_CT_PRIVACY_CONTROL,
 		.size		= 1,
 		.offset		= 0,
 		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
@@ -675,16 +675,16 @@ static const __u8 uvc_media_transport_input_guid[16] =
 static int uvc_entity_match_guid(struct uvc_entity *entity, __u8 guid[16])
 {
 	switch (UVC_ENTITY_TYPE(entity)) {
-	case ITT_CAMERA:
+	case UVC_ITT_CAMERA:
 		return memcmp(uvc_camera_guid, guid, 16) == 0;
 
-	case ITT_MEDIA_TRANSPORT_INPUT:
+	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
 		return memcmp(uvc_media_transport_input_guid, guid, 16) == 0;
 
-	case VC_PROCESSING_UNIT:
+	case UVC_VC_PROCESSING_UNIT:
 		return memcmp(uvc_processing_guid, guid, 16) == 0;
 
-	case VC_EXTENSION_UNIT:
+	case UVC_VC_EXTENSION_UNIT:
 		return memcmp(entity->extension.guidExtensionCode,
 			      guid, 16) == 0;
 
@@ -729,7 +729,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
 	}
 }
 
-struct uvc_control *uvc_find_control(struct uvc_video_device *video,
+struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
 	__u32 v4l2_id, struct uvc_control_mapping **mapping)
 {
 	struct uvc_control *ctrl = NULL;
@@ -742,17 +742,17 @@ struct uvc_control *uvc_find_control(struct uvc_video_device *video,
 	v4l2_id &= V4L2_CTRL_ID_MASK;
 
 	/* Find the control. */
-	__uvc_find_control(video->processing, v4l2_id, mapping, &ctrl, next);
+	__uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next);
 	if (ctrl && !next)
 		return ctrl;
 
-	list_for_each_entry(entity, &video->iterms, chain) {
+	list_for_each_entry(entity, &chain->iterms, chain) {
 		__uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
 		if (ctrl && !next)
 			return ctrl;
 	}
 
-	list_for_each_entry(entity, &video->extensions, chain) {
+	list_for_each_entry(entity, &chain->extensions, chain) {
 		__uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
 		if (ctrl && !next)
 			return ctrl;
@@ -765,7 +765,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_device *video,
 	return ctrl;
 }
 
-int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
+int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
 	struct v4l2_queryctrl *v4l2_ctrl)
 {
 	struct uvc_control *ctrl;
@@ -775,7 +775,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
 	__u8 *data;
 	int ret;
 
-	ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping);
+	ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
 	if (ctrl == NULL)
 		return -EINVAL;
 
@@ -793,11 +793,13 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
 		v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 	if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
-		if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id,
-				video->dev->intfnum, ctrl->info->selector,
-				data, ctrl->info->size)) < 0)
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id,
+				     chain->dev->intfnum, ctrl->info->selector,
+				     data, ctrl->info->size);
+		if (ret < 0)
 			goto out;
-		v4l2_ctrl->default_value = mapping->get(mapping, GET_DEF, data);
+		v4l2_ctrl->default_value =
+			mapping->get(mapping, UVC_GET_DEF, data);
 	}
 
 	switch (mapping->v4l2_type) {
@@ -829,25 +831,28 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
 	}
 
 	if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
-		if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id,
-				video->dev->intfnum, ctrl->info->selector,
-				data, ctrl->info->size)) < 0)
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id,
+				     chain->dev->intfnum, ctrl->info->selector,
+				     data, ctrl->info->size);
+		if (ret < 0)
 			goto out;
-		v4l2_ctrl->minimum = mapping->get(mapping, GET_MIN, data);
+		v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data);
 	}
 	if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
-		if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
-				video->dev->intfnum, ctrl->info->selector,
-				data, ctrl->info->size)) < 0)
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
+				     chain->dev->intfnum, ctrl->info->selector,
+				     data, ctrl->info->size);
+		if (ret < 0)
 			goto out;
-		v4l2_ctrl->maximum = mapping->get(mapping, GET_MAX, data);
+		v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data);
 	}
 	if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
-		if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
-				video->dev->intfnum, ctrl->info->selector,
-				data, ctrl->info->size)) < 0)
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
+				     chain->dev->intfnum, ctrl->info->selector,
+				     data, ctrl->info->size);
+		if (ret < 0)
 			goto out;
-		v4l2_ctrl->step = mapping->get(mapping, GET_RES, data);
+		v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data);
 	}
 
 	ret = 0;
@@ -881,9 +886,9 @@ out:
  * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
  * control lock.
  */
-int uvc_ctrl_begin(struct uvc_video_device *video)
+int uvc_ctrl_begin(struct uvc_video_chain *chain)
 {
-	return mutex_lock_interruptible(&video->ctrl_mutex) ? -ERESTARTSYS : 0;
+	return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0;
 }
 
 static int uvc_ctrl_commit_entity(struct uvc_device *dev,
@@ -912,7 +917,7 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
 			continue;
 
 		if (!rollback)
-			ret = uvc_query_ctrl(dev, SET_CUR, ctrl->entity->id,
+			ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id,
 				dev->intfnum, ctrl->info->selector,
 				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 				ctrl->info->size);
@@ -933,34 +938,34 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
 	return 0;
 }
 
-int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback)
+int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback)
 {
 	struct uvc_entity *entity;
 	int ret = 0;
 
 	/* Find the control. */
-	ret = uvc_ctrl_commit_entity(video->dev, video->processing, rollback);
+	ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback);
 	if (ret < 0)
 		goto done;
 
-	list_for_each_entry(entity, &video->iterms, chain) {
-		ret = uvc_ctrl_commit_entity(video->dev, entity, rollback);
+	list_for_each_entry(entity, &chain->iterms, chain) {
+		ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
 		if (ret < 0)
 			goto done;
 	}
 
-	list_for_each_entry(entity, &video->extensions, chain) {
-		ret = uvc_ctrl_commit_entity(video->dev, entity, rollback);
+	list_for_each_entry(entity, &chain->extensions, chain) {
+		ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
 		if (ret < 0)
 			goto done;
 	}
 
 done:
-	mutex_unlock(&video->ctrl_mutex);
+	mutex_unlock(&chain->ctrl_mutex);
 	return ret;
 }
 
-int uvc_ctrl_get(struct uvc_video_device *video,
+int uvc_ctrl_get(struct uvc_video_chain *chain,
 	struct v4l2_ext_control *xctrl)
 {
 	struct uvc_control *ctrl;
@@ -969,13 +974,13 @@ int uvc_ctrl_get(struct uvc_video_device *video,
 	unsigned int i;
 	int ret;
 
-	ctrl = uvc_find_control(video, xctrl->id, &mapping);
+	ctrl = uvc_find_control(chain, xctrl->id, &mapping);
 	if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0)
 		return -EINVAL;
 
 	if (!ctrl->loaded) {
-		ret = uvc_query_ctrl(video->dev, GET_CUR, ctrl->entity->id,
-				video->dev->intfnum, ctrl->info->selector,
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
+				chain->dev->intfnum, ctrl->info->selector,
 				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 				ctrl->info->size);
 		if (ret < 0)
@@ -984,7 +989,7 @@ int uvc_ctrl_get(struct uvc_video_device *video,
 		ctrl->loaded = 1;
 	}
 
-	xctrl->value = mapping->get(mapping, GET_CUR,
+	xctrl->value = mapping->get(mapping, UVC_GET_CUR,
 		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 
 	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
@@ -1000,7 +1005,7 @@ int uvc_ctrl_get(struct uvc_video_device *video,
 	return 0;
 }
 
-int uvc_ctrl_set(struct uvc_video_device *video,
+int uvc_ctrl_set(struct uvc_video_chain *chain,
 	struct v4l2_ext_control *xctrl)
 {
 	struct uvc_control *ctrl;
@@ -1008,7 +1013,7 @@ int uvc_ctrl_set(struct uvc_video_device *video,
 	s32 value = xctrl->value;
 	int ret;
 
-	ctrl = uvc_find_control(video, xctrl->id, &mapping);
+	ctrl = uvc_find_control(chain, xctrl->id, &mapping);
 	if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0)
 		return -EINVAL;
 
@@ -1023,8 +1028,8 @@ int uvc_ctrl_set(struct uvc_video_device *video,
 			memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 				0, ctrl->info->size);
 		} else {
-			ret = uvc_query_ctrl(video->dev, GET_CUR,
-				ctrl->entity->id, video->dev->intfnum,
+			ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+				ctrl->entity->id, chain->dev->intfnum,
 				ctrl->info->selector,
 				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 				ctrl->info->size);
@@ -1053,7 +1058,7 @@ int uvc_ctrl_set(struct uvc_video_device *video,
  * Dynamic controls
  */
 
-int uvc_xu_ctrl_query(struct uvc_video_device *video,
+int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
 	struct uvc_xu_control *xctrl, int set)
 {
 	struct uvc_entity *entity;
@@ -1063,7 +1068,7 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video,
 	int ret;
 
 	/* Find the extension unit. */
-	list_for_each_entry(entity, &video->extensions, chain) {
+	list_for_each_entry(entity, &chain->extensions, chain) {
 		if (entity->id == xctrl->unit)
 			break;
 	}
@@ -1102,7 +1107,7 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video,
 	    (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR)))
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&video->ctrl_mutex))
+	if (mutex_lock_interruptible(&chain->ctrl_mutex))
 		return -ERESTARTSYS;
 
 	memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
@@ -1115,9 +1120,9 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video,
 		goto out;
 	}
 
-	ret = uvc_query_ctrl(video->dev, set ? SET_CUR : GET_CUR, xctrl->unit,
-			     video->dev->intfnum, xctrl->selector, data,
-			     xctrl->size);
+	ret = uvc_query_ctrl(chain->dev, set ? UVC_SET_CUR : UVC_GET_CUR,
+			     xctrl->unit, chain->dev->intfnum, xctrl->selector,
+			     data, xctrl->size);
 	if (ret < 0)
 		goto out;
 
@@ -1132,7 +1137,7 @@ out:
 		       uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
 		       xctrl->size);
 
-	mutex_unlock(&video->ctrl_mutex);
+	mutex_unlock(&chain->ctrl_mutex);
 	return ret;
 }
 
@@ -1211,7 +1216,7 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
 	if (!found)
 		return;
 
-	if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) {
+	if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
 		/* Check if the device control information and length match
 		 * the user supplied information.
 		 */
@@ -1219,8 +1224,9 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
 		__le16 size;
 		__u8 inf;
 
-		if ((ret = uvc_query_ctrl(dev, GET_LEN, ctrl->entity->id,
-			dev->intfnum, info->selector, (__u8 *)&size, 2)) < 0) {
+		ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id,
+			dev->intfnum, info->selector, (__u8 *)&size, 2);
+		if (ret < 0) {
 			uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on "
 				"control " UVC_GUID_FORMAT "/%u (%d).\n",
 				UVC_GUID_ARGS(info->entity), info->selector,
@@ -1236,8 +1242,9 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
 			return;
 		}
 
-		if ((ret = uvc_query_ctrl(dev, GET_INFO, ctrl->entity->id,
-			dev->intfnum, info->selector, &inf, 1)) < 0) {
+		ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id,
+			dev->intfnum, info->selector, &inf, 1);
+		if (ret < 0) {
 			uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on "
 				"control " UVC_GUID_FORMAT "/%u (%d).\n",
 				UVC_GUID_ARGS(info->entity), info->selector,
@@ -1391,7 +1398,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity)
 	unsigned int size;
 	unsigned int i;
 
-	if (UVC_ENTITY_TYPE(entity) != VC_PROCESSING_UNIT)
+	if (UVC_ENTITY_TYPE(entity) != UVC_VC_PROCESSING_UNIT)
 		return;
 
 	controls = entity->processing.bmControls;
@@ -1427,13 +1434,13 @@ int uvc_ctrl_init_device(struct uvc_device *dev)
 		unsigned int bControlSize = 0, ncontrols = 0;
 		__u8 *bmControls = NULL;
 
-		if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) {
+		if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
 			bmControls = entity->extension.bmControls;
 			bControlSize = entity->extension.bControlSize;
-		} else if (UVC_ENTITY_TYPE(entity) == VC_PROCESSING_UNIT) {
+		} else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) {
 			bmControls = entity->processing.bmControls;
 			bControlSize = entity->processing.bControlSize;
-		} else if (UVC_ENTITY_TYPE(entity) == ITT_CAMERA) {
+		} else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) {
 			bmControls = entity->camera.bmControls;
 			bControlSize = entity->camera.bControlSize;
 		}
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 04b47832fa0a..8756be569154 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -249,23 +249,23 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
 
 	list_for_each_entry_continue(entity, &dev->entities, list) {
 		switch (UVC_ENTITY_TYPE(entity)) {
-		case TT_STREAMING:
+		case UVC_TT_STREAMING:
 			if (entity->output.bSourceID == id)
 				return entity;
 			break;
 
-		case VC_PROCESSING_UNIT:
+		case UVC_VC_PROCESSING_UNIT:
 			if (entity->processing.bSourceID == id)
 				return entity;
 			break;
 
-		case VC_SELECTOR_UNIT:
+		case UVC_VC_SELECTOR_UNIT:
 			for (i = 0; i < entity->selector.bNrInPins; ++i)
 				if (entity->selector.baSourceID[i] == id)
 					return entity;
 			break;
 
-		case VC_EXTENSION_UNIT:
+		case UVC_VC_EXTENSION_UNIT:
 			for (i = 0; i < entity->extension.bNrInPins; ++i)
 				if (entity->extension.baSourceID[i] == id)
 					return entity;
@@ -276,8 +276,20 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
 	return NULL;
 }
 
+static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
+{
+	struct uvc_streaming *stream;
+
+	list_for_each_entry(stream, &dev->streams, list) {
+		if (stream->header.bTerminalLink == id)
+			return stream;
+	}
+
+	return NULL;
+}
+
 /* ------------------------------------------------------------------------
- * Descriptors handling
+ * Descriptors parsing
  */
 
 static int uvc_parse_format(struct uvc_device *dev,
@@ -297,9 +309,9 @@ static int uvc_parse_format(struct uvc_device *dev,
 	format->index = buffer[3];
 
 	switch (buffer[2]) {
-	case VS_FORMAT_UNCOMPRESSED:
-	case VS_FORMAT_FRAME_BASED:
-		n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28;
+	case UVC_VS_FORMAT_UNCOMPRESSED:
+	case UVC_VS_FORMAT_FRAME_BASED:
+		n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
 		if (buflen < n) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FORMAT error\n",
@@ -325,16 +337,16 @@ static int uvc_parse_format(struct uvc_device *dev,
 		}
 
 		format->bpp = buffer[21];
-		if (buffer[2] == VS_FORMAT_UNCOMPRESSED) {
-			ftype = VS_FRAME_UNCOMPRESSED;
+		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
+			ftype = UVC_VS_FRAME_UNCOMPRESSED;
 		} else {
-			ftype = VS_FRAME_FRAME_BASED;
+			ftype = UVC_VS_FRAME_FRAME_BASED;
 			if (buffer[27])
 				format->flags = UVC_FMT_FLAG_COMPRESSED;
 		}
 		break;
 
-	case VS_FORMAT_MJPEG:
+	case UVC_VS_FORMAT_MJPEG:
 		if (buflen < 11) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FORMAT error\n",
@@ -347,10 +359,10 @@ static int uvc_parse_format(struct uvc_device *dev,
 		format->fcc = V4L2_PIX_FMT_MJPEG;
 		format->flags = UVC_FMT_FLAG_COMPRESSED;
 		format->bpp = 0;
-		ftype = VS_FRAME_MJPEG;
+		ftype = UVC_VS_FRAME_MJPEG;
 		break;
 
-	case VS_FORMAT_DV:
+	case UVC_VS_FORMAT_DV:
 		if (buflen < 9) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d FORMAT error\n",
@@ -395,8 +407,8 @@ static int uvc_parse_format(struct uvc_device *dev,
 		format->nframes = 1;
 		break;
 
-	case VS_FORMAT_MPEG2TS:
-	case VS_FORMAT_STREAM_BASED:
+	case UVC_VS_FORMAT_MPEG2TS:
+	case UVC_VS_FORMAT_STREAM_BASED:
 		/* Not supported yet. */
 	default:
 		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
@@ -416,7 +428,7 @@ static int uvc_parse_format(struct uvc_device *dev,
 	 */
 	while (buflen > 2 && buffer[2] == ftype) {
 		frame = &format->frame[format->nframes];
-		if (ftype != VS_FRAME_FRAME_BASED)
+		if (ftype != UVC_VS_FRAME_FRAME_BASED)
 			n = buflen > 25 ? buffer[25] : 0;
 		else
 			n = buflen > 21 ? buffer[21] : 0;
@@ -436,7 +448,7 @@ static int uvc_parse_format(struct uvc_device *dev,
 		frame->wHeight = get_unaligned_le16(&buffer[7]);
 		frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
 		frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
-		if (ftype != VS_FRAME_FRAME_BASED) {
+		if (ftype != UVC_VS_FRAME_FRAME_BASED) {
 			frame->dwMaxVideoFrameBufferSize =
 				get_unaligned_le32(&buffer[17]);
 			frame->dwDefaultFrameInterval =
@@ -491,12 +503,12 @@ static int uvc_parse_format(struct uvc_device *dev,
 		buffer += buffer[0];
 	}
 
-	if (buflen > 2 && buffer[2] == VS_STILL_IMAGE_FRAME) {
+	if (buflen > 2 && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
 		buflen -= buffer[0];
 		buffer += buffer[0];
 	}
 
-	if (buflen > 2 && buffer[2] == VS_COLORFORMAT) {
+	if (buflen > 2 && buffer[2] == UVC_VS_COLORFORMAT) {
 		if (buflen < 6) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d COLORFORMAT error\n",
@@ -530,7 +542,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 	int ret = -EINVAL;
 
 	if (intf->cur_altsetting->desc.bInterfaceSubClass
-		!= SC_VIDEOSTREAMING) {
+		!= UVC_SC_VIDEOSTREAMING) {
 		uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
 			"video streaming interface\n", dev->udev->devnum,
 			intf->altsetting[0].desc.bInterfaceNumber);
@@ -551,6 +563,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 	}
 
 	mutex_init(&streaming->mutex);
+	streaming->dev = dev;
 	streaming->intf = usb_get_intf(intf);
 	streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
 
@@ -589,12 +602,12 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 
 	/* Parse the header descriptor. */
 	switch (buffer[2]) {
-	case VS_OUTPUT_HEADER:
+	case UVC_VS_OUTPUT_HEADER:
 		streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 		size = 9;
 		break;
 
-	case VS_INPUT_HEADER:
+	case UVC_VS_INPUT_HEADER:
 		streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		size = 13;
 		break;
@@ -618,7 +631,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 
 	streaming->header.bNumFormats = p;
 	streaming->header.bEndpointAddress = buffer[6];
-	if (buffer[2] == VS_INPUT_HEADER) {
+	if (buffer[2] == UVC_VS_INPUT_HEADER) {
 		streaming->header.bmInfo = buffer[7];
 		streaming->header.bTerminalLink = buffer[8];
 		streaming->header.bStillCaptureMethod = buffer[9];
@@ -644,15 +657,15 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 	_buflen = buflen;
 
 	/* Count the format and frame descriptors. */
-	while (_buflen > 2 && _buffer[1] == CS_INTERFACE) {
+	while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
 		switch (_buffer[2]) {
-		case VS_FORMAT_UNCOMPRESSED:
-		case VS_FORMAT_MJPEG:
-		case VS_FORMAT_FRAME_BASED:
+		case UVC_VS_FORMAT_UNCOMPRESSED:
+		case UVC_VS_FORMAT_MJPEG:
+		case UVC_VS_FORMAT_FRAME_BASED:
 			nformats++;
 			break;
 
-		case VS_FORMAT_DV:
+		case UVC_VS_FORMAT_DV:
 			/* DV format has no frame descriptor. We will create a
 			 * dummy frame descriptor with a dummy frame interval.
 			 */
@@ -661,22 +674,22 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 			nintervals++;
 			break;
 
-		case VS_FORMAT_MPEG2TS:
-		case VS_FORMAT_STREAM_BASED:
+		case UVC_VS_FORMAT_MPEG2TS:
+		case UVC_VS_FORMAT_STREAM_BASED:
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 				"interface %d FORMAT %u is not supported.\n",
 				dev->udev->devnum,
 				alts->desc.bInterfaceNumber, _buffer[2]);
 			break;
 
-		case VS_FRAME_UNCOMPRESSED:
-		case VS_FRAME_MJPEG:
+		case UVC_VS_FRAME_UNCOMPRESSED:
+		case UVC_VS_FRAME_MJPEG:
 			nframes++;
 			if (_buflen > 25)
 				nintervals += _buffer[25] ? _buffer[25] : 3;
 			break;
 
-		case VS_FRAME_FRAME_BASED:
+		case UVC_VS_FRAME_FRAME_BASED:
 			nframes++;
 			if (_buflen > 21)
 				nintervals += _buffer[21] ? _buffer[21] : 3;
@@ -709,12 +722,12 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 	streaming->nformats = nformats;
 
 	/* Parse the format descriptors. */
-	while (buflen > 2 && buffer[1] == CS_INTERFACE) {
+	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
 		switch (buffer[2]) {
-		case VS_FORMAT_UNCOMPRESSED:
-		case VS_FORMAT_MJPEG:
-		case VS_FORMAT_DV:
-		case VS_FORMAT_FRAME_BASED:
+		case UVC_VS_FORMAT_UNCOMPRESSED:
+		case UVC_VS_FORMAT_MJPEG:
+		case UVC_VS_FORMAT_DV:
+		case UVC_VS_FORMAT_FRAME_BASED:
 			format->frame = frame;
 			ret = uvc_parse_format(dev, streaming, format,
 				&interval, buffer, buflen);
@@ -751,7 +764,7 @@ static int uvc_parse_streaming(struct uvc_device *dev,
 			streaming->maxpsize = psize;
 	}
 
-	list_add_tail(&streaming->list, &dev->streaming);
+	list_add_tail(&streaming->list, &dev->streams);
 	return 0;
 
 error:
@@ -819,7 +832,7 @@ static int uvc_parse_vendor_control(struct uvc_device *dev,
 			return -ENOMEM;
 
 		unit->id = buffer[3];
-		unit->type = VC_EXTENSION_UNIT;
+		unit->type = UVC_VC_EXTENSION_UNIT;
 		memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
 		unit->extension.bNumControls = buffer[20];
 		unit->extension.bNrInPins = get_unaligned_le16(&buffer[21]);
@@ -856,7 +869,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 	__u16 type;
 
 	switch (buffer[2]) {
-	case VC_HEADER:
+	case UVC_VC_HEADER:
 		n = buflen >= 12 ? buffer[11] : 0;
 
 		if (buflen < 12 || buflen < 12 + n) {
@@ -883,7 +896,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		}
 		break;
 
-	case VC_INPUT_TERMINAL:
+	case UVC_VC_INPUT_TERMINAL:
 		if (buflen < 8) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
 				"interface %d INPUT_TERMINAL error\n",
@@ -908,11 +921,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		p = 0;
 		len = 8;
 
-		if (type == ITT_CAMERA) {
+		if (type == UVC_ITT_CAMERA) {
 			n = buflen >= 15 ? buffer[14] : 0;
 			len = 15;
 
-		} else if (type == ITT_MEDIA_TRANSPORT_INPUT) {
+		} else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
 			n = buflen >= 9 ? buffer[8] : 0;
 			p = buflen >= 10 + n ? buffer[9+n] : 0;
 			len = 10;
@@ -932,7 +945,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		term->id = buffer[3];
 		term->type = type | UVC_TERM_INPUT;
 
-		if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) {
+		if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
 			term->camera.bControlSize = n;
 			term->camera.bmControls = (__u8 *)term + sizeof *term;
 			term->camera.wObjectiveFocalLengthMin =
@@ -942,7 +955,8 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 			term->camera.wOcularFocalLength =
 				get_unaligned_le16(&buffer[12]);
 			memcpy(term->camera.bmControls, &buffer[15], n);
-		} else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) {
+		} else if (UVC_ENTITY_TYPE(term) ==
+			   UVC_ITT_MEDIA_TRANSPORT_INPUT) {
 			term->media.bControlSize = n;
 			term->media.bmControls = (__u8 *)term + sizeof *term;
 			term->media.bTransportModeSize = p;
@@ -955,9 +969,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		if (buffer[7] != 0)
 			usb_string(udev, buffer[7], term->name,
 				   sizeof term->name);
-		else if (UVC_ENTITY_TYPE(term) == ITT_CAMERA)
+		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
 			sprintf(term->name, "Camera %u", buffer[3]);
-		else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT)
+		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
 			sprintf(term->name, "Media %u", buffer[3]);
 		else
 			sprintf(term->name, "Input %u", buffer[3]);
@@ -965,7 +979,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		list_add_tail(&term->list, &dev->entities);
 		break;
 
-	case VC_OUTPUT_TERMINAL:
+	case UVC_VC_OUTPUT_TERMINAL:
 		if (buflen < 9) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
 				"interface %d OUTPUT_TERMINAL error\n",
@@ -1002,7 +1016,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		list_add_tail(&term->list, &dev->entities);
 		break;
 
-	case VC_SELECTOR_UNIT:
+	case UVC_VC_SELECTOR_UNIT:
 		p = buflen >= 5 ? buffer[4] : 0;
 
 		if (buflen < 5 || buflen < 6 + p) {
@@ -1031,7 +1045,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		list_add_tail(&unit->list, &dev->entities);
 		break;
 
-	case VC_PROCESSING_UNIT:
+	case UVC_VC_PROCESSING_UNIT:
 		n = buflen >= 8 ? buffer[7] : 0;
 		p = dev->uvc_version >= 0x0110 ? 10 : 9;
 
@@ -1066,7 +1080,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
 		list_add_tail(&unit->list, &dev->entities);
 		break;
 
-	case VC_EXTENSION_UNIT:
+	case UVC_VC_EXTENSION_UNIT:
 		p = buflen >= 22 ? buffer[21] : 0;
 		n = buflen >= 24 + p ? buffer[22+p] : 0;
 
@@ -1158,43 +1172,40 @@ next_descriptor:
 }
 
 /* ------------------------------------------------------------------------
- * USB probe and disconnect
+ * UVC device scan
  */
 
 /*
- * Unregister the video devices.
- */
-static void uvc_unregister_video(struct uvc_device *dev)
-{
-	if (dev->video.vdev) {
-		if (dev->video.vdev->minor == -1)
-			video_device_release(dev->video.vdev);
-		else
-			video_unregister_device(dev->video.vdev);
-		dev->video.vdev = NULL;
-	}
-}
-
-/*
  * Scan the UVC descriptors to locate a chain starting at an Output Terminal
  * and containing the following units:
  *
- * - one Output Terminal (USB Streaming or Display)
+ * - one or more Output Terminals (USB Streaming or Display)
  * - zero or one Processing Unit
- * - zero, one or mode single-input Selector Units
+ * - zero, one or more single-input Selector Units
  * - zero or one multiple-input Selector Units, provided all inputs are
  *   connected to input terminals
  * - zero, one or mode single-input Extension Units
  * - one or more Input Terminals (Camera, External or USB Streaming)
  *
- * A side forward scan is made on each detected entity to check for additional
- * extension units.
+ * The terminal and units must match on of the following structures:
+ *
+ * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
+ * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
+ * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
+ *
+ *                 +---------+    +---------+ -> OTT_*(0)
+ * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
+ *                 +---------+    +---------+ -> OTT_*(n)
+ *
+ * The Processing Unit and Extension Units can be in any order. Additional
+ * Extension Units connected to the main chain as single-unit branches are
+ * also supported. Single-input Selector Units are ignored.
  */
-static int uvc_scan_chain_entity(struct uvc_video_device *video,
+static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
 	struct uvc_entity *entity)
 {
 	switch (UVC_ENTITY_TYPE(entity)) {
-	case VC_EXTENSION_UNIT:
+	case UVC_VC_EXTENSION_UNIT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
 			printk(" <- XU %d", entity->id);
 
@@ -1204,23 +1215,23 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video,
 			return -1;
 		}
 
-		list_add_tail(&entity->chain, &video->extensions);
+		list_add_tail(&entity->chain, &chain->extensions);
 		break;
 
-	case VC_PROCESSING_UNIT:
+	case UVC_VC_PROCESSING_UNIT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
 			printk(" <- PU %d", entity->id);
 
-		if (video->processing != NULL) {
+		if (chain->processing != NULL) {
 			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
 				"Processing Units in chain.\n");
 			return -1;
 		}
 
-		video->processing = entity;
+		chain->processing = entity;
 		break;
 
-	case VC_SELECTOR_UNIT:
+	case UVC_VC_SELECTOR_UNIT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
 			printk(" <- SU %d", entity->id);
 
@@ -1228,25 +1239,25 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video,
 		if (entity->selector.bNrInPins == 1)
 			break;
 
-		if (video->selector != NULL) {
+		if (chain->selector != NULL) {
 			uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
 				"Units in chain.\n");
 			return -1;
 		}
 
-		video->selector = entity;
+		chain->selector = entity;
 		break;
 
-	case ITT_VENDOR_SPECIFIC:
-	case ITT_CAMERA:
-	case ITT_MEDIA_TRANSPORT_INPUT:
+	case UVC_ITT_VENDOR_SPECIFIC:
+	case UVC_ITT_CAMERA:
+	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
 			printk(" <- IT %d\n", entity->id);
 
-		list_add_tail(&entity->chain, &video->iterms);
+		list_add_tail(&entity->chain, &chain->iterms);
 		break;
 
-	case TT_STREAMING:
+	case UVC_TT_STREAMING:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
 			printk(" <- IT %d\n", entity->id);
 
@@ -1256,14 +1267,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video,
 			return -1;
 		}
 
-		if (video->sterm != NULL) {
-			uvc_trace(UVC_TRACE_DESCR, "Found multiple streaming "
-				"entities in chain.\n");
-			return -1;
-		}
-
-		list_add_tail(&entity->chain, &video->iterms);
-		video->sterm = entity;
+		list_add_tail(&entity->chain, &chain->iterms);
 		break;
 
 	default:
@@ -1275,7 +1279,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video,
 	return 0;
 }
 
-static int uvc_scan_chain_forward(struct uvc_video_device *video,
+static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
 	struct uvc_entity *entity, struct uvc_entity *prev)
 {
 	struct uvc_entity *forward;
@@ -1286,28 +1290,51 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video,
 	found = 0;
 
 	while (1) {
-		forward = uvc_entity_by_reference(video->dev, entity->id,
+		forward = uvc_entity_by_reference(chain->dev, entity->id,
 			forward);
 		if (forward == NULL)
 			break;
-
-		if (UVC_ENTITY_TYPE(forward) != VC_EXTENSION_UNIT ||
-		    forward == prev)
+		if (forward == prev)
 			continue;
 
-		if (forward->extension.bNrInPins != 1) {
-			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has "
-				"more than 1 input pin.\n", entity->id);
-			return -1;
-		}
+		switch (UVC_ENTITY_TYPE(forward)) {
+		case UVC_VC_EXTENSION_UNIT:
+			if (forward->extension.bNrInPins != 1) {
+				uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
+					  "has more than 1 input pin.\n",
+					  entity->id);
+				return -EINVAL;
+			}
+
+			list_add_tail(&forward->chain, &chain->extensions);
+			if (uvc_trace_param & UVC_TRACE_PROBE) {
+				if (!found)
+					printk(" (->");
 
-		list_add_tail(&forward->chain, &video->extensions);
-		if (uvc_trace_param & UVC_TRACE_PROBE) {
-			if (!found)
-				printk(" (-> XU");
+				printk(" XU %d", forward->id);
+				found = 1;
+			}
+			break;
+
+		case UVC_OTT_VENDOR_SPECIFIC:
+		case UVC_OTT_DISPLAY:
+		case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+		case UVC_TT_STREAMING:
+			if (UVC_ENTITY_IS_ITERM(forward)) {
+				uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
+					"terminal %u.\n", forward->id);
+				return -EINVAL;
+			}
 
-			printk(" %d", forward->id);
-			found = 1;
+			list_add_tail(&forward->chain, &chain->oterms);
+			if (uvc_trace_param & UVC_TRACE_PROBE) {
+				if (!found)
+					printk(" (->");
+
+				printk(" OT %d", forward->id);
+				found = 1;
+			}
+			break;
 		}
 	}
 	if (found)
@@ -1316,22 +1343,22 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video,
 	return 0;
 }
 
-static int uvc_scan_chain_backward(struct uvc_video_device *video,
+static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
 	struct uvc_entity *entity)
 {
 	struct uvc_entity *term;
 	int id = -1, i;
 
 	switch (UVC_ENTITY_TYPE(entity)) {
-	case VC_EXTENSION_UNIT:
+	case UVC_VC_EXTENSION_UNIT:
 		id = entity->extension.baSourceID[0];
 		break;
 
-	case VC_PROCESSING_UNIT:
+	case UVC_VC_PROCESSING_UNIT:
 		id = entity->processing.bSourceID;
 		break;
 
-	case VC_SELECTOR_UNIT:
+	case UVC_VC_SELECTOR_UNIT:
 		/* Single-input selector units are ignored. */
 		if (entity->selector.bNrInPins == 1) {
 			id = entity->selector.baSourceID[0];
@@ -1341,10 +1368,10 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video,
 		if (uvc_trace_param & UVC_TRACE_PROBE)
 			printk(" <- IT");
 
-		video->selector = entity;
+		chain->selector = entity;
 		for (i = 0; i < entity->selector.bNrInPins; ++i) {
 			id = entity->selector.baSourceID[i];
-			term = uvc_entity_by_id(video->dev, id);
+			term = uvc_entity_by_id(chain->dev, id);
 			if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
 				uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
 					"input %d isn't connected to an "
@@ -1355,8 +1382,8 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video,
 			if (uvc_trace_param & UVC_TRACE_PROBE)
 				printk(" %d", term->id);
 
-			list_add_tail(&term->chain, &video->iterms);
-			uvc_scan_chain_forward(video, term, entity);
+			list_add_tail(&term->chain, &chain->iterms);
+			uvc_scan_chain_forward(chain, term, entity);
 		}
 
 		if (uvc_trace_param & UVC_TRACE_PROBE)
@@ -1369,125 +1396,170 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video,
 	return id;
 }
 
-static int uvc_scan_chain(struct uvc_video_device *video)
+static int uvc_scan_chain(struct uvc_video_chain *chain,
+			  struct uvc_entity *oterm)
 {
 	struct uvc_entity *entity, *prev;
 	int id;
 
-	entity = video->oterm;
+	entity = oterm;
+	list_add_tail(&entity->chain, &chain->oterms);
 	uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
 
-	if (UVC_ENTITY_TYPE(entity) == TT_STREAMING)
-		video->sterm = entity;
-
 	id = entity->output.bSourceID;
 	while (id != 0) {
 		prev = entity;
-		entity = uvc_entity_by_id(video->dev, id);
+		entity = uvc_entity_by_id(chain->dev, id);
 		if (entity == NULL) {
 			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
 				"unknown entity %d.\n", id);
-			return -1;
+			return -EINVAL;
+		}
+
+		if (entity->chain.next || entity->chain.prev) {
+			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+				"entity %d already in chain.\n", id);
+			return -EINVAL;
 		}
 
 		/* Process entity */
-		if (uvc_scan_chain_entity(video, entity) < 0)
-			return -1;
+		if (uvc_scan_chain_entity(chain, entity) < 0)
+			return -EINVAL;
 
 		/* Forward scan */
-		if (uvc_scan_chain_forward(video, entity, prev) < 0)
-			return -1;
+		if (uvc_scan_chain_forward(chain, entity, prev) < 0)
+			return -EINVAL;
 
 		/* Stop when a terminal is found. */
-		if (!UVC_ENTITY_IS_UNIT(entity))
+		if (UVC_ENTITY_IS_TERM(entity))
 			break;
 
 		/* Backward scan */
-		id = uvc_scan_chain_backward(video, entity);
+		id = uvc_scan_chain_backward(chain, entity);
 		if (id < 0)
 			return id;
 	}
 
-	if (video->sterm == NULL) {
-		uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in "
-			"chain.\n");
-		return -1;
+	return 0;
+}
+
+static unsigned int uvc_print_terms(struct list_head *terms, char *buffer)
+{
+	struct uvc_entity *term;
+	unsigned int nterms = 0;
+	char *p = buffer;
+
+	list_for_each_entry(term, terms, chain) {
+		p += sprintf(p, "%u", term->id);
+		if (term->chain.next != terms) {
+			p += sprintf(p, ",");
+			if (++nterms >= 4) {
+				p += sprintf(p, "...");
+				break;
+			}
+		}
 	}
 
-	return 0;
+	return p - buffer;
+}
+
+static const char *uvc_print_chain(struct uvc_video_chain *chain)
+{
+	static char buffer[43];
+	char *p = buffer;
+
+	p += uvc_print_terms(&chain->iterms, p);
+	p += sprintf(p, " -> ");
+	uvc_print_terms(&chain->oterms, p);
+
+	return buffer;
 }
 
 /*
- * Register the video devices.
- *
- * The driver currently supports a single video device per control interface
- * only. The terminal and units must match the following structure:
+ * Scan the device for video chains and register video devices.
  *
- * ITT_* -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING
- * TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_*
- *
- * The Extension Units, if present, must have a single input pin. The
- * Processing Unit and Extension Units can be in any order. Additional
- * Extension Units connected to the main chain as single-unit branches are
- * also supported.
+ * Chains are scanned starting at their output terminals and walked backwards.
  */
-static int uvc_register_video(struct uvc_device *dev)
+static int uvc_scan_device(struct uvc_device *dev)
 {
-	struct video_device *vdev;
+	struct uvc_video_chain *chain;
 	struct uvc_entity *term;
-	int found = 0, ret;
 
-	/* Check if the control interface matches the structure we expect. */
 	list_for_each_entry(term, &dev->entities, list) {
-		struct uvc_streaming *streaming;
-
-		if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term))
+		if (!UVC_ENTITY_IS_OTERM(term))
 			continue;
 
-		memset(&dev->video, 0, sizeof dev->video);
-		mutex_init(&dev->video.ctrl_mutex);
-		INIT_LIST_HEAD(&dev->video.iterms);
-		INIT_LIST_HEAD(&dev->video.extensions);
-		dev->video.oterm = term;
-		dev->video.dev = dev;
-		if (uvc_scan_chain(&dev->video) < 0)
+		/* If the terminal is already included in a chain, skip it.
+		 * This can happen for chains that have multiple output
+		 * terminals, where all output terminals beside the first one
+		 * will be inserted in the chain in forward scans.
+		 */
+		if (term->chain.next || term->chain.prev)
 			continue;
 
-		list_for_each_entry(streaming, &dev->streaming, list) {
-			if (streaming->header.bTerminalLink ==
-			    dev->video.sterm->id) {
-				dev->video.streaming = streaming;
-				found = 1;
-				break;
-			}
+		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+		if (chain == NULL)
+			return -ENOMEM;
+
+		INIT_LIST_HEAD(&chain->iterms);
+		INIT_LIST_HEAD(&chain->oterms);
+		INIT_LIST_HEAD(&chain->extensions);
+		mutex_init(&chain->ctrl_mutex);
+		chain->dev = dev;
+
+		if (uvc_scan_chain(chain, term) < 0) {
+			kfree(chain);
+			continue;
 		}
 
-		if (found)
-			break;
+		uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
+			  uvc_print_chain(chain));
+
+		list_add_tail(&chain->list, &dev->chains);
 	}
 
-	if (!found) {
+	if (list_empty(&dev->chains)) {
 		uvc_printk(KERN_INFO, "No valid video chain found.\n");
 		return -1;
 	}
 
-	if (uvc_trace_param & UVC_TRACE_PROBE) {
-		uvc_printk(KERN_INFO, "Found a valid video chain (");
-		list_for_each_entry(term, &dev->video.iterms, chain) {
-			printk("%d", term->id);
-			if (term->chain.next != &dev->video.iterms)
-				printk(",");
-		}
-		printk(" -> %d).\n", dev->video.oterm->id);
+	return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Video device registration and unregistration
+ */
+
+/*
+ * Unregister the video devices.
+ */
+static void uvc_unregister_video(struct uvc_device *dev)
+{
+	struct uvc_streaming *stream;
+
+	list_for_each_entry(stream, &dev->streams, list) {
+		if (stream->vdev == NULL)
+			continue;
+
+		if (stream->vdev->minor == -1)
+			video_device_release(stream->vdev);
+		else
+			video_unregister_device(stream->vdev);
+		stream->vdev = NULL;
 	}
+}
 
-	/* Initialize the video buffers queue. */
-	uvc_queue_init(&dev->video.queue, dev->video.streaming->type);
+static int uvc_register_video(struct uvc_device *dev,
+		struct uvc_streaming *stream)
+{
+	struct video_device *vdev;
+	int ret;
 
 	/* Initialize the streaming interface with default streaming
 	 * parameters.
 	 */
-	if ((ret = uvc_video_init(&dev->video)) < 0) {
+	ret = uvc_video_init(stream);
+	if (ret < 0) {
 		uvc_printk(KERN_ERR, "Failed to initialize the device "
 			"(%d).\n", ret);
 		return ret;
@@ -1495,8 +1567,11 @@ static int uvc_register_video(struct uvc_device *dev)
 
 	/* Register the device with V4L. */
 	vdev = video_device_alloc();
-	if (vdev == NULL)
-		return -1;
+	if (vdev == NULL) {
+		uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
+			   ret);
+		return -ENOMEM;
+	}
 
 	/* We already hold a reference to dev->udev. The video device will be
 	 * unregistered before the reference is released, so we don't need to
@@ -1511,19 +1586,74 @@ static int uvc_register_video(struct uvc_device *dev)
 	/* Set the driver data before calling video_register_device, otherwise
 	 * uvc_v4l2_open might race us.
 	 */
-	dev->video.vdev = vdev;
-	video_set_drvdata(vdev, &dev->video);
-
-	if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) {
-		dev->video.vdev = NULL;
+	stream->vdev = vdev;
+	video_set_drvdata(vdev, stream);
+
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
+			   ret);
+		stream->vdev = NULL;
 		video_device_release(vdev);
-		return -1;
+		return ret;
 	}
 
 	return 0;
 }
 
 /*
+ * Register all video devices in all chains.
+ */
+static int uvc_register_terms(struct uvc_device *dev,
+	struct uvc_video_chain *chain, struct list_head *terms)
+{
+	struct uvc_streaming *stream;
+	struct uvc_entity *term;
+	int ret;
+
+	list_for_each_entry(term, terms, chain) {
+		if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
+			continue;
+
+		stream = uvc_stream_by_id(dev, term->id);
+		if (stream == NULL) {
+			uvc_printk(KERN_INFO, "No streaming interface found "
+				   "for terminal %u.", term->id);
+			continue;
+		}
+
+		stream->chain = chain;
+		ret = uvc_register_video(dev, stream);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int uvc_register_chains(struct uvc_device *dev)
+{
+	struct uvc_video_chain *chain;
+	int ret;
+
+	list_for_each_entry(chain, &dev->chains, list) {
+		ret = uvc_register_terms(dev, chain, &chain->iterms);
+		if (ret < 0)
+			return ret;
+
+		ret = uvc_register_terms(dev, chain, &chain->oterms);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * USB probe, disconnect, suspend and resume
+ */
+
+/*
  * Delete the UVC device.
  *
  * Called by the kernel when the last reference to the uvc_device structure
@@ -1544,7 +1674,7 @@ void uvc_delete(struct kref *kref)
 	struct uvc_device *dev = container_of(kref, struct uvc_device, kref);
 	struct list_head *p, *n;
 
-	/* Unregister the video device. */
+	/* Unregister the video devices. */
 	uvc_unregister_video(dev);
 	usb_put_intf(dev->intf);
 	usb_put_dev(dev->udev);
@@ -1552,13 +1682,19 @@ void uvc_delete(struct kref *kref)
 	uvc_status_cleanup(dev);
 	uvc_ctrl_cleanup_device(dev);
 
+	list_for_each_safe(p, n, &dev->chains) {
+		struct uvc_video_chain *chain;
+		chain = list_entry(p, struct uvc_video_chain, list);
+		kfree(chain);
+	}
+
 	list_for_each_safe(p, n, &dev->entities) {
 		struct uvc_entity *entity;
 		entity = list_entry(p, struct uvc_entity, list);
 		kfree(entity);
 	}
 
-	list_for_each_safe(p, n, &dev->streaming) {
+	list_for_each_safe(p, n, &dev->streams) {
 		struct uvc_streaming *streaming;
 		streaming = list_entry(p, struct uvc_streaming, list);
 		usb_driver_release_interface(&uvc_driver.driver,
@@ -1592,7 +1728,8 @@ static int uvc_probe(struct usb_interface *intf,
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&dev->entities);
-	INIT_LIST_HEAD(&dev->streaming);
+	INIT_LIST_HEAD(&dev->chains);
+	INIT_LIST_HEAD(&dev->streams);
 	kref_init(&dev->kref);
 	atomic_set(&dev->users, 0);
 
@@ -1633,8 +1770,12 @@ static int uvc_probe(struct usb_interface *intf,
 	if (uvc_ctrl_init_device(dev) < 0)
 		goto error;
 
-	/* Register the video devices. */
-	if (uvc_register_video(dev) < 0)
+	/* Scan the device for video chains. */
+	if (uvc_scan_device(dev) < 0)
+		goto error;
+
+	/* Register video devices. */
+	if (uvc_register_chains(dev) < 0)
 		goto error;
 
 	/* Save our data pointer in the interface data. */
@@ -1664,7 +1805,8 @@ static void uvc_disconnect(struct usb_interface *intf)
 	 */
 	usb_set_intfdata(intf, NULL);
 
-	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOSTREAMING)
+	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
+	    UVC_SC_VIDEOSTREAMING)
 		return;
 
 	/* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide
@@ -1687,31 +1829,36 @@ static void uvc_disconnect(struct usb_interface *intf)
 static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct uvc_device *dev = usb_get_intfdata(intf);
+	struct uvc_streaming *stream;
 
 	uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
 		intf->cur_altsetting->desc.bInterfaceNumber);
 
 	/* Controls are cached on the fly so they don't need to be saved. */
-	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL)
+	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
+	    UVC_SC_VIDEOCONTROL)
 		return uvc_status_suspend(dev);
 
-	if (dev->video.streaming->intf != intf) {
-		uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB "
-				"interface mismatch.\n");
-		return -EINVAL;
+	list_for_each_entry(stream, &dev->streams, list) {
+		if (stream->intf == intf)
+			return uvc_video_suspend(stream);
 	}
 
-	return uvc_video_suspend(&dev->video);
+	uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
+			"mismatch.\n");
+	return -EINVAL;
 }
 
 static int __uvc_resume(struct usb_interface *intf, int reset)
 {
 	struct uvc_device *dev = usb_get_intfdata(intf);
+	struct uvc_streaming *stream;
 
 	uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
 		intf->cur_altsetting->desc.bInterfaceNumber);
 
-	if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
+	if (intf->cur_altsetting->desc.bInterfaceSubClass ==
+	    UVC_SC_VIDEOCONTROL) {
 		if (reset) {
 			int ret = uvc_ctrl_resume_device(dev);
 
@@ -1722,13 +1869,14 @@ static int __uvc_resume(struct usb_interface *intf, int reset)
 		return uvc_status_resume(dev);
 	}
 
-	if (dev->video.streaming->intf != intf) {
-		uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB "
-				"interface mismatch.\n");
-		return -EINVAL;
+	list_for_each_entry(stream, &dev->streams, list) {
+		if (stream->intf == intf)
+			return uvc_video_resume(stream);
 	}
 
-	return uvc_video_resume(&dev->video);
+	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
+			"mismatch.\n");
+	return -EINVAL;
 }
 
 static int uvc_resume(struct usb_interface *intf)
@@ -1880,7 +2028,8 @@ static struct usb_device_id uvc_ids[] = {
 	  .bInterfaceClass	= USB_CLASS_VIDEO,
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
-	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
+	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
+				| UVC_QUIRK_PROBE_DEF },
 	/* Syntek (HP Spartan) */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1943,7 +2092,8 @@ static struct usb_device_id uvc_ids[] = {
 	  .bInterfaceClass	= USB_CLASS_VIDEO,
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
-	  .driver_info		= UVC_QUIRK_PROBE_EXTRAFIELDS },
+	  .driver_info		= UVC_QUIRK_PROBE_MINMAX
+				| UVC_QUIRK_PROBE_EXTRAFIELDS },
 	/* Ecamm Pico iMage */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c
index 436f462685a0..a9285b570dbe 100644
--- a/drivers/media/video/uvc/uvc_isight.c
+++ b/drivers/media/video/uvc/uvc_isight.c
@@ -99,7 +99,7 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
 	return 0;
 }
 
-void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
+void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
 		struct uvc_buffer *buf)
 {
 	int ret, i;
@@ -120,7 +120,7 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
 		 * processes the data of the first payload of the new frame.
 		 */
 		do {
-			ret = isight_decode(&video->queue, buf,
+			ret = isight_decode(&stream->queue, buf,
 					urb->transfer_buffer +
 					urb->iso_frame_desc[i].offset,
 					urb->iso_frame_desc[i].actual_length);
@@ -130,7 +130,8 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
 
 			if (buf->state == UVC_BUF_STATE_DONE ||
 			    buf->state == UVC_BUF_STATE_ERROR)
-				buf = uvc_queue_next_buffer(&video->queue, buf);
+				buf = uvc_queue_next_buffer(&stream->queue,
+							buf);
 		} while (ret == -EAGAIN);
 	}
 }
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 5e77cad29690..9e7351569b5d 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -40,7 +40,7 @@
  * table for the controls that can be mapped directly, and handle the others
  * manually.
  */
-static int uvc_v4l2_query_menu(struct uvc_video_device *video,
+static int uvc_v4l2_query_menu(struct uvc_video_chain *chain,
 	struct v4l2_querymenu *query_menu)
 {
 	struct uvc_menu_info *menu_info;
@@ -49,7 +49,7 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video,
 	u32 index = query_menu->index;
 	u32 id = query_menu->id;
 
-	ctrl = uvc_find_control(video, query_menu->id, &mapping);
+	ctrl = uvc_find_control(chain, query_menu->id, &mapping);
 	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
 		return -EINVAL;
 
@@ -103,7 +103,7 @@ static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval)
 	return interval;
 }
 
-static int uvc_v4l2_try_format(struct uvc_video_device *video,
+static int uvc_v4l2_try_format(struct uvc_streaming *stream,
 	struct v4l2_format *fmt, struct uvc_streaming_control *probe,
 	struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
 {
@@ -116,7 +116,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video,
 	int ret = 0;
 	__u8 *fcc;
 
-	if (fmt->type != video->streaming->type)
+	if (fmt->type != stream->type)
 		return -EINVAL;
 
 	fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
@@ -126,8 +126,8 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video,
 			fmt->fmt.pix.width, fmt->fmt.pix.height);
 
 	/* Check if the hardware supports the requested format. */
-	for (i = 0; i < video->streaming->nformats; ++i) {
-		format = &video->streaming->format[i];
+	for (i = 0; i < stream->nformats; ++i) {
+		format = &stream->format[i];
 		if (format->fcc == fmt->fmt.pix.pixelformat)
 			break;
 	}
@@ -191,12 +191,13 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video,
 	 * developers test their webcams with the Linux driver as well as with
 	 * the Windows driver).
 	 */
-	if (video->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
+	if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
 		probe->dwMaxVideoFrameSize =
-			video->streaming->ctrl.dwMaxVideoFrameSize;
+			stream->ctrl.dwMaxVideoFrameSize;
 
 	/* Probe the device. */
-	if ((ret = uvc_probe_video(video, probe)) < 0)
+	ret = uvc_probe_video(stream, probe);
+	if (ret < 0)
 		goto done;
 
 	fmt->fmt.pix.width = frame->wWidth;
@@ -216,13 +217,13 @@ done:
 	return ret;
 }
 
-static int uvc_v4l2_get_format(struct uvc_video_device *video,
+static int uvc_v4l2_get_format(struct uvc_streaming *stream,
 	struct v4l2_format *fmt)
 {
-	struct uvc_format *format = video->streaming->cur_format;
-	struct uvc_frame *frame = video->streaming->cur_frame;
+	struct uvc_format *format = stream->cur_format;
+	struct uvc_frame *frame = stream->cur_frame;
 
-	if (fmt->type != video->streaming->type)
+	if (fmt->type != stream->type)
 		return -EINVAL;
 
 	if (format == NULL || frame == NULL)
@@ -233,14 +234,14 @@ static int uvc_v4l2_get_format(struct uvc_video_device *video,
 	fmt->fmt.pix.height = frame->wHeight;
 	fmt->fmt.pix.field = V4L2_FIELD_NONE;
 	fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
-	fmt->fmt.pix.sizeimage = video->streaming->ctrl.dwMaxVideoFrameSize;
+	fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize;
 	fmt->fmt.pix.colorspace = format->colorspace;
 	fmt->fmt.pix.priv = 0;
 
 	return 0;
 }
 
-static int uvc_v4l2_set_format(struct uvc_video_device *video,
+static int uvc_v4l2_set_format(struct uvc_streaming *stream,
 	struct v4l2_format *fmt)
 {
 	struct uvc_streaming_control probe;
@@ -248,39 +249,39 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video,
 	struct uvc_frame *frame;
 	int ret;
 
-	if (fmt->type != video->streaming->type)
+	if (fmt->type != stream->type)
 		return -EINVAL;
 
-	if (uvc_queue_allocated(&video->queue))
+	if (uvc_queue_allocated(&stream->queue))
 		return -EBUSY;
 
-	ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame);
+	ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
 	if (ret < 0)
 		return ret;
 
-	memcpy(&video->streaming->ctrl, &probe, sizeof probe);
-	video->streaming->cur_format = format;
-	video->streaming->cur_frame = frame;
+	memcpy(&stream->ctrl, &probe, sizeof probe);
+	stream->cur_format = format;
+	stream->cur_frame = frame;
 
 	return 0;
 }
 
-static int uvc_v4l2_get_streamparm(struct uvc_video_device *video,
+static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
 		struct v4l2_streamparm *parm)
 {
 	uint32_t numerator, denominator;
 
-	if (parm->type != video->streaming->type)
+	if (parm->type != stream->type)
 		return -EINVAL;
 
-	numerator = video->streaming->ctrl.dwFrameInterval;
+	numerator = stream->ctrl.dwFrameInterval;
 	denominator = 10000000;
 	uvc_simplify_fraction(&numerator, &denominator, 8, 333);
 
 	memset(parm, 0, sizeof *parm);
-	parm->type = video->streaming->type;
+	parm->type = stream->type;
 
-	if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+	if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
 		parm->parm.capture.capturemode = 0;
 		parm->parm.capture.timeperframe.numerator = numerator;
@@ -297,19 +298,19 @@ static int uvc_v4l2_get_streamparm(struct uvc_video_device *video,
 	return 0;
 }
 
-static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
+static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
 		struct v4l2_streamparm *parm)
 {
-	struct uvc_frame *frame = video->streaming->cur_frame;
+	struct uvc_frame *frame = stream->cur_frame;
 	struct uvc_streaming_control probe;
 	struct v4l2_fract timeperframe;
 	uint32_t interval;
 	int ret;
 
-	if (parm->type != video->streaming->type)
+	if (parm->type != stream->type)
 		return -EINVAL;
 
-	if (uvc_queue_streaming(&video->queue))
+	if (uvc_queue_streaming(&stream->queue))
 		return -EBUSY;
 
 	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -317,7 +318,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
 	else
 		timeperframe = parm->parm.output.timeperframe;
 
-	memcpy(&probe, &video->streaming->ctrl, sizeof probe);
+	memcpy(&probe, &stream->ctrl, sizeof probe);
 	interval = uvc_fraction_to_interval(timeperframe.numerator,
 		timeperframe.denominator);
 
@@ -326,10 +327,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
 	probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
 
 	/* Probe the device with the new settings. */
-	if ((ret = uvc_probe_video(video, &probe)) < 0)
+	ret = uvc_probe_video(stream, &probe);
+	if (ret < 0)
 		return ret;
 
-	memcpy(&video->streaming->ctrl, &probe, sizeof probe);
+	memcpy(&stream->ctrl, &probe, sizeof probe);
 
 	/* Return the actual frame period. */
 	timeperframe.numerator = probe.dwFrameInterval;
@@ -382,8 +384,8 @@ static int uvc_acquire_privileges(struct uvc_fh *handle)
 
 	/* Check if the device already has a privileged handle. */
 	mutex_lock(&uvc_driver.open_mutex);
-	if (atomic_inc_return(&handle->device->active) != 1) {
-		atomic_dec(&handle->device->active);
+	if (atomic_inc_return(&handle->stream->active) != 1) {
+		atomic_dec(&handle->stream->active);
 		ret = -EBUSY;
 		goto done;
 	}
@@ -398,7 +400,7 @@ done:
 static void uvc_dismiss_privileges(struct uvc_fh *handle)
 {
 	if (handle->state == UVC_HANDLE_ACTIVE)
-		atomic_dec(&handle->device->active);
+		atomic_dec(&handle->stream->active);
 
 	handle->state = UVC_HANDLE_PASSIVE;
 }
@@ -414,45 +416,47 @@ static int uvc_has_privileges(struct uvc_fh *handle)
 
 static int uvc_v4l2_open(struct file *file)
 {
-	struct uvc_video_device *video;
+	struct uvc_streaming *stream;
 	struct uvc_fh *handle;
 	int ret = 0;
 
 	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
 	mutex_lock(&uvc_driver.open_mutex);
-	video = video_drvdata(file);
+	stream = video_drvdata(file);
 
-	if (video->dev->state & UVC_DEV_DISCONNECTED) {
+	if (stream->dev->state & UVC_DEV_DISCONNECTED) {
 		ret = -ENODEV;
 		goto done;
 	}
 
-	ret = usb_autopm_get_interface(video->dev->intf);
+	ret = usb_autopm_get_interface(stream->dev->intf);
 	if (ret < 0)
 		goto done;
 
 	/* Create the device handle. */
 	handle = kzalloc(sizeof *handle, GFP_KERNEL);
 	if (handle == NULL) {
-		usb_autopm_put_interface(video->dev->intf);
+		usb_autopm_put_interface(stream->dev->intf);
 		ret = -ENOMEM;
 		goto done;
 	}
 
-	if (atomic_inc_return(&video->dev->users) == 1) {
-		if ((ret = uvc_status_start(video->dev)) < 0) {
-			usb_autopm_put_interface(video->dev->intf);
-			atomic_dec(&video->dev->users);
+	if (atomic_inc_return(&stream->dev->users) == 1) {
+		ret = uvc_status_start(stream->dev);
+		if (ret < 0) {
+			usb_autopm_put_interface(stream->dev->intf);
+			atomic_dec(&stream->dev->users);
 			kfree(handle);
 			goto done;
 		}
 	}
 
-	handle->device = video;
+	handle->chain = stream->chain;
+	handle->stream = stream;
 	handle->state = UVC_HANDLE_PASSIVE;
 	file->private_data = handle;
 
-	kref_get(&video->dev->kref);
+	kref_get(&stream->dev->kref);
 
 done:
 	mutex_unlock(&uvc_driver.open_mutex);
@@ -461,20 +465,20 @@ done:
 
 static int uvc_v4l2_release(struct file *file)
 {
-	struct uvc_video_device *video = video_drvdata(file);
 	struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
+	struct uvc_streaming *stream = handle->stream;
 
 	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
 
 	/* Only free resources if this is a privileged handle. */
 	if (uvc_has_privileges(handle)) {
-		uvc_video_enable(video, 0);
+		uvc_video_enable(stream, 0);
 
-		mutex_lock(&video->queue.mutex);
-		if (uvc_free_buffers(&video->queue) < 0)
+		mutex_lock(&stream->queue.mutex);
+		if (uvc_free_buffers(&stream->queue) < 0)
 			uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
 					"free buffers.\n");
-		mutex_unlock(&video->queue.mutex);
+		mutex_unlock(&stream->queue.mutex);
 	}
 
 	/* Release the file handle. */
@@ -482,19 +486,20 @@ static int uvc_v4l2_release(struct file *file)
 	kfree(handle);
 	file->private_data = NULL;
 
-	if (atomic_dec_return(&video->dev->users) == 0)
-		uvc_status_stop(video->dev);
+	if (atomic_dec_return(&stream->dev->users) == 0)
+		uvc_status_stop(stream->dev);
 
-	usb_autopm_put_interface(video->dev->intf);
-	kref_put(&video->dev->kref, uvc_delete);
+	usb_autopm_put_interface(stream->dev->intf);
+	kref_put(&stream->dev->kref, uvc_delete);
 	return 0;
 }
 
 static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *vdev = video_devdata(file);
-	struct uvc_video_device *video = video_get_drvdata(vdev);
 	struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
+	struct uvc_video_chain *chain = handle->chain;
+	struct uvc_streaming *stream = handle->stream;
 	long ret = 0;
 
 	switch (cmd) {
@@ -506,10 +511,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		memset(cap, 0, sizeof *cap);
 		strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
 		strlcpy(cap->card, vdev->name, sizeof cap->card);
-		usb_make_path(video->dev->udev,
+		usb_make_path(stream->dev->udev,
 			      cap->bus_info, sizeof(cap->bus_info));
 		cap->version = DRIVER_VERSION_NUMBER;
-		if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 			cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
 					  | V4L2_CAP_STREAMING;
 		else
@@ -520,7 +525,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
 	/* Get, Set & Query control */
 	case VIDIOC_QUERYCTRL:
-		return uvc_query_v4l2_ctrl(video, arg);
+		return uvc_query_v4l2_ctrl(chain, arg);
 
 	case VIDIOC_G_CTRL:
 	{
@@ -530,12 +535,12 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		memset(&xctrl, 0, sizeof xctrl);
 		xctrl.id = ctrl->id;
 
-	       ret = uvc_ctrl_begin(video);
-	       if (ret < 0)
+		ret = uvc_ctrl_begin(chain);
+		if (ret < 0)
 			return ret;
 
-		ret = uvc_ctrl_get(video, &xctrl);
-		uvc_ctrl_rollback(video);
+		ret = uvc_ctrl_get(chain, &xctrl);
+		uvc_ctrl_rollback(chain);
 		if (ret >= 0)
 			ctrl->value = xctrl.value;
 		break;
@@ -550,21 +555,21 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		xctrl.id = ctrl->id;
 		xctrl.value = ctrl->value;
 
-	       ret = uvc_ctrl_begin(video);
-	       if (ret < 0)
+		uvc_ctrl_begin(chain);
+		if (ret < 0)
 			return ret;
 
-		ret = uvc_ctrl_set(video, &xctrl);
+		ret = uvc_ctrl_set(chain, &xctrl);
 		if (ret < 0) {
-			uvc_ctrl_rollback(video);
+			uvc_ctrl_rollback(chain);
 			return ret;
 		}
-		ret = uvc_ctrl_commit(video);
+		ret = uvc_ctrl_commit(chain);
 		break;
 	}
 
 	case VIDIOC_QUERYMENU:
-		return uvc_v4l2_query_menu(video, arg);
+		return uvc_v4l2_query_menu(chain, arg);
 
 	case VIDIOC_G_EXT_CTRLS:
 	{
@@ -572,20 +577,20 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		struct v4l2_ext_control *ctrl = ctrls->controls;
 		unsigned int i;
 
-	       ret = uvc_ctrl_begin(video);
-	       if (ret < 0)
+		ret = uvc_ctrl_begin(chain);
+		if (ret < 0)
 			return ret;
 
 		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-			ret = uvc_ctrl_get(video, ctrl);
+			ret = uvc_ctrl_get(chain, ctrl);
 			if (ret < 0) {
-				uvc_ctrl_rollback(video);
+				uvc_ctrl_rollback(chain);
 				ctrls->error_idx = i;
 				return ret;
 			}
 		}
 		ctrls->error_idx = 0;
-		ret = uvc_ctrl_rollback(video);
+		ret = uvc_ctrl_rollback(chain);
 		break;
 	}
 
@@ -596,14 +601,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		struct v4l2_ext_control *ctrl = ctrls->controls;
 		unsigned int i;
 
-		ret = uvc_ctrl_begin(video);
+		ret = uvc_ctrl_begin(chain);
 		if (ret < 0)
 			return ret;
 
 		for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-			ret = uvc_ctrl_set(video, ctrl);
+			ret = uvc_ctrl_set(chain, ctrl);
 			if (ret < 0) {
-				uvc_ctrl_rollback(video);
+				uvc_ctrl_rollback(chain);
 				ctrls->error_idx = i;
 				return ret;
 			}
@@ -612,31 +617,31 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		ctrls->error_idx = 0;
 
 		if (cmd == VIDIOC_S_EXT_CTRLS)
-			ret = uvc_ctrl_commit(video);
+			ret = uvc_ctrl_commit(chain);
 		else
-			ret = uvc_ctrl_rollback(video);
+			ret = uvc_ctrl_rollback(chain);
 		break;
 	}
 
 	/* Get, Set & Enum input */
 	case VIDIOC_ENUMINPUT:
 	{
-		const struct uvc_entity *selector = video->selector;
+		const struct uvc_entity *selector = chain->selector;
 		struct v4l2_input *input = arg;
 		struct uvc_entity *iterm = NULL;
 		u32 index = input->index;
 		int pin = 0;
 
 		if (selector == NULL ||
-		    (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
 			if (index != 0)
 				return -EINVAL;
-			iterm = list_first_entry(&video->iterms,
+			iterm = list_first_entry(&chain->iterms,
 					struct uvc_entity, chain);
 			pin = iterm->id;
 		} else if (pin < selector->selector.bNrInPins) {
 			pin = selector->selector.baSourceID[index];
-			list_for_each_entry(iterm, video->iterms.next, chain) {
+			list_for_each_entry(iterm, chain->iterms.next, chain) {
 				if (iterm->id == pin)
 					break;
 			}
@@ -648,7 +653,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		memset(input, 0, sizeof *input);
 		input->index = index;
 		strlcpy(input->name, iterm->name, sizeof input->name);
-		if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA)
+		if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
 			input->type = V4L2_INPUT_TYPE_CAMERA;
 		break;
 	}
@@ -657,15 +662,15 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		u8 input;
 
-		if (video->selector == NULL ||
-		    (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+		if (chain->selector == NULL ||
+		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
 			*(int *)arg = 0;
 			break;
 		}
 
-		ret = uvc_query_ctrl(video->dev, GET_CUR, video->selector->id,
-			video->dev->intfnum, SU_INPUT_SELECT_CONTROL,
-			&input, 1);
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+			chain->selector->id, chain->dev->intfnum,
+			UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
 		if (ret < 0)
 			return ret;
 
@@ -680,19 +685,19 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		if ((ret = uvc_acquire_privileges(handle)) < 0)
 			return ret;
 
-		if (video->selector == NULL ||
-		    (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+		if (chain->selector == NULL ||
+		    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
 			if (input != 1)
 				return -EINVAL;
 			break;
 		}
 
-		if (input == 0 || input > video->selector->selector.bNrInPins)
+		if (input == 0 || input > chain->selector->selector.bNrInPins)
 			return -EINVAL;
 
-		return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id,
-			video->dev->intfnum, SU_INPUT_SELECT_CONTROL,
-			&input, 1);
+		return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
+			chain->selector->id, chain->dev->intfnum,
+			UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
 	}
 
 	/* Try, Get, Set & Enum format */
@@ -703,15 +708,15 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		enum v4l2_buf_type type = fmt->type;
 		__u32 index = fmt->index;
 
-		if (fmt->type != video->streaming->type ||
-		    fmt->index >= video->streaming->nformats)
+		if (fmt->type != stream->type ||
+		    fmt->index >= stream->nformats)
 			return -EINVAL;
 
 		memset(fmt, 0, sizeof(*fmt));
 		fmt->index = index;
 		fmt->type = type;
 
-		format = &video->streaming->format[fmt->index];
+		format = &stream->format[fmt->index];
 		fmt->flags = 0;
 		if (format->flags & UVC_FMT_FLAG_COMPRESSED)
 			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
@@ -729,17 +734,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		if ((ret = uvc_acquire_privileges(handle)) < 0)
 			return ret;
 
-		return uvc_v4l2_try_format(video, arg, &probe, NULL, NULL);
+		return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
 	}
 
 	case VIDIOC_S_FMT:
 		if ((ret = uvc_acquire_privileges(handle)) < 0)
 			return ret;
 
-		return uvc_v4l2_set_format(video, arg);
+		return uvc_v4l2_set_format(stream, arg);
 
 	case VIDIOC_G_FMT:
-		return uvc_v4l2_get_format(video, arg);
+		return uvc_v4l2_get_format(stream, arg);
 
 	/* Frame size enumeration */
 	case VIDIOC_ENUM_FRAMESIZES:
@@ -750,10 +755,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		int i;
 
 		/* Look for the given pixel format */
-		for (i = 0; i < video->streaming->nformats; i++) {
-			if (video->streaming->format[i].fcc ==
+		for (i = 0; i < stream->nformats; i++) {
+			if (stream->format[i].fcc ==
 					fsize->pixel_format) {
-				format = &video->streaming->format[i];
+				format = &stream->format[i];
 				break;
 			}
 		}
@@ -779,10 +784,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 		int i;
 
 		/* Look for the given pixel format and frame size */
-		for (i = 0; i < video->streaming->nformats; i++) {
-			if (video->streaming->format[i].fcc ==
+		for (i = 0; i < stream->nformats; i++) {
+			if (stream->format[i].fcc ==
 					fival->pixel_format) {
-				format = &video->streaming->format[i];
+				format = &stream->format[i];
 				break;
 			}
 		}
@@ -832,21 +837,21 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
 	/* Get & Set streaming parameters */
 	case VIDIOC_G_PARM:
-		return uvc_v4l2_get_streamparm(video, arg);
+		return uvc_v4l2_get_streamparm(stream, arg);
 
 	case VIDIOC_S_PARM:
 		if ((ret = uvc_acquire_privileges(handle)) < 0)
 			return ret;
 
-		return uvc_v4l2_set_streamparm(video, arg);
+		return uvc_v4l2_set_streamparm(stream, arg);
 
 	/* Cropping and scaling */
 	case VIDIOC_CROPCAP:
 	{
 		struct v4l2_cropcap *ccap = arg;
-		struct uvc_frame *frame = video->streaming->cur_frame;
+		struct uvc_frame *frame = stream->cur_frame;
 
-		if (ccap->type != video->streaming->type)
+		if (ccap->type != stream->type)
 			return -EINVAL;
 
 		ccap->bounds.left = 0;
@@ -870,16 +875,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		struct v4l2_requestbuffers *rb = arg;
 		unsigned int bufsize =
-			video->streaming->ctrl.dwMaxVideoFrameSize;
+			stream->ctrl.dwMaxVideoFrameSize;
 
-		if (rb->type != video->streaming->type ||
+		if (rb->type != stream->type ||
 		    rb->memory != V4L2_MEMORY_MMAP)
 			return -EINVAL;
 
 		if ((ret = uvc_acquire_privileges(handle)) < 0)
 			return ret;
 
-		ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize);
+		ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize);
 		if (ret < 0)
 			return ret;
 
@@ -892,39 +897,40 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		struct v4l2_buffer *buf = arg;
 
-		if (buf->type != video->streaming->type)
+		if (buf->type != stream->type)
 			return -EINVAL;
 
 		if (!uvc_has_privileges(handle))
 			return -EBUSY;
 
-		return uvc_query_buffer(&video->queue, buf);
+		return uvc_query_buffer(&stream->queue, buf);
 	}
 
 	case VIDIOC_QBUF:
 		if (!uvc_has_privileges(handle))
 			return -EBUSY;
 
-		return uvc_queue_buffer(&video->queue, arg);
+		return uvc_queue_buffer(&stream->queue, arg);
 
 	case VIDIOC_DQBUF:
 		if (!uvc_has_privileges(handle))
 			return -EBUSY;
 
-		return uvc_dequeue_buffer(&video->queue, arg,
+		return uvc_dequeue_buffer(&stream->queue, arg,
 			file->f_flags & O_NONBLOCK);
 
 	case VIDIOC_STREAMON:
 	{
 		int *type = arg;
 
-		if (*type != video->streaming->type)
+		if (*type != stream->type)
 			return -EINVAL;
 
 		if (!uvc_has_privileges(handle))
 			return -EBUSY;
 
-		if ((ret = uvc_video_enable(video, 1)) < 0)
+		ret = uvc_video_enable(stream, 1);
+		if (ret < 0)
 			return ret;
 		break;
 	}
@@ -933,13 +939,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	{
 		int *type = arg;
 
-		if (*type != video->streaming->type)
+		if (*type != stream->type)
 			return -EINVAL;
 
 		if (!uvc_has_privileges(handle))
 			return -EBUSY;
 
-		return uvc_video_enable(video, 0);
+		return uvc_video_enable(stream, 0);
 	}
 
 	/* Analog video standards make no sense for digital cameras. */
@@ -1013,10 +1019,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	}
 
 	case UVCIOC_CTRL_GET:
-		return uvc_xu_ctrl_query(video, arg, 0);
+		return uvc_xu_ctrl_query(chain, arg, 0);
 
 	case UVCIOC_CTRL_SET:
-		return uvc_xu_ctrl_query(video, arg, 1);
+		return uvc_xu_ctrl_query(chain, arg, 1);
 
 	default:
 		if ((ret = v4l_compat_translate_ioctl(file, cmd, arg,
@@ -1070,7 +1076,9 @@ static struct vm_operations_struct uvc_vm_ops = {
 
 static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct uvc_video_device *video = video_drvdata(file);
+	struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
+	struct uvc_streaming *stream = handle->stream;
+	struct uvc_video_queue *queue = &stream->queue;
 	struct uvc_buffer *uninitialized_var(buffer);
 	struct page *page;
 	unsigned long addr, start, size;
@@ -1082,15 +1090,15 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 	start = vma->vm_start;
 	size = vma->vm_end - vma->vm_start;
 
-	mutex_lock(&video->queue.mutex);
+	mutex_lock(&queue->mutex);
 
-	for (i = 0; i < video->queue.count; ++i) {
-		buffer = &video->queue.buffer[i];
+	for (i = 0; i < queue->count; ++i) {
+		buffer = &queue->buffer[i];
 		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
 			break;
 	}
 
-	if (i == video->queue.count || size != video->queue.buf_size) {
+	if (i == queue->count || size != queue->buf_size) {
 		ret = -EINVAL;
 		goto done;
 	}
@@ -1101,7 +1109,7 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 	 */
 	vma->vm_flags |= VM_IO;
 
-	addr = (unsigned long)video->queue.mem + buffer->buf.m.offset;
+	addr = (unsigned long)queue->mem + buffer->buf.m.offset;
 	while (size > 0) {
 		page = vmalloc_to_page((void *)addr);
 		if ((ret = vm_insert_page(vma, start, page)) < 0)
@@ -1117,17 +1125,18 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 	uvc_vm_open(vma);
 
 done:
-	mutex_unlock(&video->queue.mutex);
+	mutex_unlock(&queue->mutex);
 	return ret;
 }
 
 static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
 {
-	struct uvc_video_device *video = video_drvdata(file);
+	struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
+	struct uvc_streaming *stream = handle->stream;
 
 	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
 
-	return uvc_queue_poll(&video->queue, file, wait);
+	return uvc_queue_poll(&stream->queue, file, wait);
 }
 
 const struct v4l2_file_operations uvc_fops = {
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 01b633c73480..5b757f32d997 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
 	return 0;
 }
 
-static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
+static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl)
 {
 	struct uvc_format *format;
@@ -69,10 +69,10 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
 	unsigned int i;
 
 	if (ctrl->bFormatIndex <= 0 ||
-	    ctrl->bFormatIndex > video->streaming->nformats)
+	    ctrl->bFormatIndex > stream->nformats)
 		return;
 
-	format = &video->streaming->format[ctrl->bFormatIndex - 1];
+	format = &stream->format[ctrl->bFormatIndex - 1];
 
 	for (i = 0; i < format->nframes; ++i) {
 		if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
@@ -86,12 +86,12 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
 
 	if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
 	     (ctrl->dwMaxVideoFrameSize == 0 &&
-	      video->dev->uvc_version < 0x0110))
+	      stream->dev->uvc_version < 0x0110))
 		ctrl->dwMaxVideoFrameSize =
 			frame->dwMaxVideoFrameBufferSize;
 
-	if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
-	    video->streaming->intf->num_altsetting > 1) {
+	if (stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
+	    stream->intf->num_altsetting > 1) {
 		u32 interval;
 		u32 bandwidth;
 
@@ -108,7 +108,7 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
 		bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
 		bandwidth *= 10000000 / interval + 1;
 		bandwidth /= 1000;
-		if (video->dev->udev->speed == USB_SPEED_HIGH)
+		if (stream->dev->udev->speed == USB_SPEED_HIGH)
 			bandwidth /= 8;
 		bandwidth += 12;
 
@@ -116,40 +116,43 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
 	}
 }
 
-static int uvc_get_video_ctrl(struct uvc_video_device *video,
+static int uvc_get_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl, int probe, __u8 query)
 {
 	__u8 *data;
 	__u16 size;
 	int ret;
 
-	size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
+	size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
 	data = kmalloc(size, GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
 
-	ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
-		probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
-		UVC_CTRL_STREAMING_TIMEOUT);
+	if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF)
+		return -EIO;
+
+	ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum,
+		probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data,
+		size, UVC_CTRL_STREAMING_TIMEOUT);
 
-	if ((query == GET_MIN || query == GET_MAX) && ret == 2) {
+	if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) {
 		/* Some cameras, mostly based on Bison Electronics chipsets,
 		 * answer a GET_MIN or GET_MAX request with the wCompQuality
 		 * field only.
 		 */
-		uvc_warn_once(video->dev, UVC_WARN_MINMAX, "UVC non "
+		uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non "
 			"compliance - GET_MIN/MAX(PROBE) incorrectly "
 			"supported. Enabling workaround.\n");
 		memset(ctrl, 0, sizeof ctrl);
 		ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
 		ret = 0;
 		goto out;
-	} else if (query == GET_DEF && probe == 1 && ret != size) {
+	} else if (query == UVC_GET_DEF && probe == 1 && ret != size) {
 		/* Many cameras don't support the GET_DEF request on their
 		 * video probe control. Warn once and return, the caller will
 		 * fall back to GET_CUR.
 		 */
-		uvc_warn_once(video->dev, UVC_WARN_PROBE_DEF, "UVC non "
+		uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non "
 			"compliance - GET_DEF(PROBE) not supported. "
 			"Enabling workaround.\n");
 		ret = -EIO;
@@ -181,7 +184,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
 		ctrl->bMinVersion = data[32];
 		ctrl->bMaxVersion = data[33];
 	} else {
-		ctrl->dwClockFrequency = video->dev->clock_frequency;
+		ctrl->dwClockFrequency = stream->dev->clock_frequency;
 		ctrl->bmFramingInfo = 0;
 		ctrl->bPreferedVersion = 0;
 		ctrl->bMinVersion = 0;
@@ -192,7 +195,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
 	 * dwMaxPayloadTransferSize fields. Try to get the value from the
 	 * format and frame descriptors.
 	 */
-	uvc_fixup_video_ctrl(video, ctrl);
+	uvc_fixup_video_ctrl(stream, ctrl);
 	ret = 0;
 
 out:
@@ -200,14 +203,14 @@ out:
 	return ret;
 }
 
-static int uvc_set_video_ctrl(struct uvc_video_device *video,
+static int uvc_set_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl, int probe)
 {
 	__u8 *data;
 	__u16 size;
 	int ret;
 
-	size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
+	size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
 	data = kzalloc(size, GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
@@ -232,10 +235,9 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video,
 		data[33] = ctrl->bMaxVersion;
 	}
 
-	ret = __uvc_query_ctrl(video->dev, SET_CUR, 0,
-		video->streaming->intfnum,
-		probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
-		UVC_CTRL_STREAMING_TIMEOUT);
+	ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum,
+		probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data,
+		size, UVC_CTRL_STREAMING_TIMEOUT);
 	if (ret != size) {
 		uvc_printk(KERN_ERR, "Failed to set UVC %s control : "
 			"%d (exp. %u).\n", probe ? "probe" : "commit",
@@ -247,7 +249,7 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video,
 	return ret;
 }
 
-int uvc_probe_video(struct uvc_video_device *video,
+int uvc_probe_video(struct uvc_streaming *stream,
 	struct uvc_streaming_control *probe)
 {
 	struct uvc_streaming_control probe_min, probe_max;
@@ -255,7 +257,7 @@ int uvc_probe_video(struct uvc_video_device *video,
 	unsigned int i;
 	int ret;
 
-	mutex_lock(&video->streaming->mutex);
+	mutex_lock(&stream->mutex);
 
 	/* Perform probing. The device should adjust the requested values
 	 * according to its capabilities. However, some devices, namely the
@@ -264,15 +266,16 @@ int uvc_probe_video(struct uvc_video_device *video,
 	 * that reason, if the needed bandwidth exceeds the maximum available
 	 * bandwidth, try to lower the quality.
 	 */
-	if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0)
+	ret = uvc_set_video_ctrl(stream, probe, 1);
+	if (ret < 0)
 		goto done;
 
 	/* Get the minimum and maximum values for compression settings. */
-	if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) {
-		ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN);
+	if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) {
+		ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN);
 		if (ret < 0)
 			goto done;
-		ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX);
+		ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX);
 		if (ret < 0)
 			goto done;
 
@@ -280,18 +283,21 @@ int uvc_probe_video(struct uvc_video_device *video,
 	}
 
 	for (i = 0; i < 2; ++i) {
-		if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0 ||
-		    (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
+		ret = uvc_set_video_ctrl(stream, probe, 1);
+		if (ret < 0)
+			goto done;
+		ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);
+		if (ret < 0)
 			goto done;
 
-		if (video->streaming->intf->num_altsetting == 1)
+		if (stream->intf->num_altsetting == 1)
 			break;
 
 		bandwidth = probe->dwMaxPayloadTransferSize;
-		if (bandwidth <= video->streaming->maxpsize)
+		if (bandwidth <= stream->maxpsize)
 			break;
 
-		if (video->dev->quirks & UVC_QUIRK_PROBE_MINMAX) {
+		if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) {
 			ret = -ENOSPC;
 			goto done;
 		}
@@ -304,14 +310,14 @@ int uvc_probe_video(struct uvc_video_device *video,
 	}
 
 done:
-	mutex_unlock(&video->streaming->mutex);
+	mutex_unlock(&stream->mutex);
 	return ret;
 }
 
-int uvc_commit_video(struct uvc_video_device *video,
+int uvc_commit_video(struct uvc_streaming *stream,
 	struct uvc_streaming_control *probe)
 {
-	return uvc_set_video_ctrl(video, probe, 0);
+	return uvc_set_video_ctrl(stream, probe, 0);
 }
 
 /* ------------------------------------------------------------------------
@@ -363,7 +369,7 @@ int uvc_commit_video(struct uvc_video_device *video,
  * to be called with a NULL buf parameter. uvc_video_decode_data and
  * uvc_video_decode_end will never be called with a NULL buffer.
  */
-static int uvc_video_decode_start(struct uvc_video_device *video,
+static int uvc_video_decode_start(struct uvc_streaming *stream,
 		struct uvc_buffer *buf, const __u8 *data, int len)
 {
 	__u8 fid;
@@ -389,25 +395,25 @@ static int uvc_video_decode_start(struct uvc_video_device *video,
 	 * NULL.
 	 */
 	if (buf == NULL) {
-		video->last_fid = fid;
+		stream->last_fid = fid;
 		return -ENODATA;
 	}
 
 	/* Synchronize to the input stream by waiting for the FID bit to be
 	 * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
-	 * video->last_fid is initialized to -1, so the first isochronous
+	 * stream->last_fid is initialized to -1, so the first isochronous
 	 * frame will always be in sync.
 	 *
-	 * If the device doesn't toggle the FID bit, invert video->last_fid
+	 * If the device doesn't toggle the FID bit, invert stream->last_fid
 	 * when the EOF bit is set to force synchronisation on the next packet.
 	 */
 	if (buf->state != UVC_BUF_STATE_ACTIVE) {
-		if (fid == video->last_fid) {
+		if (fid == stream->last_fid) {
 			uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of "
 				"sync).\n");
-			if ((video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) &&
+			if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) &&
 			    (data[1] & UVC_STREAM_EOF))
-				video->last_fid ^= UVC_STREAM_FID;
+				stream->last_fid ^= UVC_STREAM_FID;
 			return -ENODATA;
 		}
 
@@ -422,7 +428,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video,
 	 * last payload can be lost anyway). We thus must check if the FID has
 	 * been toggled.
 	 *
-	 * video->last_fid is initialized to -1, so the first isochronous
+	 * stream->last_fid is initialized to -1, so the first isochronous
 	 * frame will never trigger an end of frame detection.
 	 *
 	 * Empty buffers (bytesused == 0) don't trigger end of frame detection
@@ -430,22 +436,22 @@ static int uvc_video_decode_start(struct uvc_video_device *video,
 	 * avoids detecting end of frame conditions at FID toggling if the
 	 * previous payload had the EOF bit set.
 	 */
-	if (fid != video->last_fid && buf->buf.bytesused != 0) {
+	if (fid != stream->last_fid && buf->buf.bytesused != 0) {
 		uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
 				"toggled).\n");
 		buf->state = UVC_BUF_STATE_DONE;
 		return -EAGAIN;
 	}
 
-	video->last_fid = fid;
+	stream->last_fid = fid;
 
 	return data[0];
 }
 
-static void uvc_video_decode_data(struct uvc_video_device *video,
+static void uvc_video_decode_data(struct uvc_streaming *stream,
 		struct uvc_buffer *buf, const __u8 *data, int len)
 {
-	struct uvc_video_queue *queue = &video->queue;
+	struct uvc_video_queue *queue = &stream->queue;
 	unsigned int maxlen, nbytes;
 	void *mem;
 
@@ -466,7 +472,7 @@ static void uvc_video_decode_data(struct uvc_video_device *video,
 	}
 }
 
-static void uvc_video_decode_end(struct uvc_video_device *video,
+static void uvc_video_decode_end(struct uvc_streaming *stream,
 		struct uvc_buffer *buf, const __u8 *data, int len)
 {
 	/* Mark the buffer as done if the EOF marker is set. */
@@ -475,8 +481,8 @@ static void uvc_video_decode_end(struct uvc_video_device *video,
 		if (data[0] == len)
 			uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
 		buf->state = UVC_BUF_STATE_DONE;
-		if (video->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
-			video->last_fid ^= UVC_STREAM_FID;
+		if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
+			stream->last_fid ^= UVC_STREAM_FID;
 	}
 }
 
@@ -491,26 +497,26 @@ static void uvc_video_decode_end(struct uvc_video_device *video,
  * uvc_video_encode_data is called for every URB and copies the data from the
  * video buffer to the transfer buffer.
  */
-static int uvc_video_encode_header(struct uvc_video_device *video,
+static int uvc_video_encode_header(struct uvc_streaming *stream,
 		struct uvc_buffer *buf, __u8 *data, int len)
 {
 	data[0] = 2;	/* Header length */
 	data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF
-		| (video->last_fid & UVC_STREAM_FID);
+		| (stream->last_fid & UVC_STREAM_FID);
 	return 2;
 }
 
-static int uvc_video_encode_data(struct uvc_video_device *video,
+static int uvc_video_encode_data(struct uvc_streaming *stream,
 		struct uvc_buffer *buf, __u8 *data, int len)
 {
-	struct uvc_video_queue *queue = &video->queue;
+	struct uvc_video_queue *queue = &stream->queue;
 	unsigned int nbytes;
 	void *mem;
 
 	/* Copy video data to the URB buffer. */
 	mem = queue->mem + buf->buf.m.offset + queue->buf_used;
 	nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
-	nbytes = min(video->bulk.max_payload_size - video->bulk.payload_size,
+	nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size,
 			nbytes);
 	memcpy(data, mem, nbytes);
 
@@ -526,8 +532,8 @@ static int uvc_video_encode_data(struct uvc_video_device *video,
 /*
  * Completion handler for video URBs.
  */
-static void uvc_video_decode_isoc(struct urb *urb,
-	struct uvc_video_device *video, struct uvc_buffer *buf)
+static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
+	struct uvc_buffer *buf)
 {
 	u8 *mem;
 	int ret, i;
@@ -542,31 +548,32 @@ static void uvc_video_decode_isoc(struct urb *urb,
 		/* Decode the payload header. */
 		mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 		do {
-			ret = uvc_video_decode_start(video, buf, mem,
+			ret = uvc_video_decode_start(stream, buf, mem,
 				urb->iso_frame_desc[i].actual_length);
 			if (ret == -EAGAIN)
-				buf = uvc_queue_next_buffer(&video->queue, buf);
+				buf = uvc_queue_next_buffer(&stream->queue,
+							    buf);
 		} while (ret == -EAGAIN);
 
 		if (ret < 0)
 			continue;
 
 		/* Decode the payload data. */
-		uvc_video_decode_data(video, buf, mem + ret,
+		uvc_video_decode_data(stream, buf, mem + ret,
 			urb->iso_frame_desc[i].actual_length - ret);
 
 		/* Process the header again. */
-		uvc_video_decode_end(video, buf, mem,
+		uvc_video_decode_end(stream, buf, mem,
 			urb->iso_frame_desc[i].actual_length);
 
 		if (buf->state == UVC_BUF_STATE_DONE ||
 		    buf->state == UVC_BUF_STATE_ERROR)
-			buf = uvc_queue_next_buffer(&video->queue, buf);
+			buf = uvc_queue_next_buffer(&stream->queue, buf);
 	}
 }
 
-static void uvc_video_decode_bulk(struct urb *urb,
-	struct uvc_video_device *video, struct uvc_buffer *buf)
+static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream,
+	struct uvc_buffer *buf)
 {
 	u8 *mem;
 	int len, ret;
@@ -576,24 +583,25 @@ static void uvc_video_decode_bulk(struct urb *urb,
 
 	mem = urb->transfer_buffer;
 	len = urb->actual_length;
-	video->bulk.payload_size += len;
+	stream->bulk.payload_size += len;
 
 	/* If the URB is the first of its payload, decode and save the
 	 * header.
 	 */
-	if (video->bulk.header_size == 0 && !video->bulk.skip_payload) {
+	if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) {
 		do {
-			ret = uvc_video_decode_start(video, buf, mem, len);
+			ret = uvc_video_decode_start(stream, buf, mem, len);
 			if (ret == -EAGAIN)
-				buf = uvc_queue_next_buffer(&video->queue, buf);
+				buf = uvc_queue_next_buffer(&stream->queue,
+							    buf);
 		} while (ret == -EAGAIN);
 
 		/* If an error occured skip the rest of the payload. */
 		if (ret < 0 || buf == NULL) {
-			video->bulk.skip_payload = 1;
+			stream->bulk.skip_payload = 1;
 		} else {
-			memcpy(video->bulk.header, mem, ret);
-			video->bulk.header_size = ret;
+			memcpy(stream->bulk.header, mem, ret);
+			stream->bulk.header_size = ret;
 
 			mem += ret;
 			len -= ret;
@@ -606,33 +614,34 @@ static void uvc_video_decode_bulk(struct urb *urb,
 	 */
 
 	/* Process video data. */
-	if (!video->bulk.skip_payload && buf != NULL)
-		uvc_video_decode_data(video, buf, mem, len);
+	if (!stream->bulk.skip_payload && buf != NULL)
+		uvc_video_decode_data(stream, buf, mem, len);
 
 	/* Detect the payload end by a URB smaller than the maximum size (or
 	 * a payload size equal to the maximum) and process the header again.
 	 */
 	if (urb->actual_length < urb->transfer_buffer_length ||
-	    video->bulk.payload_size >= video->bulk.max_payload_size) {
-		if (!video->bulk.skip_payload && buf != NULL) {
-			uvc_video_decode_end(video, buf, video->bulk.header,
-				video->bulk.payload_size);
+	    stream->bulk.payload_size >= stream->bulk.max_payload_size) {
+		if (!stream->bulk.skip_payload && buf != NULL) {
+			uvc_video_decode_end(stream, buf, stream->bulk.header,
+				stream->bulk.payload_size);
 			if (buf->state == UVC_BUF_STATE_DONE ||
 			    buf->state == UVC_BUF_STATE_ERROR)
-				buf = uvc_queue_next_buffer(&video->queue, buf);
+				buf = uvc_queue_next_buffer(&stream->queue,
+							    buf);
 		}
 
-		video->bulk.header_size = 0;
-		video->bulk.skip_payload = 0;
-		video->bulk.payload_size = 0;
+		stream->bulk.header_size = 0;
+		stream->bulk.skip_payload = 0;
+		stream->bulk.payload_size = 0;
 	}
 }
 
-static void uvc_video_encode_bulk(struct urb *urb,
-	struct uvc_video_device *video, struct uvc_buffer *buf)
+static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
+	struct uvc_buffer *buf)
 {
 	u8 *mem = urb->transfer_buffer;
-	int len = video->urb_size, ret;
+	int len = stream->urb_size, ret;
 
 	if (buf == NULL) {
 		urb->transfer_buffer_length = 0;
@@ -640,40 +649,40 @@ static void uvc_video_encode_bulk(struct urb *urb,
 	}
 
 	/* If the URB is the first of its payload, add the header. */
-	if (video->bulk.header_size == 0) {
-		ret = uvc_video_encode_header(video, buf, mem, len);
-		video->bulk.header_size = ret;
-		video->bulk.payload_size += ret;
+	if (stream->bulk.header_size == 0) {
+		ret = uvc_video_encode_header(stream, buf, mem, len);
+		stream->bulk.header_size = ret;
+		stream->bulk.payload_size += ret;
 		mem += ret;
 		len -= ret;
 	}
 
 	/* Process video data. */
-	ret = uvc_video_encode_data(video, buf, mem, len);
+	ret = uvc_video_encode_data(stream, buf, mem, len);
 
-	video->bulk.payload_size += ret;
+	stream->bulk.payload_size += ret;
 	len -= ret;
 
-	if (buf->buf.bytesused == video->queue.buf_used ||
-	    video->bulk.payload_size == video->bulk.max_payload_size) {
-		if (buf->buf.bytesused == video->queue.buf_used) {
-			video->queue.buf_used = 0;
+	if (buf->buf.bytesused == stream->queue.buf_used ||
+	    stream->bulk.payload_size == stream->bulk.max_payload_size) {
+		if (buf->buf.bytesused == stream->queue.buf_used) {
+			stream->queue.buf_used = 0;
 			buf->state = UVC_BUF_STATE_DONE;
-			uvc_queue_next_buffer(&video->queue, buf);
-			video->last_fid ^= UVC_STREAM_FID;
+			uvc_queue_next_buffer(&stream->queue, buf);
+			stream->last_fid ^= UVC_STREAM_FID;
 		}
 
-		video->bulk.header_size = 0;
-		video->bulk.payload_size = 0;
+		stream->bulk.header_size = 0;
+		stream->bulk.payload_size = 0;
 	}
 
-	urb->transfer_buffer_length = video->urb_size - len;
+	urb->transfer_buffer_length = stream->urb_size - len;
 }
 
 static void uvc_video_complete(struct urb *urb)
 {
-	struct uvc_video_device *video = urb->context;
-	struct uvc_video_queue *queue = &video->queue;
+	struct uvc_streaming *stream = urb->context;
+	struct uvc_video_queue *queue = &stream->queue;
 	struct uvc_buffer *buf = NULL;
 	unsigned long flags;
 	int ret;
@@ -687,7 +696,7 @@ static void uvc_video_complete(struct urb *urb)
 			"completion handler.\n", urb->status);
 
 	case -ENOENT:		/* usb_kill_urb() called. */
-		if (video->frozen)
+		if (stream->frozen)
 			return;
 
 	case -ECONNRESET:	/* usb_unlink_urb() called. */
@@ -702,7 +711,7 @@ static void uvc_video_complete(struct urb *urb)
 				       queue);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 
-	video->decode(urb, video, buf);
+	stream->decode(urb, stream, buf);
 
 	if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
 		uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
@@ -713,19 +722,19 @@ static void uvc_video_complete(struct urb *urb)
 /*
  * Free transfer buffers.
  */
-static void uvc_free_urb_buffers(struct uvc_video_device *video)
+static void uvc_free_urb_buffers(struct uvc_streaming *stream)
 {
 	unsigned int i;
 
 	for (i = 0; i < UVC_URBS; ++i) {
-		if (video->urb_buffer[i]) {
-			usb_buffer_free(video->dev->udev, video->urb_size,
-				video->urb_buffer[i], video->urb_dma[i]);
-			video->urb_buffer[i] = NULL;
+		if (stream->urb_buffer[i]) {
+			usb_buffer_free(stream->dev->udev, stream->urb_size,
+				stream->urb_buffer[i], stream->urb_dma[i]);
+			stream->urb_buffer[i] = NULL;
 		}
 	}
 
-	video->urb_size = 0;
+	stream->urb_size = 0;
 }
 
 /*
@@ -739,15 +748,15 @@ static void uvc_free_urb_buffers(struct uvc_video_device *video)
  *
  * Return the number of allocated packets on success or 0 when out of memory.
  */
-static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
+static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
 	unsigned int size, unsigned int psize, gfp_t gfp_flags)
 {
 	unsigned int npackets;
 	unsigned int i;
 
 	/* Buffers are already allocated, bail out. */
-	if (video->urb_size)
-		return video->urb_size / psize;
+	if (stream->urb_size)
+		return stream->urb_size / psize;
 
 	/* Compute the number of packets. Bulk endpoints might transfer UVC
 	 * payloads accross multiple URBs.
@@ -759,17 +768,17 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
 	/* Retry allocations until one succeed. */
 	for (; npackets > 1; npackets /= 2) {
 		for (i = 0; i < UVC_URBS; ++i) {
-			video->urb_buffer[i] = usb_buffer_alloc(
-				video->dev->udev, psize * npackets,
-				gfp_flags | __GFP_NOWARN, &video->urb_dma[i]);
-			if (!video->urb_buffer[i]) {
-				uvc_free_urb_buffers(video);
+			stream->urb_buffer[i] = usb_buffer_alloc(
+				stream->dev->udev, psize * npackets,
+				gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
+			if (!stream->urb_buffer[i]) {
+				uvc_free_urb_buffers(stream);
 				break;
 			}
 		}
 
 		if (i == UVC_URBS) {
-			video->urb_size = psize * npackets;
+			stream->urb_size = psize * npackets;
 			return npackets;
 		}
 	}
@@ -780,29 +789,30 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
 /*
  * Uninitialize isochronous/bulk URBs and free transfer buffers.
  */
-static void uvc_uninit_video(struct uvc_video_device *video, int free_buffers)
+static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
 {
 	struct urb *urb;
 	unsigned int i;
 
 	for (i = 0; i < UVC_URBS; ++i) {
-		if ((urb = video->urb[i]) == NULL)
+		urb = stream->urb[i];
+		if (urb == NULL)
 			continue;
 
 		usb_kill_urb(urb);
 		usb_free_urb(urb);
-		video->urb[i] = NULL;
+		stream->urb[i] = NULL;
 	}
 
 	if (free_buffers)
-		uvc_free_urb_buffers(video);
+		uvc_free_urb_buffers(stream);
 }
 
 /*
  * Initialize isochronous URBs and allocate transfer buffers. The packet size
  * is given by the endpoint.
  */
-static int uvc_init_video_isoc(struct uvc_video_device *video,
+static int uvc_init_video_isoc(struct uvc_streaming *stream,
 	struct usb_host_endpoint *ep, gfp_t gfp_flags)
 {
 	struct urb *urb;
@@ -812,9 +822,9 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
 
 	psize = le16_to_cpu(ep->desc.wMaxPacketSize);
 	psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-	size = video->streaming->ctrl.dwMaxVideoFrameSize;
+	size = stream->ctrl.dwMaxVideoFrameSize;
 
-	npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags);
+	npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
 	if (npackets == 0)
 		return -ENOMEM;
 
@@ -823,18 +833,18 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
 	for (i = 0; i < UVC_URBS; ++i) {
 		urb = usb_alloc_urb(npackets, gfp_flags);
 		if (urb == NULL) {
-			uvc_uninit_video(video, 1);
+			uvc_uninit_video(stream, 1);
 			return -ENOMEM;
 		}
 
-		urb->dev = video->dev->udev;
-		urb->context = video;
-		urb->pipe = usb_rcvisocpipe(video->dev->udev,
+		urb->dev = stream->dev->udev;
+		urb->context = stream;
+		urb->pipe = usb_rcvisocpipe(stream->dev->udev,
 				ep->desc.bEndpointAddress);
 		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 		urb->interval = ep->desc.bInterval;
-		urb->transfer_buffer = video->urb_buffer[i];
-		urb->transfer_dma = video->urb_dma[i];
+		urb->transfer_buffer = stream->urb_buffer[i];
+		urb->transfer_dma = stream->urb_dma[i];
 		urb->complete = uvc_video_complete;
 		urb->number_of_packets = npackets;
 		urb->transfer_buffer_length = size;
@@ -844,7 +854,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
 			urb->iso_frame_desc[j].length = psize;
 		}
 
-		video->urb[i] = urb;
+		stream->urb[i] = urb;
 	}
 
 	return 0;
@@ -854,7 +864,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
  * Initialize bulk URBs and allocate transfer buffers. The packet size is
  * given by the endpoint.
  */
-static int uvc_init_video_bulk(struct uvc_video_device *video,
+static int uvc_init_video_bulk(struct uvc_streaming *stream,
 	struct usb_host_endpoint *ep, gfp_t gfp_flags)
 {
 	struct urb *urb;
@@ -863,39 +873,39 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
 	u32 size;
 
 	psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
-	size = video->streaming->ctrl.dwMaxPayloadTransferSize;
-	video->bulk.max_payload_size = size;
+	size = stream->ctrl.dwMaxPayloadTransferSize;
+	stream->bulk.max_payload_size = size;
 
-	npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags);
+	npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
 	if (npackets == 0)
 		return -ENOMEM;
 
 	size = npackets * psize;
 
 	if (usb_endpoint_dir_in(&ep->desc))
-		pipe = usb_rcvbulkpipe(video->dev->udev,
+		pipe = usb_rcvbulkpipe(stream->dev->udev,
 				       ep->desc.bEndpointAddress);
 	else
-		pipe = usb_sndbulkpipe(video->dev->udev,
+		pipe = usb_sndbulkpipe(stream->dev->udev,
 				       ep->desc.bEndpointAddress);
 
-	if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+	if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
 		size = 0;
 
 	for (i = 0; i < UVC_URBS; ++i) {
 		urb = usb_alloc_urb(0, gfp_flags);
 		if (urb == NULL) {
-			uvc_uninit_video(video, 1);
+			uvc_uninit_video(stream, 1);
 			return -ENOMEM;
 		}
 
-		usb_fill_bulk_urb(urb, video->dev->udev, pipe,
-			video->urb_buffer[i], size, uvc_video_complete,
-			video);
+		usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
+			stream->urb_buffer[i], size, uvc_video_complete,
+			stream);
 		urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-		urb->transfer_dma = video->urb_dma[i];
+		urb->transfer_dma = stream->urb_dma[i];
 
-		video->urb[i] = urb;
+		stream->urb[i] = urb;
 	}
 
 	return 0;
@@ -904,35 +914,35 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
 /*
  * Initialize isochronous/bulk URBs and allocate transfer buffers.
  */
-static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags)
+static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
 {
-	struct usb_interface *intf = video->streaming->intf;
+	struct usb_interface *intf = stream->intf;
 	struct usb_host_interface *alts;
 	struct usb_host_endpoint *ep = NULL;
-	int intfnum = video->streaming->intfnum;
+	int intfnum = stream->intfnum;
 	unsigned int bandwidth, psize, i;
 	int ret;
 
-	video->last_fid = -1;
-	video->bulk.header_size = 0;
-	video->bulk.skip_payload = 0;
-	video->bulk.payload_size = 0;
+	stream->last_fid = -1;
+	stream->bulk.header_size = 0;
+	stream->bulk.skip_payload = 0;
+	stream->bulk.payload_size = 0;
 
 	if (intf->num_altsetting > 1) {
 		/* Isochronous endpoint, select the alternate setting. */
-		bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize;
+		bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
 
 		if (bandwidth == 0) {
 			uvc_printk(KERN_WARNING, "device %s requested null "
 				"bandwidth, defaulting to lowest.\n",
-				video->vdev->name);
+				stream->dev->name);
 			bandwidth = 1;
 		}
 
 		for (i = 0; i < intf->num_altsetting; ++i) {
 			alts = &intf->altsetting[i];
 			ep = uvc_find_endpoint(alts,
-				video->streaming->header.bEndpointAddress);
+				stream->header.bEndpointAddress);
 			if (ep == NULL)
 				continue;
 
@@ -946,18 +956,19 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags)
 		if (i >= intf->num_altsetting)
 			return -EIO;
 
-		if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)
+		ret = usb_set_interface(stream->dev->udev, intfnum, i);
+		if (ret < 0)
 			return ret;
 
-		ret = uvc_init_video_isoc(video, ep, gfp_flags);
+		ret = uvc_init_video_isoc(stream, ep, gfp_flags);
 	} else {
 		/* Bulk endpoint, proceed to URB initialization. */
 		ep = uvc_find_endpoint(&intf->altsetting[0],
-				video->streaming->header.bEndpointAddress);
+				stream->header.bEndpointAddress);
 		if (ep == NULL)
 			return -EIO;
 
-		ret = uvc_init_video_bulk(video, ep, gfp_flags);
+		ret = uvc_init_video_bulk(stream, ep, gfp_flags);
 	}
 
 	if (ret < 0)
@@ -965,10 +976,11 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags)
 
 	/* Submit the URBs. */
 	for (i = 0; i < UVC_URBS; ++i) {
-		if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) {
+		ret = usb_submit_urb(stream->urb[i], gfp_flags);
+		if (ret < 0) {
 			uvc_printk(KERN_ERR, "Failed to submit URB %u "
 					"(%d).\n", i, ret);
-			uvc_uninit_video(video, 1);
+			uvc_uninit_video(stream, 1);
 			return ret;
 		}
 	}
@@ -987,14 +999,14 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags)
  * video buffers in any way. We mark the device as frozen to make sure the URB
  * completion handler won't try to cancel the queue when we kill the URBs.
  */
-int uvc_video_suspend(struct uvc_video_device *video)
+int uvc_video_suspend(struct uvc_streaming *stream)
 {
-	if (!uvc_queue_streaming(&video->queue))
+	if (!uvc_queue_streaming(&stream->queue))
 		return 0;
 
-	video->frozen = 1;
-	uvc_uninit_video(video, 0);
-	usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
+	stream->frozen = 1;
+	uvc_uninit_video(stream, 0);
+	usb_set_interface(stream->dev->udev, stream->intfnum, 0);
 	return 0;
 }
 
@@ -1006,22 +1018,24 @@ int uvc_video_suspend(struct uvc_video_device *video)
  * buffers, making sure userspace applications are notified of the problem
  * instead of waiting forever.
  */
-int uvc_video_resume(struct uvc_video_device *video)
+int uvc_video_resume(struct uvc_streaming *stream)
 {
 	int ret;
 
-	video->frozen = 0;
+	stream->frozen = 0;
 
-	if ((ret = uvc_commit_video(video, &video->streaming->ctrl)) < 0) {
-		uvc_queue_enable(&video->queue, 0);
+	ret = uvc_commit_video(stream, &stream->ctrl);
+	if (ret < 0) {
+		uvc_queue_enable(&stream->queue, 0);
 		return ret;
 	}
 
-	if (!uvc_queue_streaming(&video->queue))
+	if (!uvc_queue_streaming(&stream->queue))
 		return 0;
 
-	if ((ret = uvc_init_video(video, GFP_NOIO)) < 0)
-		uvc_queue_enable(&video->queue, 0);
+	ret = uvc_init_video(stream, GFP_NOIO);
+	if (ret < 0)
+		uvc_queue_enable(&stream->queue, 0);
 
 	return ret;
 }
@@ -1040,47 +1054,53 @@ int uvc_video_resume(struct uvc_video_device *video)
  *
  * This function is called before registering the device with V4L.
  */
-int uvc_video_init(struct uvc_video_device *video)
+int uvc_video_init(struct uvc_streaming *stream)
 {
-	struct uvc_streaming_control *probe = &video->streaming->ctrl;
+	struct uvc_streaming_control *probe = &stream->ctrl;
 	struct uvc_format *format = NULL;
 	struct uvc_frame *frame = NULL;
 	unsigned int i;
 	int ret;
 
-	if (video->streaming->nformats == 0) {
+	if (stream->nformats == 0) {
 		uvc_printk(KERN_INFO, "No supported video formats found.\n");
 		return -EINVAL;
 	}
 
+	atomic_set(&stream->active, 0);
+
+	/* Initialize the video buffers queue. */
+	uvc_queue_init(&stream->queue, stream->type);
+
 	/* Alternate setting 0 should be the default, yet the XBox Live Vision
 	 * Cam (and possibly other devices) crash or otherwise misbehave if
 	 * they don't receive a SET_INTERFACE request before any other video
 	 * control request.
 	 */
-	usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
+	usb_set_interface(stream->dev->udev, stream->intfnum, 0);
 
 	/* Set the streaming probe control with default streaming parameters
 	 * retrieved from the device. Webcams that don't suport GET_DEF
 	 * requests on the probe control will just keep their current streaming
 	 * parameters.
 	 */
-	if (uvc_get_video_ctrl(video, probe, 1, GET_DEF) == 0)
-		uvc_set_video_ctrl(video, probe, 1);
+	if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0)
+		uvc_set_video_ctrl(stream, probe, 1);
 
 	/* Initialize the streaming parameters with the probe control current
 	 * value. This makes sure SET_CUR requests on the streaming commit
 	 * control will always use values retrieved from a successful GET_CUR
 	 * request on the probe control, as required by the UVC specification.
 	 */
-	if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
+	ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);
+	if (ret < 0)
 		return ret;
 
 	/* Check if the default format descriptor exists. Use the first
 	 * available format otherwise.
 	 */
-	for (i = video->streaming->nformats; i > 0; --i) {
-		format = &video->streaming->format[i-1];
+	for (i = stream->nformats; i > 0; --i) {
+		format = &stream->format[i-1];
 		if (format->index == probe->bFormatIndex)
 			break;
 	}
@@ -1105,21 +1125,20 @@ int uvc_video_init(struct uvc_video_device *video)
 	probe->bFormatIndex = format->index;
 	probe->bFrameIndex = frame->bFrameIndex;
 
-	video->streaming->cur_format = format;
-	video->streaming->cur_frame = frame;
-	atomic_set(&video->active, 0);
+	stream->cur_format = format;
+	stream->cur_frame = frame;
 
 	/* Select the video decoding function */
-	if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)
-			video->decode = uvc_video_decode_isight;
-		else if (video->streaming->intf->num_altsetting > 1)
-			video->decode = uvc_video_decode_isoc;
+	if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)
+			stream->decode = uvc_video_decode_isight;
+		else if (stream->intf->num_altsetting > 1)
+			stream->decode = uvc_video_decode_isoc;
 		else
-			video->decode = uvc_video_decode_bulk;
+			stream->decode = uvc_video_decode_bulk;
 	} else {
-		if (video->streaming->intf->num_altsetting == 1)
-			video->decode = uvc_video_encode_bulk;
+		if (stream->intf->num_altsetting == 1)
+			stream->decode = uvc_video_encode_bulk;
 		else {
 			uvc_printk(KERN_INFO, "Isochronous endpoints are not "
 				"supported for video output devices.\n");
@@ -1133,31 +1152,32 @@ int uvc_video_init(struct uvc_video_device *video)
 /*
  * Enable or disable the video stream.
  */
-int uvc_video_enable(struct uvc_video_device *video, int enable)
+int uvc_video_enable(struct uvc_streaming *stream, int enable)
 {
 	int ret;
 
 	if (!enable) {
-		uvc_uninit_video(video, 1);
-		usb_set_interface(video->dev->udev,
-			video->streaming->intfnum, 0);
-		uvc_queue_enable(&video->queue, 0);
+		uvc_uninit_video(stream, 1);
+		usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+		uvc_queue_enable(&stream->queue, 0);
 		return 0;
 	}
 
-	if ((video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) ||
+	if ((stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) ||
 	    uvc_no_drop_param)
-		video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
+		stream->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
 	else
-		video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
+		stream->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
 
-	if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
+	ret = uvc_queue_enable(&stream->queue, 1);
+	if (ret < 0)
 		return ret;
 
 	/* Commit the streaming parameters. */
-	if ((ret = uvc_commit_video(video, &video->streaming->ctrl)) < 0)
+	ret = uvc_commit_video(stream, &stream->ctrl);
+	if (ret < 0)
 		return ret;
 
-	return uvc_init_video(video, GFP_KERNEL);
+	return uvc_init_video(stream, GFP_KERNEL);
 }
 
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 3c78d3c1e4c0..e7958aa454ce 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -67,155 +67,12 @@ struct uvc_xu_control {
 #ifdef __KERNEL__
 
 #include <linux/poll.h>
+#include <linux/usb/video.h>
 
 /* --------------------------------------------------------------------------
  * UVC constants
  */
 
-#define SC_UNDEFINED			0x00
-#define SC_VIDEOCONTROL			0x01
-#define SC_VIDEOSTREAMING		0x02
-#define SC_VIDEO_INTERFACE_COLLECTION	0x03
-
-#define PC_PROTOCOL_UNDEFINED		0x00
-
-#define CS_UNDEFINED			0x20
-#define CS_DEVICE			0x21
-#define CS_CONFIGURATION		0x22
-#define CS_STRING			0x23
-#define CS_INTERFACE			0x24
-#define CS_ENDPOINT			0x25
-
-/* VideoControl class specific interface descriptor */
-#define VC_DESCRIPTOR_UNDEFINED		0x00
-#define VC_HEADER			0x01
-#define VC_INPUT_TERMINAL		0x02
-#define VC_OUTPUT_TERMINAL		0x03
-#define VC_SELECTOR_UNIT		0x04
-#define VC_PROCESSING_UNIT		0x05
-#define VC_EXTENSION_UNIT		0x06
-
-/* VideoStreaming class specific interface descriptor */
-#define VS_UNDEFINED			0x00
-#define VS_INPUT_HEADER			0x01
-#define VS_OUTPUT_HEADER		0x02
-#define VS_STILL_IMAGE_FRAME		0x03
-#define VS_FORMAT_UNCOMPRESSED		0x04
-#define VS_FRAME_UNCOMPRESSED		0x05
-#define VS_FORMAT_MJPEG			0x06
-#define VS_FRAME_MJPEG			0x07
-#define VS_FORMAT_MPEG2TS		0x0a
-#define VS_FORMAT_DV			0x0c
-#define VS_COLORFORMAT			0x0d
-#define VS_FORMAT_FRAME_BASED		0x10
-#define VS_FRAME_FRAME_BASED		0x11
-#define VS_FORMAT_STREAM_BASED		0x12
-
-/* Endpoint type */
-#define EP_UNDEFINED			0x00
-#define EP_GENERAL			0x01
-#define EP_ENDPOINT			0x02
-#define EP_INTERRUPT			0x03
-
-/* Request codes */
-#define RC_UNDEFINED			0x00
-#define SET_CUR				0x01
-#define GET_CUR				0x81
-#define GET_MIN				0x82
-#define GET_MAX				0x83
-#define GET_RES				0x84
-#define GET_LEN				0x85
-#define GET_INFO			0x86
-#define GET_DEF				0x87
-
-/* VideoControl interface controls */
-#define VC_CONTROL_UNDEFINED		0x00
-#define VC_VIDEO_POWER_MODE_CONTROL	0x01
-#define VC_REQUEST_ERROR_CODE_CONTROL	0x02
-
-/* Terminal controls */
-#define TE_CONTROL_UNDEFINED		0x00
-
-/* Selector Unit controls */
-#define SU_CONTROL_UNDEFINED		0x00
-#define SU_INPUT_SELECT_CONTROL		0x01
-
-/* Camera Terminal controls */
-#define CT_CONTROL_UNDEFINED				0x00
-#define CT_SCANNING_MODE_CONTROL			0x01
-#define CT_AE_MODE_CONTROL				0x02
-#define CT_AE_PRIORITY_CONTROL				0x03
-#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL		0x04
-#define CT_EXPOSURE_TIME_RELATIVE_CONTROL		0x05
-#define CT_FOCUS_ABSOLUTE_CONTROL			0x06
-#define CT_FOCUS_RELATIVE_CONTROL			0x07
-#define CT_FOCUS_AUTO_CONTROL				0x08
-#define CT_IRIS_ABSOLUTE_CONTROL			0x09
-#define CT_IRIS_RELATIVE_CONTROL			0x0a
-#define CT_ZOOM_ABSOLUTE_CONTROL			0x0b
-#define CT_ZOOM_RELATIVE_CONTROL			0x0c
-#define CT_PANTILT_ABSOLUTE_CONTROL			0x0d
-#define CT_PANTILT_RELATIVE_CONTROL			0x0e
-#define CT_ROLL_ABSOLUTE_CONTROL			0x0f
-#define CT_ROLL_RELATIVE_CONTROL			0x10
-#define CT_PRIVACY_CONTROL				0x11
-
-/* Processing Unit controls */
-#define PU_CONTROL_UNDEFINED				0x00
-#define PU_BACKLIGHT_COMPENSATION_CONTROL		0x01
-#define PU_BRIGHTNESS_CONTROL				0x02
-#define PU_CONTRAST_CONTROL				0x03
-#define PU_GAIN_CONTROL					0x04
-#define PU_POWER_LINE_FREQUENCY_CONTROL			0x05
-#define PU_HUE_CONTROL					0x06
-#define PU_SATURATION_CONTROL				0x07
-#define PU_SHARPNESS_CONTROL				0x08
-#define PU_GAMMA_CONTROL				0x09
-#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL		0x0a
-#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL	0x0b
-#define PU_WHITE_BALANCE_COMPONENT_CONTROL		0x0c
-#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL		0x0d
-#define PU_DIGITAL_MULTIPLIER_CONTROL			0x0e
-#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL		0x0f
-#define PU_HUE_AUTO_CONTROL				0x10
-#define PU_ANALOG_VIDEO_STANDARD_CONTROL		0x11
-#define PU_ANALOG_LOCK_STATUS_CONTROL			0x12
-
-#define LXU_MOTOR_PANTILT_RELATIVE_CONTROL		0x01
-#define LXU_MOTOR_PANTILT_RESET_CONTROL			0x02
-#define LXU_MOTOR_FOCUS_MOTOR_CONTROL			0x03
-
-/* VideoStreaming interface controls */
-#define VS_CONTROL_UNDEFINED		0x00
-#define VS_PROBE_CONTROL		0x01
-#define VS_COMMIT_CONTROL		0x02
-#define VS_STILL_PROBE_CONTROL		0x03
-#define VS_STILL_COMMIT_CONTROL		0x04
-#define VS_STILL_IMAGE_TRIGGER_CONTROL	0x05
-#define VS_STREAM_ERROR_CODE_CONTROL	0x06
-#define VS_GENERATE_KEY_FRAME_CONTROL	0x07
-#define VS_UPDATE_FRAME_SEGMENT_CONTROL	0x08
-#define VS_SYNC_DELAY_CONTROL		0x09
-
-#define TT_VENDOR_SPECIFIC		0x0100
-#define TT_STREAMING			0x0101
-
-/* Input Terminal types */
-#define ITT_VENDOR_SPECIFIC		0x0200
-#define ITT_CAMERA			0x0201
-#define ITT_MEDIA_TRANSPORT_INPUT	0x0202
-
-/* Output Terminal types */
-#define OTT_VENDOR_SPECIFIC		0x0300
-#define OTT_DISPLAY			0x0301
-#define OTT_MEDIA_TRANSPORT_OUTPUT	0x0302
-
-/* External Terminal types */
-#define EXTERNAL_VENDOR_SPECIFIC	0x0400
-#define COMPOSITE_CONNECTOR		0x0401
-#define SVIDEO_CONNECTOR		0x0402
-#define COMPONENT_CONNECTOR		0x0403
-
 #define UVC_TERM_INPUT			0x0000
 #define UVC_TERM_OUTPUT			0x8000
 
@@ -223,12 +80,12 @@ struct uvc_xu_control {
 #define UVC_ENTITY_IS_UNIT(entity)	(((entity)->type & 0xff00) == 0)
 #define UVC_ENTITY_IS_TERM(entity)	(((entity)->type & 0xff00) != 0)
 #define UVC_ENTITY_IS_ITERM(entity) \
-	(((entity)->type & 0x8000) == UVC_TERM_INPUT)
+	(UVC_ENTITY_IS_TERM(entity) && \
+	((entity)->type & 0x8000) == UVC_TERM_INPUT)
 #define UVC_ENTITY_IS_OTERM(entity) \
-	(((entity)->type & 0x8000) == UVC_TERM_OUTPUT)
+	(UVC_ENTITY_IS_TERM(entity) && \
+	((entity)->type & 0x8000) == UVC_TERM_OUTPUT)
 
-#define UVC_STATUS_TYPE_CONTROL		1
-#define UVC_STATUS_TYPE_STREAMING	2
 
 /* ------------------------------------------------------------------------
  * GUIDs
@@ -249,19 +106,6 @@ struct uvc_xu_control {
 	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
 	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}
 
-#define UVC_GUID_LOGITECH_DEV_INFO \
-	{0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
-	 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1e}
-#define UVC_GUID_LOGITECH_USER_HW \
-	{0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
-	 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f}
-#define UVC_GUID_LOGITECH_VIDEO \
-	{0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
-	 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50}
-#define UVC_GUID_LOGITECH_MOTOR \
-	{0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
-	 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56}
-
 #define UVC_GUID_FORMAT_MJPEG \
 	{ 'M',  'J',  'P',  'G', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
@@ -314,6 +158,7 @@ struct uvc_xu_control {
 #define UVC_QUIRK_STREAM_NO_FID		0x00000010
 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT	0x00000020
 #define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
+#define UVC_QUIRK_PROBE_DEF		0x00000100
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED		0x00000001
@@ -518,26 +363,6 @@ struct uvc_streaming_header {
 	__u8 bTriggerUsage;
 };
 
-struct uvc_streaming {
-	struct list_head list;
-
-	struct usb_interface *intf;
-	int intfnum;
-	__u16 maxpsize;
-
-	struct uvc_streaming_header header;
-	enum v4l2_buf_type type;
-
-	unsigned int nformats;
-	struct uvc_format *format;
-
-	struct uvc_streaming_control ctrl;
-	struct uvc_format *cur_format;
-	struct uvc_frame *cur_frame;
-
-	struct mutex mutex;
-};
-
 enum uvc_buffer_state {
 	UVC_BUF_STATE_IDLE	= 0,
 	UVC_BUF_STATE_QUEUED	= 1,
@@ -579,26 +404,45 @@ struct uvc_video_queue {
 	struct list_head irqqueue;
 };
 
-struct uvc_video_device {
+struct uvc_video_chain {
 	struct uvc_device *dev;
-	struct video_device *vdev;
-	atomic_t active;
-	unsigned int frozen : 1;
+	struct list_head list;
 
 	struct list_head iterms;		/* Input terminals */
-	struct uvc_entity *oterm;		/* Output terminal */
-	struct uvc_entity *sterm;		/* USB streaming terminal */
-	struct uvc_entity *processing;
-	struct uvc_entity *selector;
-	struct list_head extensions;
+	struct list_head oterms;		/* Output terminals */
+	struct uvc_entity *processing;		/* Processing unit */
+	struct uvc_entity *selector;		/* Selector unit */
+	struct list_head extensions;		/* Extension units */
+
 	struct mutex ctrl_mutex;
+};
 
-	struct uvc_video_queue queue;
+struct uvc_streaming {
+	struct list_head list;
+	struct uvc_device *dev;
+	struct video_device *vdev;
+	struct uvc_video_chain *chain;
+	atomic_t active;
 
-	/* Video streaming object, must always be non-NULL. */
-	struct uvc_streaming *streaming;
+	struct usb_interface *intf;
+	int intfnum;
+	__u16 maxpsize;
 
-	void (*decode) (struct urb *urb, struct uvc_video_device *video,
+	struct uvc_streaming_header header;
+	enum v4l2_buf_type type;
+
+	unsigned int nformats;
+	struct uvc_format *format;
+
+	struct uvc_streaming_control ctrl;
+	struct uvc_format *cur_format;
+	struct uvc_frame *cur_frame;
+
+	struct mutex mutex;
+
+	unsigned int frozen : 1;
+	struct uvc_video_queue queue;
+	void (*decode) (struct urb *urb, struct uvc_streaming *video,
 			struct uvc_buffer *buf);
 
 	/* Context data used by the bulk completion handler. */
@@ -640,8 +484,10 @@ struct uvc_device {
 	__u32 clock_frequency;
 
 	struct list_head entities;
+	struct list_head chains;
 
-	struct uvc_video_device video;
+	/* Video Streaming interfaces */
+	struct list_head streams;
 
 	/* Status Interrupt Endpoint */
 	struct usb_host_endpoint *int_ep;
@@ -649,9 +495,6 @@ struct uvc_device {
 	__u8 *status;
 	struct input_dev *input;
 	char input_phys[64];
-
-	/* Video Streaming interfaces */
-	struct list_head streaming;
 };
 
 enum uvc_handle_state {
@@ -660,7 +503,8 @@ enum uvc_handle_state {
 };
 
 struct uvc_fh {
-	struct uvc_video_device *device;
+	struct uvc_video_chain *chain;
+	struct uvc_streaming *stream;
 	enum uvc_handle_state state;
 };
 
@@ -757,13 +601,13 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 extern const struct v4l2_file_operations uvc_fops;
 
 /* Video */
-extern int uvc_video_init(struct uvc_video_device *video);
-extern int uvc_video_suspend(struct uvc_video_device *video);
-extern int uvc_video_resume(struct uvc_video_device *video);
-extern int uvc_video_enable(struct uvc_video_device *video, int enable);
-extern int uvc_probe_video(struct uvc_video_device *video,
+extern int uvc_video_init(struct uvc_streaming *stream);
+extern int uvc_video_suspend(struct uvc_streaming *stream);
+extern int uvc_video_resume(struct uvc_streaming *stream);
+extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
+extern int uvc_probe_video(struct uvc_streaming *stream,
 		struct uvc_streaming_control *probe);
-extern int uvc_commit_video(struct uvc_video_device *video,
+extern int uvc_commit_video(struct uvc_streaming *stream,
 		struct uvc_streaming_control *ctrl);
 extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
 		__u8 intfnum, __u8 cs, void *data, __u16 size);
@@ -777,9 +621,9 @@ extern int uvc_status_suspend(struct uvc_device *dev);
 extern int uvc_status_resume(struct uvc_device *dev);
 
 /* Controls */
-extern struct uvc_control *uvc_find_control(struct uvc_video_device *video,
+extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
 		__u32 v4l2_id, struct uvc_control_mapping **mapping);
-extern int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
+extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
 		struct v4l2_queryctrl *v4l2_ctrl);
 
 extern int uvc_ctrl_add_info(struct uvc_control_info *info);
@@ -789,23 +633,23 @@ extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
 extern int uvc_ctrl_resume_device(struct uvc_device *dev);
 extern void uvc_ctrl_init(void);
 
-extern int uvc_ctrl_begin(struct uvc_video_device *video);
-extern int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback);
-static inline int uvc_ctrl_commit(struct uvc_video_device *video)
+extern int uvc_ctrl_begin(struct uvc_video_chain *chain);
+extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback);
+static inline int uvc_ctrl_commit(struct uvc_video_chain *chain)
 {
-	return __uvc_ctrl_commit(video, 0);
+	return __uvc_ctrl_commit(chain, 0);
 }
-static inline int uvc_ctrl_rollback(struct uvc_video_device *video)
+static inline int uvc_ctrl_rollback(struct uvc_video_chain *chain)
 {
-	return __uvc_ctrl_commit(video, 1);
+	return __uvc_ctrl_commit(chain, 1);
 }
 
-extern int uvc_ctrl_get(struct uvc_video_device *video,
+extern int uvc_ctrl_get(struct uvc_video_chain *chain,
 		struct v4l2_ext_control *xctrl);
-extern int uvc_ctrl_set(struct uvc_video_device *video,
+extern int uvc_ctrl_set(struct uvc_video_chain *chain,
 		struct v4l2_ext_control *xctrl);
 
-extern int uvc_xu_ctrl_query(struct uvc_video_device *video,
+extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
 		struct uvc_xu_control *ctrl, int set);
 
 /* Utility functions */
@@ -817,7 +661,7 @@ extern struct usb_host_endpoint *uvc_find_endpoint(
 		struct usb_host_interface *alts, __u8 epaddr);
 
 /* Quirks support */
-void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
+void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
 		struct uvc_buffer *buf);
 
 #endif /* __KERNEL__ */