rpms/kernel/devel kernel.spec, 1.600, 1.601 linux-2.6-uvcvideo.patch, 1.1, 1.2

Kyle McMartin (kyle) fedora-extras-commits at redhat.com
Wed Apr 9 19:47:21 UTC 2008


Author: kyle

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv31208

Modified Files:
	kernel.spec linux-2.6-uvcvideo.patch 
Log Message:
* Wed Apr 09 2008 Kyle McMartin <kmcmartin at redhat.com>
- Update uvcvideo to svn rev200



Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.600
retrieving revision 1.601
diff -u -r1.600 -r1.601
--- kernel.spec	9 Apr 2008 04:30:31 -0000	1.600
+++ kernel.spec	9 Apr 2008 19:46:16 -0000	1.601
@@ -1758,6 +1758,9 @@
 %kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL}.xen -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.xen.conf %{with_xen} xen
 
 %changelog
+* Wed Apr 09 2008 Kyle McMartin <kmcmartin at redhat.com>
+- Update uvcvideo to svn rev200
+
 * Wed Apr 09 2008 Chuck Ebbert <cebbert at redhat.com>
 - 2.6.25-rc8-git7
 

linux-2.6-uvcvideo.patch:

Index: linux-2.6-uvcvideo.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-uvcvideo.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-uvcvideo.patch	23 Jan 2008 21:03:41 -0000	1.1
+++ linux-2.6-uvcvideo.patch	9 Apr 2008 19:46:16 -0000	1.2
@@ -1,8 +1,8 @@
 diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
-index c9f14bf..19acd71 100644
+index 1832966..1be8bb6 100644
 --- a/drivers/media/video/Kconfig
 +++ b/drivers/media/video/Kconfig
-@@ -718,6 +718,7 @@ source "drivers/media/video/em28xx/Kconfig"
+@@ -737,6 +737,7 @@ source "drivers/media/video/em28xx/Kconfig"
  source "drivers/media/video/usbvision/Kconfig"
  
  source "drivers/media/video/usbvideo/Kconfig"
@@ -11,10 +11,10 @@
  source "drivers/media/video/et61x251/Kconfig"
  
 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
-index b5a0641..91033cf 100644
+index 3f209b3..dda5db0 100644
 --- a/drivers/media/video/Makefile
 +++ b/drivers/media/video/Makefile
-@@ -123,6 +123,8 @@ obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
+@@ -130,6 +130,8 @@ obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
  obj-$(CONFIG_USB_VICAM)         += usbvideo/
  obj-$(CONFIG_USB_QUICKCAM_MESSENGER)	+= usbvideo/
  
@@ -38,18 +38,18 @@
 +	If unsure, jump up and down and look confused.
 diff --git a/drivers/media/video/uvcvideo/Makefile b/drivers/media/video/uvcvideo/Makefile
 new file mode 100644
-index 0000000..ada681c
+index 0000000..fe006fb
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/Makefile
 @@ -0,0 +1,2 @@
 +obj-$(CONFIG_USB_UVCVIDEO)	:= uvcvideo.o
-+uvcvideo-objs   := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o uvc_status.o uvc_isight.o
++uvcvideo-objs	:= uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o uvc_status.o uvc_isight.o
 diff --git a/drivers/media/video/uvcvideo/uvc_compat.h b/drivers/media/video/uvcvideo/uvc_compat.h
 new file mode 100644
-index 0000000..321f3d3
+index 0000000..7152561
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_compat.h
-@@ -0,0 +1,263 @@
+@@ -0,0 +1,316 @@
 +#ifndef _UVC_COMPAT_H
 +#define _UVC_COMPAT_H
 +
@@ -191,6 +191,51 @@
 +#define VIDIOC_ENUM_FRAMEINTERVALS	_IOWR ('V', 75, struct v4l2_frmivalenum)
 +#endif
 +
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
++/*
++ * V4L2 Control identifiers.
++ */
++#define V4L2_CTRL_CLASS_CAMERA 0x009A0000	/* Camera class controls */
++ 
++#define V4L2_CID_POWER_LINE_FREQUENCY		(V4L2_CID_BASE+24) 
++enum v4l2_power_line_frequency {
++	V4L2_CID_POWER_LINE_FREQUENCY_DISABLED	= 0,
++	V4L2_CID_POWER_LINE_FREQUENCY_50HZ	= 1,
++	V4L2_CID_POWER_LINE_FREQUENCY_60HZ	= 2,
++};
++
++#define V4L2_CID_HUE_AUTO			(V4L2_CID_BASE+25) 
++#define V4L2_CID_WHITE_BALANCE_TEMPERATURE	(V4L2_CID_BASE+26) 
++#define V4L2_CID_SHARPNESS			(V4L2_CID_BASE+27) 
++#define V4L2_CID_BACKLIGHT_COMPENSATION 	(V4L2_CID_BASE+28) 
++
++#define V4L2_CID_CAMERA_CLASS_BASE 		(V4L2_CTRL_CLASS_CAMERA | 0x900)
++#define V4L2_CID_CAMERA_CLASS 			(V4L2_CTRL_CLASS_CAMERA | 1)
++
++#define V4L2_CID_EXPOSURE_AUTO			(V4L2_CID_CAMERA_CLASS_BASE+1)
++enum  v4l2_exposure_auto_type {
++	V4L2_EXPOSURE_MANUAL = 0,
++	V4L2_EXPOSURE_AUTO = 1,
++	V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
++	V4L2_EXPOSURE_APERTURE_PRIORITY = 3
++};
++#define V4L2_CID_EXPOSURE_ABSOLUTE		(V4L2_CID_CAMERA_CLASS_BASE+2)
++#define V4L2_CID_EXPOSURE_AUTO_PRIORITY		(V4L2_CID_CAMERA_CLASS_BASE+3)
++
++#define V4L2_CID_PAN_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+4)
++#define V4L2_CID_TILT_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+5)
++#define V4L2_CID_PAN_RESET			(V4L2_CID_CAMERA_CLASS_BASE+6)
++#define V4L2_CID_TILT_RESET			(V4L2_CID_CAMERA_CLASS_BASE+7)
++
++#define V4L2_CID_PAN_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+8)
++#define V4L2_CID_TILT_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+9)
++
++#define V4L2_CID_FOCUS_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+10)
++#define V4L2_CID_FOCUS_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+11)
++#define V4L2_CID_FOCUS_AUTO			(V4L2_CID_CAMERA_CLASS_BASE+12)
++ 
++#endif
++
 +#ifdef __KERNEL__
 +
 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
