Hi,
Follows the cleaned up patch. Thanks for te comments, the patch now
weight less than 8K !
Signed-off-by: Étienne Bersac <[EMAIL PROTECTED]>
---
Add built-in isight support to uvcvideo driver. Add a decode function
member to struct uvc_video_queue. The decode function has three
implementation yet : isoc, bulk and isight. uvc_isight.c contains the
the isight decode function implementation.
A BUILTIN_ISIGHT quirk is added allowing to determine wether to use
isight decode function or not.
Index: uvc_video.c
===================================================================
--- uvc_video.c (révision 149)
+++ uvc_video.c (copie de travail)
@@ -452,7 +452,7 @@
/*
* Completion handler for video URBs.
*/
-static void uvc_video_complete_isoc(struct urb *urb,
+static void uvc_video_decode_isoc(struct urb *urb,
struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
u8 *mem;
@@ -490,7 +490,7 @@
}
}
-static void uvc_video_complete_bulk(struct urb *urb,
+static void uvc_video_decode_bulk(struct urb *urb,
struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
u8 *mem;
@@ -585,10 +585,7 @@
buf = list_entry(queue->irqqueue.next, struct uvc_buffer,
queue);
spin_unlock_irqrestore(&queue->irqlock, flags);
- if (urb->number_of_packets)
- uvc_video_complete_isoc(urb, queue, buf);
- else
- uvc_video_complete_bulk(urb, queue, buf);
+ queue->decode(urb, queue, buf);
if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
@@ -937,6 +934,14 @@
video->streaming->cur_frame = frame;
atomic_set(&video->active, 1);
+ /* Select the video decoding function */
+ if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)
+ video->queue.decode = uvc_video_decode_isight;
+ else if (video->streaming->intf->num_altsetting > 1)
+ video->queue.decode = uvc_video_decode_isoc;
+ else
+ video->queue.decode = uvc_video_decode_bulk;
+
return 0;
}
Index: uvc_isight.c
===================================================================
--- uvc_isight.c (révision 0)
+++ uvc_isight.c (révision 0)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006-2007 Ivan N. Zlatev <[EMAIL PROTECTED]>
+ *
+ * Based on extract.c by Ronald S. Bultje <[EMAIL PROTECTED]>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA
+ */
+
+#include <linux/usb.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include "uvcvideo.h"
+
+/* Built-in iSight webcams implements most of UVC 1.0 except a
+ * different packet format. Instead of sending a header at the
+ * beginning of each isochronous transfer payload, the webcam sends a
+ * single header per image (on its own in a packet), followed by
+ * packets containing data only.
+ *
+ * Offset Size (bytes) Description
+ * ------------------------------------------------------------------
+ * 0x00 1 Header length
+ * 0x01 1 Flags (UVC-compliant)
+ * 0x02 4 Always equal to '11223344'
+ * 0x06 8 Always equal to 'deadbeefdeadface'
+ * 0x0e 16 Unknown
+ *
+ * The header can be prefixed by an optional, unknown-purpose byte.
+ */
+
+static int isight_decode (struct uvc_video_queue *queue, struct uvc_buffer
*buf,
+ const __u8 *data, unsigned int len)
+{
+ static const __u8 hdr[] = {
+ 0x11, 0x22, 0x33, 0x44,
+ 0xde, 0xad, 0xbe, 0xef,
+ 0xde, 0xad, 0xfa, 0xce
+ };
+
+ unsigned int maxlen, nbytes;
+ __u8 *mem;
+ int is_header = 0;
+
+ if (buf == NULL)
+ return 0;
+
+ if ((len >= 14 && memcmp (&data[2], hdr, 12) == 0) ||
+ (len >= 15 && memcmp (&data[3], hdr, 12) == 0)) {
+ uvc_trace(UVC_TRACE_FRAME, "iSight header found\n");
+ is_header = 1;
+ }
+
+ /* Synchronize to the input stream by waiting for a header packet. */
+ if (buf->state != UVC_BUF_STATE_ACTIVE) {
+ if (!is_header) {
+ uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of "
+ "sync).\n");
+ return 0;
+ }
+
+ buf->state = UVC_BUF_STATE_ACTIVE;
+ }
+
+ /* Mark the buffer as done if we're at the beginning of a new frame.
+ *
+ * Empty buffers (bytesused == 0) don't trigger end of frame detection
+ * as it doesn't make sense to return an empty buffer.
+ */
+ if (is_header && buf->buf.bytesused != 0) {
+ buf->state = UVC_BUF_STATE_DONE;
+ return -EAGAIN;
+ }
+
+ /* Copy the video data to the buffer. Skip header packets, as they
+ * contain no data.
+ */
+ if (!is_header) {
+ maxlen = buf->buf.length - buf->buf.bytesused;
+ mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ nbytes = min(len, maxlen);
+ memcpy(mem, data, nbytes);
+ buf->buf.bytesused += nbytes;
+
+ if (len > maxlen || buf->buf.bytesused == buf->buf.length) {
+ uvc_trace(UVC_TRACE_FRAME, "Frame complete
(overflow).\n");
+ buf->state = UVC_BUF_STATE_DONE;
+ }
+ }
+
+ return 0;
+}
+
+void uvc_video_decode_isight (struct urb *urb, struct uvc_video_queue *queue,
+ struct uvc_buffer *buf)
+{
+ int ret, i;
+
+ for (i = 0; i < urb->number_of_packets; ++i) {
+ if (urb->iso_frame_desc[i].status < 0) {
+ uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
+ "lost (%d).\n",
+ urb->iso_frame_desc[i].status);
+ }
+
+ /* Decode the payload packet.
+ * uvc_video_decode is entered twice when a frame transition
+ * has been detected because the end of frame can only be
+ * reliably detected when the first packet of the new frame
+ * is processed. The first pass detects the transition and
+ * closes the previous frame's buffer, the second pass
+ * processes the data of the first payload of the new frame.
+ */
+ do {
+ ret = isight_decode(queue, buf,
+ urb->transfer_buffer +
urb->iso_frame_desc[i].offset,
+
urb->iso_frame_desc[i].actual_length);
+
+ if (buf == NULL)
+ break;
+
+ if (buf->state == UVC_BUF_STATE_DONE ||
+ buf->state == UVC_BUF_STATE_ERROR)
+ buf = uvc_queue_next_buffer(queue, buf);
+ } while (ret == -EAGAIN);
+ }
+}
Index: uvc_driver.c
===================================================================
--- uvc_driver.c (révision 149)
+++ uvc_driver.c (copie de travail)
@@ -1667,6 +1667,13 @@
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
},
+ /* Apple Built-In iSight */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x05ac,
+ .idProduct = 0x8501,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX
+ | UVC_QUIRK_BUILTIN_ISIGHT
+ },
/* Microsoft Lifecam NX-6000 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
Index: uvcvideo.h
===================================================================
--- uvcvideo.h (révision 149)
+++ uvcvideo.h (copie de travail)
@@ -311,6 +311,7 @@
#define UVC_QUIRK_STATUS_INTERVAL 0x00000001
#define UVC_QUIRK_PROBE_MINMAX 0x00000002
#define UVC_QUIRK_PROBE_EXTRAFIELDS 0x00000004
+#define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
@@ -576,6 +577,9 @@
struct list_head mainqueue;
struct list_head irqqueue;
+
+ void (*decode) (struct urb *urb, struct uvc_video_queue *queue,
+ struct uvc_buffer *buf);
};
struct uvc_video_device {
@@ -764,6 +768,10 @@
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_queue *queue,
+ struct uvc_buffer *buf);
+
#endif /* __KERNEL__ */
#endif
Index: Makefile
===================================================================
--- Makefile (révision 149)
+++ Makefile (copie de travail)
@@ -5,7 +5,7 @@
PWD := $(shell pwd)
obj-m := uvcvideo.o
-uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o
+uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o
uvc_isight.o
all: uvcvideo
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel