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 scm-commits
mailing list