@@ -309,16 +354,24 @@
 +
 +#endif
 +
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
++/*
++ * Linked list API
++ */
++#define list_first_entry(ptr, type, member) \
++	list_entry((ptr)->next, type, member)
++#endif
++
 +#endif /* __KERNEL__ */
 +
 +#endif /* _UVC_COMPAT_H */
 +
 diff --git a/drivers/media/video/uvcvideo/uvc_ctrl.c b/drivers/media/video/uvcvideo/uvc_ctrl.c
 new file mode 100644
-index 0000000..8b7caf9
+index 0000000..dce576b
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_ctrl.c
-@@ -0,0 +1,1169 @@
+@@ -0,0 +1,1245 @@
 +/*
 + *      uvcvideo.c  --  USB Video Class driver
 + *
@@ -493,6 +546,14 @@
 +		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 +				| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 +	},
++	{
++		.entity		= UVC_GUID_UVC_PROCESSING,
++		.selector	= PU_WHITE_BALANCE_COMPONENT_CONTROL,
++		.index		= 7,
++		.size		= 4,
++		.flags		= UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
++				| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
++	},
 +};
 +
 +static struct uvc_menu_info power_line_frequency_controls[] = {
@@ -644,7 +705,7 @@
 +		.data_type	= UVC_CTRL_DATA_TYPE_UNSIGNED,
 +	},
 +	{
-+		.id		= V4L2_CID_WHITE_BALANCE_TEMPERATURE_AUTO,
++		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
 +		.name		= "White Balance Temperature, Auto",
 +		.entity		= UVC_GUID_UVC_PROCESSING,
 +		.selector	= PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
@@ -664,6 +725,36 @@
 +		.data_type	= UVC_CTRL_DATA_TYPE_UNSIGNED,
 +	},
 +	{
++		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
++		.name		= "White Balance Component, Auto",
++		.entity		= UVC_GUID_UVC_PROCESSING,
++		.selector	= PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
++		.size		= 1,
++		.offset		= 0,
++		.v4l2_type	= V4L2_CTRL_TYPE_BOOLEAN,
++		.data_type	= UVC_CTRL_DATA_TYPE_BOOLEAN,
++	},
++	{
++		.id		= V4L2_CID_BLUE_BALANCE,
++		.name		= "White Balance Blue Component",
++		.entity		= UVC_GUID_UVC_PROCESSING,
++		.selector	= PU_WHITE_BALANCE_COMPONENT_CONTROL,
++		.size		= 16,
++		.offset		= 0,
++		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
++		.data_type	= UVC_CTRL_DATA_TYPE_SIGNED,
++	},
++	{
++		.id		= V4L2_CID_RED_BALANCE,
++		.name		= "White Balance Red Component",
++		.entity		= UVC_GUID_UVC_PROCESSING,
++		.selector	= PU_WHITE_BALANCE_COMPONENT_CONTROL,
++		.size		= 16,
++		.offset		= 16,
++		.v4l2_type	= V4L2_CTRL_TYPE_INTEGER,
++		.data_type	= UVC_CTRL_DATA_TYPE_SIGNED,
++	},
++	{
 +		.id		= V4L2_CID_FOCUS_ABSOLUTE,
 +		.name		= "Focus (absolute)",
 +		.entity		= UVC_GUID_UVC_CAMERA,
@@ -857,6 +948,8 @@
 +{
 +	struct uvc_control *ctrl;
 +	struct uvc_control_mapping *mapping;
++	struct uvc_menu_info *menu;
++	unsigned int i;
 +	__u8 data[8];
 +	int ret;
 +
@@ -879,6 +972,23 @@
 +			return ret;
 +		v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
 +	}
++
++	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
++		v4l2_ctrl->minimum = 0;
++		v4l2_ctrl->maximum = mapping->menu_count - 1;
++		v4l2_ctrl->step = 1;
++
++		menu = mapping->menu_info;
++		for (i = 0; i < mapping->menu_count; ++i, ++menu) {
++			if (menu->value == v4l2_ctrl->default_value) {
++				v4l2_ctrl->default_value = i;
++				break;
++			}
++		}
++
++		return 0;
++	}
++
 +	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,
@@ -1006,6 +1116,8 @@
 +{
 +	struct uvc_control *ctrl;
 +	struct uvc_control_mapping *mapping;
++	struct uvc_menu_info *menu;
++	unsigned int i;
 +	int ret;
 +
 +	ctrl = uvc_find_control(video, xctrl->id, &mapping);
@@ -1027,6 +1139,16 @@
 +	xctrl->value = uvc_get_le_value(
 +		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
 +
++	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
++		menu = mapping->menu_info;
++		for (i = 0; i < mapping->menu_count; ++i, ++menu) {
++			if (menu->value == xctrl->value) {
++				xctrl->value = i;
++				break;
++			}
++		}
++	}
++
 +	return 0;
 +}
 +
@@ -1035,12 +1157,19 @@
 +{
 +	struct uvc_control *ctrl;
 +	struct uvc_control_mapping *mapping;
++	s32 value = xctrl->value;
 +	int ret;
 +
 +	ctrl = uvc_find_control(video, xctrl->id, &mapping);
 +	if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0)
 +		return -EINVAL;
 +
++	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
++		if (value < 0 || value >= mapping->menu_count)
++			return -EINVAL;
++		value = mapping->menu_info[value].value;
++	}
++
 +	if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) {
 +		if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) {
 +			memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
@@ -1065,7 +1194,7 @@
 +		       ctrl->info->size);
 +	}
 +
-+	uvc_set_le_value(xctrl->value,
++	uvc_set_le_value(value,
 +		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
 +
 +	ctrl->dirty = 1;
@@ -1490,10 +1619,10 @@
 +
 diff --git a/drivers/media/video/uvcvideo/uvc_driver.c b/drivers/media/video/uvcvideo/uvc_driver.c
 new file mode 100644
-index 0000000..bd194fb
+index 0000000..6acfce1
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_driver.c
-@@ -0,0 +1,1877 @@
+@@ -0,0 +1,1920 @@
 +/*
 + *      uvcvideo.c  --  USB Video Class driver
 + *
@@ -1539,10 +1668,16 @@
 +#endif
 +
 +#include "uvcvideo.h"
++#include "version.h"
 +
 +#define DRIVER_AUTHOR		"Laurent Pinchart <laurent.pinchart at skynet.be>"
 +#define DRIVER_DESC		"USB Video Class driver"
-+#define DRIVER_VERSION		"0.1.0"
++#ifndef DRIVER_VERSION
++#define DRIVER_VERSION		"v0.1.0"
++#endif
++
++static unsigned int uvc_quirks_param = 0;
++unsigned int uvc_trace_param = 0;
 +
 +/* ------------------------------------------------------------------------
 + * Control, formats, ...
@@ -1579,6 +1714,16 @@
 +		.guid		= UVC_GUID_FORMAT_UYVY,
 +		.fcc		= V4L2_PIX_FMT_UYVY,
 +	},
++	{
++		.name		= "Greyscale",
++		.guid		= UVC_GUID_FORMAT_Y800,
++		.fcc		= V4L2_PIX_FMT_GREY,
++	},
++	{
++		.name		= "RGB Bayer",
++		.guid		= UVC_GUID_FORMAT_BY8,
++		.fcc		= V4L2_PIX_FMT_SBGGR8,
++	},
 +};
 +
 +#if 0
@@ -2520,8 +2665,9 @@
 +
 +		case VC_PROCESSING_UNIT:
 +			n = buflen >= 8 ? buffer[7] : 0;
++			p = dev->uvc_version >= 0x0110 ? 10 : 9;
 +
-+			if (buflen < 8 + n) {
++			if (buflen < p + n) {
 +				uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
 +				       "interface %d PROCESSING_UNIT error\n", udev->devnum,
 +				       dev->intf->cur_altsetting->desc.bInterfaceNumber);
@@ -2539,7 +2685,8 @@
 +			unit->processing.bControlSize = buffer[7];
 +			unit->processing.bmControls = (__u8*)unit + sizeof *unit;
 +			memcpy(unit->processing.bmControls, &buffer[8], n);
-+			unit->processing.bmVideoStandards = buffer[9+n];
++			if (dev->uvc_version >= 0x0110)
++				unit->processing.bmVideoStandards = buffer[9+n];
 +
 +			if (buffer[8+n] != 0)
 +				usb_string(udev, buffer[8+n], unit->name, sizeof unit->name);
@@ -2919,14 +3066,6 @@
 +	if (vdev == NULL)
 +		return -1;
 +
-+	if (dev->udev->product != NULL)
-+		strncpy(vdev->name, dev->udev->product, sizeof vdev->name);
-+	else
-+		snprintf(vdev->name, sizeof vdev->name,
-+			"UVC Camera (%04x:%04x)",
-+			le16_to_cpu(dev->udev->descriptor.idVendor),
-+			le16_to_cpu(dev->udev->descriptor.idProduct));
-+
 +	/* 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
 +	 * get another one.
@@ -2937,6 +3076,7 @@
 +	vdev->minor = -1;
 +	vdev->fops = &uvc_fops;
 +	vdev->release = video_device_release;
++	strncpy(vdev->name, dev->name, sizeof vdev->name);
 +
 +	/* Set the driver data before calling video_register_device, otherwise
 +	 * uvc_v4l2_open might race us.
@@ -3030,7 +3170,15 @@
 +	dev->udev = usb_get_dev(udev);
 +	dev->intf = usb_get_intf(intf);
 +	dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
-+	dev->quirks = id->driver_info;
++	dev->quirks = id->driver_info | uvc_quirks_param;
++
++	if (udev->product != NULL)
++		strncpy(dev->name, udev->product, sizeof dev->name);
++	else
++		snprintf(dev->name, sizeof dev->name,
++			"UVC Camera (%04x:%04x)",
++			le16_to_cpu(udev->descriptor.idVendor),
++			le16_to_cpu(udev->descriptor.idProduct));
 +
 +	/* Parse the Video Class control descriptor */
 +	if (uvc_parse_control(dev) < 0) {
@@ -3044,6 +3192,13 @@
 +		le16_to_cpu(udev->descriptor.idVendor),
 +		le16_to_cpu(udev->descriptor.idProduct));
 +
++	if (uvc_quirks_param != 0) {
++		uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module "
++			"parameter for testing purpose.\n", uvc_quirks_param);
++		uvc_printk(KERN_INFO, "Please report required quirks to the "
++			"linux-uvc-devel mailing list.\n");
++	}
++
 +	/* Initialize controls */
 +	if (uvc_ctrl_init_device(dev) < 0)
 +		goto error;
@@ -3213,14 +3368,6 @@
 +	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
 +	  .bInterfaceSubClass	= 1,
 +	  .bInterfaceProtocol	= 0 },
-+	/* Logitech Quickcam Communicator */
-+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor		= 0x046d,
-+	  .idProduct		= 0x08d7,
-+	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
-+	  .bInterfaceSubClass	= 1,
-+	  .bInterfaceProtocol	= 0 },
 +	/* Logitech Quickcam OEM Dell Notebook */
 +	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 +				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -3238,11 +3385,24 @@
 +	  .bInterfaceSubClass	= 1,
 +	  .bInterfaceProtocol	= 0 },
 +	/* Apple Built-In iSight */
-+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE,
++	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
++				| USB_DEVICE_ID_MATCH_INT_INFO,
 +	  .idVendor		= 0x05ac,
 +	  .idProduct		= 0x8501,
++	  .bInterfaceClass      = USB_CLASS_VIDEO,
++	  .bInterfaceSubClass   = 1,
++	  .bInterfaceProtocol   = 0,
 +	  .driver_info 		= UVC_QUIRK_PROBE_MINMAX
 +	                        | UVC_QUIRK_BUILTIN_ISIGHT },
++	/* Genesys Logic USB 2.0 PC Camera */
++	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
++				| USB_DEVICE_ID_MATCH_INT_INFO,
++	  .idVendor             = 0x05e3,
++	  .idProduct            = 0x0505,
++	  .bInterfaceClass      = USB_CLASS_VIDEO,
++	  .bInterfaceSubClass   = 1,
++	  .bInterfaceProtocol   = 0,
++	  .driver_info          = UVC_QUIRK_STREAM_NO_FID },
 +	/* Silicon Motion SM371 */
 +	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 +				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -3297,6 +3457,15 @@
 +	  .bInterfaceSubClass	= 1,
 +	  .bInterfaceProtocol	= 0,
 +	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
++	/* Packard Bell OEM Webcam */
++	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
++				| USB_DEVICE_ID_MATCH_INT_INFO,
++	  .idVendor		= 0x5986,
++	  .idProduct		= 0x0101,
++	  .bInterfaceClass	= USB_CLASS_VIDEO,
++	  .bInterfaceSubClass	= 1,
++	  .bInterfaceProtocol	= 0,
++	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
 +	/* Acer Crystal Eye webcam */
 +	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 +				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -3352,7 +3521,7 @@
 +
 +	result = usb_register(&uvc_driver.driver);
 +	if (result == 0)
-+		printk(KERN_INFO DRIVER_DESC " (v" DRIVER_VERSION ")\n");
++		printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
 +	return result;
 +}
 +
@@ -3364,12 +3533,15 @@
 +module_init(uvc_init);
 +module_exit(uvc_cleanup);
 +
-+unsigned int uvc_trace_param = 0;
++module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
++MODULE_PARM_DESC(quirks, "Forced device quirks");
 +module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
++MODULE_PARM_DESC(trace, "Trace level bitmask");
 +
 +MODULE_AUTHOR(DRIVER_AUTHOR);
 +MODULE_DESCRIPTION(DRIVER_DESC);
 +MODULE_LICENSE("GPL");
++MODULE_VERSION(DRIVER_VERSION);
 +
 diff --git a/drivers/media/video/uvcvideo/uvc_isight.c b/drivers/media/video/uvcvideo/uvc_isight.c
 new file mode 100644
@@ -3519,10 +3691,10 @@
 +}
 diff --git a/drivers/media/video/uvcvideo/uvc_queue.c b/drivers/media/video/uvcvideo/uvc_queue.c
 new file mode 100644
-index 0000000..4957109
+index 0000000..d7e4461
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_queue.c
-@@ -0,0 +1,414 @@
+@@ -0,0 +1,463 @@
 +/*
 + *      uvcvideo.c  --  USB Video Class driver
 + *
@@ -3705,7 +3877,7 @@
 +	return 0;
 +}
 +
-+void uvc_query_buffer(struct uvc_buffer *buf,
++static void __uvc_query_buffer(struct uvc_buffer *buf,
 +		struct v4l2_buffer *v4l2_buf)
 +{
 +	memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
@@ -3728,6 +3900,24 @@
 +	}
 +}
 +
++int uvc_query_buffer(struct uvc_video_queue *queue,
++		struct v4l2_buffer *v4l2_buf)
++{
++	int ret = 0;
++
++	mutex_lock(&queue->mutex);
++	if (v4l2_buf->index >= queue->count) {
++		ret = -EINVAL;
++		goto done;
++	}
++
++	__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
++
++done:
++       mutex_unlock(&queue->mutex);
++       return ret;
++}
++
 +/*
 + * Queue a video buffer. Attempting to queue a buffer that has already been
 + * queued will return -EINVAL.
@@ -3813,11 +4003,13 @@
 +		goto done;
 +	}
 +
-+	buf = list_entry(queue->mainqueue.next, struct uvc_buffer, stream);
-+	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u.\n", buf->buf.index);
++	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
 +	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
 +		goto done;
 +
++	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
++		buf->buf.index, buf->state, buf->buf.bytesused);
++
 +	switch (buf->state) {
 +	case UVC_BUF_STATE_ERROR:
 +		uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
@@ -3838,7 +4030,7 @@
 +	}
 +
 +	list_del(&buf->stream);
-+	uvc_query_buffer(buf, v4l2_buf);
++	__uvc_query_buffer(buf, v4l2_buf);
 +
 +done:
 +	mutex_unlock(&queue->mutex);
@@ -3846,6 +4038,35 @@
 +}
 +
 +/*
++ * Poll the video queue.
++ *
++ * This function implements video queue polling and is intended to be used by
++ * the device poll handler.
++ */
++unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
++		poll_table *wait)
++{
++	struct uvc_buffer *buf;
++	unsigned int mask = 0;
++
++	mutex_lock(&queue->mutex);
++	if (list_empty(&queue->mainqueue)) {
++		mask |= POLLERR;
++		goto done;
++	}
++	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
++
++	poll_wait(file, &buf->wait, wait);
++	if (buf->state == UVC_BUF_STATE_DONE ||
++	    buf->state == UVC_BUF_STATE_ERROR)
++		mask |= POLLIN | POLLRDNORM;
++
++done:
++	mutex_unlock(&queue->mutex);
++	return mask;
++}
++
++/*
 + * Enable or disable the video buffers queue.
 + *
 + * The queue must be enabled before starting video acquisition and must be
@@ -3907,7 +4128,7 @@
 +
 +	spin_lock_irqsave(&queue->irqlock, flags);
 +	while (!list_empty(&queue->irqqueue)) {
-+		buf = list_entry(queue->irqqueue.next, struct uvc_buffer, queue);
++		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue);
 +		list_del(&buf->queue);
 +		buf->state = UVC_BUF_STATE_ERROR;
 +		wake_up(&buf->wait);
@@ -3924,7 +4145,7 @@
 +	spin_lock_irqsave(&queue->irqlock, flags);
 +	list_del(&buf->queue);
 +	if (!list_empty(&queue->irqqueue))
-+		nextbuf = list_entry(queue->irqqueue.next, struct uvc_buffer,
++		nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
 +					queue);
 +	else
 +		nextbuf = NULL;
@@ -3939,10 +4160,10 @@
 +
 diff --git a/drivers/media/video/uvcvideo/uvc_status.c b/drivers/media/video/uvcvideo/uvc_status.c
 new file mode 100644
-index 0000000..a944152
+index 0000000..4be8de4
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_status.c
-@@ -0,0 +1,153 @@
+@@ -0,0 +1,220 @@
 +/*
 + *      uvc_status.c  --  USB Video Class driver
 + *
@@ -3957,10 +4178,72 @@
 + */
 +
 +#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/input.h>
 +#include <linux/usb.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#include <linux/usb_input.h>
++#else
++#include <linux/usb/input.h>
++#endif
 +
 +#include "uvcvideo.h"
 +
++/* --------------------------------------------------------------------------
++ * Input device
++ */
++static int uvc_input_init(struct uvc_device *dev)
++{
++	struct usb_device *udev = dev->udev;
++	struct input_dev *input;
++	char *phys = NULL;
++	int ret;
++
++	input = input_allocate_device();
++	if (input == NULL)
++		return -ENOMEM;
++
++	phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath),
++			GFP_KERNEL);
++	if (phys == NULL) {
++		ret = -ENOMEM;
++		goto error;
++	}
++	sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath);
++
++	input->name = dev->name;
++	input->phys = phys;
++	usb_to_input_id(udev, &input->id);
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
++	input->dev.parent = &dev->intf->dev;
++#else
++	input->cdev.dev = &dev->intf->dev;
++#endif
++
++	set_bit(EV_KEY, input->evbit);
++	set_bit(BTN_0, input->keybit);
++
++	if ((ret = input_register_device(input)) < 0)
++		goto error;
++
++	dev->input = input;
++	return 0;
++
++error:
++	input_free_device(input);
++	kfree(phys);
++	return ret;
++}
++
++static void uvc_input_cleanup(struct uvc_device *dev)
++{
++	if (dev->input)
++		input_unregister_device(dev->input);
++}
++
++/* --------------------------------------------------------------------------
++ * Status interrupt endpoint
++ */
 +static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
 +{
 +	if (len < 3) {
@@ -3974,6 +4257,8 @@
 +			return;
 +		uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
 +			data[1], data[3] ? "pressed" : "released", len);
++		if (dev->input)
++			input_report_key(dev->input, BTN_0, data[3]);
 +	} else {
 +		uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
 +			"len %d.\n", data[1], data[2], data[3], len);
@@ -4055,6 +4340,8 @@
 +	if (ep == NULL)
 +		return 0;
 +
++	uvc_input_init(dev);
++
 +	dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
 +	if (dev->int_urb == NULL)
 +		return -ENOMEM;
@@ -4080,6 +4367,7 @@
 +{
 +	usb_kill_urb(dev->int_urb);
 +	usb_free_urb(dev->int_urb);
++	uvc_input_cleanup(dev);
 +}
 +
 +int uvc_status_suspend(struct uvc_device *dev)
@@ -4098,10 +4386,10 @@
 +
 diff --git a/drivers/media/video/uvcvideo/uvc_v4l2.c b/drivers/media/video/uvcvideo/uvc_v4l2.c
 new file mode 100644
-index 0000000..fcd2c6e
+index 0000000..c335758
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_v4l2.c
-@@ -0,0 +1,1112 @@
+@@ -0,0 +1,1087 @@
 +/*
 + *      uvcvideo.c  --  USB Video Class driver
 + *
@@ -4150,22 +4438,17 @@
 +	struct uvc_menu_info *menu_info;
 +	struct uvc_control_mapping *mapping;
 +	struct uvc_control *ctrl;
-+	__u32 i;
 +
 +	ctrl = uvc_find_control(video, query_menu->id, &mapping);
 +	if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
 +		return -EINVAL;
 +
-+	menu_info = mapping->menu_info;
-+
-+	for (i = 0; i < mapping->menu_count; ++i, ++menu_info) {
-+		if (query_menu->index == menu_info->index) {
-+			strncpy(query_menu->name, menu_info->name, 32);
-+			return 0;
-+		}
-+	}
++	if (query_menu->index >= mapping->menu_count)
++		return -EINVAL;
 +
-+	return -EINVAL;
++	menu_info = &mapping->menu_info[query_menu->index];
++	strncpy(query_menu->name, menu_info->name, 32);
++	return 0;
 +}
 +
 +/*
@@ -4706,7 +4989,7 @@
 +		if (selector == NULL) {
 +			if (index != 0)
 +				return -EINVAL;
-+			iterm = list_entry(video->iterms.next,
++			iterm = list_first_entry(&video->iterms,
 +					struct uvc_entity, chain);
 +			pin = iterm->id;
 +		} else if (pin < selector->selector.bNrInPins) {
@@ -4949,19 +5232,15 @@
 +	case VIDIOC_QUERYBUF:
 +	{
 +		struct v4l2_buffer *buf = arg;
-+		struct uvc_buffer *ubuf;
 +
-+		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-+		    buf->index >= video->queue.count)
++		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 +			return -EINVAL;
 +
 +		if (!uvc_has_privileges(handle))
 +			return -EBUSY;
 +
-+		ubuf = &video->queue.buffer[buf->index];
-+		uvc_query_buffer(ubuf, buf);
++		return uvc_query_buffer(&video->queue, buf);
 +	}
-+		break;
 +
 +	case VIDIOC_QBUF:
 +		if (!uvc_has_privileges(handle))
@@ -5178,26 +5457,10 @@
 +{
 +	struct video_device *vdev = video_devdata(file);
 +	struct uvc_video_device *video = video_get_drvdata(vdev);
-+	struct uvc_buffer *buf;
-+	unsigned int mask = 0;
 +
 +	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
 +
-+	mutex_lock(&video->queue.mutex);
-+	if (list_empty(&video->queue.mainqueue)) {
-+		mask |= POLLERR;
-+		goto done;
-+	}
-+	buf = list_entry(video->queue.mainqueue.next, struct uvc_buffer, stream);
-+
-+	poll_wait(file, &buf->wait, wait);
-+	if (buf->state == UVC_BUF_STATE_DONE ||
-+	    buf->state == UVC_BUF_STATE_ERROR)
-+		mask |= POLLIN | POLLRDNORM;
-+
-+done:
-+	mutex_unlock(&video->queue.mutex);
-+	return mask;
++	return uvc_queue_poll(&video->queue, file, wait);
 +}
 +
 +struct file_operations uvc_fops = {
@@ -5216,10 +5479,10 @@
 +
 diff --git a/drivers/media/video/uvcvideo/uvc_video.c b/drivers/media/video/uvcvideo/uvc_video.c
 new file mode 100644
-index 0000000..2f33732
+index 0000000..cb89a7a
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvc_video.c
-@@ -0,0 +1,913 @@
+@@ -0,0 +1,922 @@
 +/*
 + *      uvcvideo.c  --  USB Video Class driver
 + *
@@ -5242,6 +5505,7 @@
 +#include <linux/vmalloc.h>
 +#include <linux/wait.h>
 +#include <asm/atomic.h>
++#include <asm/unaligned.h>
 +
 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
 +#include <media/v4l2-common.h>
@@ -5309,11 +5573,14 @@
 +	ctrl->wCompQuality = le16_to_cpup((__le16*)&data[12]);
 +	ctrl->wCompWindowSize = le16_to_cpup((__le16*)&data[14]);
 +	ctrl->wDelay = le16_to_cpup((__le16*)&data[16]);
-+	ctrl->dwMaxVideoFrameSize = le32_to_cpup((__le32*)&data[18]);
-+	ctrl->dwMaxPayloadTransferSize = le32_to_cpup((__le32*)&data[22]);
++	ctrl->dwMaxVideoFrameSize =
++		le32_to_cpu(get_unaligned((__le32*)&data[18]));
++	ctrl->dwMaxPayloadTransferSize =
++		le32_to_cpu(get_unaligned((__le32*)&data[22]));
 +
 +	if (size == 34) {
-+		ctrl->dwClockFrequency = le32_to_cpup((__le32*)&data[26]);
++		ctrl->dwClockFrequency =
++			le32_to_cpu(get_unaligned((__le32*)&data[26]));
 +		ctrl->bmFramingInfo = data[30];
 +		ctrl->bPreferedVersion = data[31];
 +		ctrl->bMinVersion = data[32];
@@ -5335,9 +5602,11 @@
 +		struct uvc_format *format = NULL;
 +		struct uvc_frame *frame = NULL;
 +
-+		if (ctrl->bFormatIndex <= video->streaming->nformats)
++		if (ctrl->bFormatIndex <= video->streaming->nformats &&
++		    ctrl->bFormatIndex != 0)
 +			format = &video->streaming->format[ctrl->bFormatIndex - 1];
-+		if (format && ctrl->bFrameIndex <= format->nframes) {
++		if (format && ctrl->bFrameIndex <= format->nframes &&
++		    ctrl->bFrameIndex != 0) {
 +			frame = &format->frame[ctrl->bFrameIndex - 1];
 +			ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize;
 +		}
@@ -5367,11 +5636,14 @@
 +	/* Note: Some of the fields below are not required for IN devices (see
 +	 * UVC spec, 4.3.1.1), but we still copy them in case support for OUT
 +	 * devices is added in the future. */
-+	*(__le32*)&data[18] = cpu_to_le32(ctrl->dwMaxVideoFrameSize);
-+	*(__le32*)&data[22] = cpu_to_le32(ctrl->dwMaxPayloadTransferSize);
++	put_unaligned(cpu_to_le32(ctrl->dwMaxVideoFrameSize),
++		(__le32*)&data[18]);
++	put_unaligned(cpu_to_le32(ctrl->dwMaxPayloadTransferSize),
++		(__le32*)&data[22]);
 +
 +	if (size == 34) {
-+		*(__le32*)&data[26] = cpu_to_le32(ctrl->dwClockFrequency);
++		put_unaligned(cpu_to_le32(ctrl->dwClockFrequency),
++			(__le32*)&data[26]);
 +		data[30] = ctrl->bmFramingInfo;
 +		data[31] = ctrl->bPreferedVersion;
 +		data[32] = ctrl->bMinVersion;
@@ -5744,7 +6016,7 @@
 +
 +	spin_lock_irqsave(&queue->irqlock, flags);
 +	if (!list_empty(&queue->irqqueue))
-+		buf = list_entry(queue->irqqueue.next, struct uvc_buffer, queue);
++		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue);
 +	spin_unlock_irqrestore(&queue->irqlock, flags);
 +
 +	video->decode(urb, video, buf);
@@ -6135,10 +6407,10 @@
 +
 diff --git a/drivers/media/video/uvcvideo/uvcvideo.h b/drivers/media/video/uvcvideo/uvcvideo.h
 new file mode 100644
-index 0000000..73b2146
+index 0000000..fb755c2
 --- /dev/null
 +++ b/drivers/media/video/uvcvideo/uvcvideo.h
-@@ -0,0 +1,787 @@
+@@ -0,0 +1,771 @@
 +#ifndef _USB_VIDEO_H_
 +#define _USB_VIDEO_H_
 +
@@ -6149,32 +6421,6 @@
 +#include "uvc_compat.h"
 +
 +/*
-+ * Private V4L2 control identifiers.
-+ */
-+
-+#define V4L2_CID_BACKLIGHT_COMPENSATION		(V4L2_CID_PRIVATE_BASE+0)
-+#define V4L2_CID_POWER_LINE_FREQUENCY		(V4L2_CID_PRIVATE_BASE+1)
-+#define V4L2_CID_SHARPNESS			(V4L2_CID_PRIVATE_BASE+2)
-+#define V4L2_CID_HUE_AUTO			(V4L2_CID_PRIVATE_BASE+3)
-+
-+#define V4L2_CID_FOCUS_AUTO			(V4L2_CID_PRIVATE_BASE+4)
-+#define V4L2_CID_FOCUS_ABSOLUTE			(V4L2_CID_PRIVATE_BASE+5)
-+#define V4L2_CID_FOCUS_RELATIVE			(V4L2_CID_PRIVATE_BASE+6)
-+
-+#define V4L2_CID_PAN_RELATIVE			(V4L2_CID_PRIVATE_BASE+7)
-+#define V4L2_CID_TILT_RELATIVE			(V4L2_CID_PRIVATE_BASE+8)
-+#define V4L2_CID_PANTILT_RESET			(V4L2_CID_PRIVATE_BASE+9)
-+
-+#define V4L2_CID_EXPOSURE_AUTO			(V4L2_CID_PRIVATE_BASE+10)
-+#define V4L2_CID_EXPOSURE_ABSOLUTE		(V4L2_CID_PRIVATE_BASE+11)
-+#define V4L2_CID_EXPOSURE_AUTO_PRIORITY		(V4L2_CID_PRIVATE_BASE+14)
-+
-+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE_AUTO	(V4L2_CID_PRIVATE_BASE+12)
-+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE	(V4L2_CID_PRIVATE_BASE+13)
-+
-+#define V4L2_CID_PRIVATE_LAST			V4L2_CID_EXPOSURE_AUTO_PRIORITY
-+
-+/*
 + * Dynamic controls
 + */
 +/* Data types for UVC control data */
@@ -6236,6 +6482,8 @@
 +
 +#ifdef __KERNEL__
 +
++#include <linux/poll.h>
++
 +/* --------------------------------------------------------------------------
 + * UVC constants
 + */
@@ -6434,6 +6682,10 @@
 +				 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 +#define UVC_GUID_FORMAT_UYVY	{ 'U',  'Y',  'V',  'Y', 0x00, 0x00, 0x10, 0x00, \
 +				 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
++#define UVC_GUID_FORMAT_Y800	{ 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
++				 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
++#define UVC_GUID_FORMAT_BY8	{ 'B',  'Y',  '8',  ' ', 0x00, 0x00, 0x10, 0x00, \
++				 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 +
 +
 +/* ------------------------------------------------------------------------
@@ -6494,7 +6746,7 @@
 +};
 +
 +struct uvc_menu_info {
-+	__u32 index;
++	__u32 value;
 +	__u8 name[32];
 +};
 +
@@ -6705,8 +6957,8 @@
 +	unsigned int count;
 +	unsigned int buf_size;
 +	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
-+	struct mutex mutex;
-+	spinlock_t irqlock;
++	struct mutex mutex;	/* protects buffers and mainqueue */
++	spinlock_t irqlock;	/* protects irqqueue */
 +
 +	struct list_head mainqueue;
 +	struct list_head irqqueue;
@@ -6756,6 +7008,7 @@
 +	struct usb_interface *intf;
 +	__u32 quirks;
 +	int intfnum;
++	char name[32];
 +
 +	enum uvc_device_state state;
 +	struct kref kref;
@@ -6773,6 +7026,7 @@
 +	struct usb_host_endpoint *int_ep;
 +	struct urb *int_urb;
 +	__u8 status[16];
++	struct input_dev *input;
 +
 +	/* Video Streaming interfaces */
 +	struct list_head streaming;
@@ -6846,7 +7100,7 @@
 +extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
 +		unsigned int nbuffers, unsigned int buflength);
 +extern int uvc_free_buffers(struct uvc_video_queue *queue);
-+extern void uvc_query_buffer(struct uvc_buffer *buf,
++extern int uvc_query_buffer(struct uvc_video_queue *queue,
 +		struct v4l2_buffer *v4l2_buf);
 +extern int uvc_queue_buffer(struct uvc_video_queue *queue,
 +		struct v4l2_buffer *v4l2_buf);
@@ -6856,6 +7110,8 @@
 +extern void uvc_queue_cancel(struct uvc_video_queue *queue);
 +extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
 +		struct uvc_buffer *buf);
++extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
++		struct file *file, poll_table *wait);
 +
 +/* V4L2 interface */
 +extern struct file_operations uvc_fops;
@@ -6926,3 +7182,10 @@
 +
 +#endif
 +
+diff --git a/drivers/media/video/uvcvideo/version.h b/drivers/media/video/uvcvideo/version.h
+new file mode 100644
+index 0000000..503c00c
+--- /dev/null
++++ b/drivers/media/video/uvcvideo/version.h
+@@ -0,0 +1 @@
++#define	DRIVER_VERSION	"SVN r200"




More information about the fedora-extras-commits mailing list