Merge branch 'topic/hda' into for-linus
[linux-2.6] / drivers / media / video / uvc / uvc_isight.c
1 /*
2  *      uvc_isight.c  --  USB Video Class driver - iSight support
3  *
4  *      Copyright (C) 2006-2007
5  *              Ivan N. Zlatev <contact@i-nz.net>
6  *      Copyright (C) 2008-2009
7  *              Laurent Pinchart <laurent.pinchart@skynet.be>
8  *
9  *      This program is free software; you can redistribute it and/or modify
10  *      it under the terms of the GNU General Public License as published by
11  *      the Free Software Foundation; either version 2 of the License, or
12  *      (at your option) any later version.
13  *
14  */
15
16 #include <linux/usb.h>
17 #include <linux/kernel.h>
18 #include <linux/mm.h>
19
20 #include "uvcvideo.h"
21
22 /* Built-in iSight webcams implements most of UVC 1.0 except a
23  * different packet format. Instead of sending a header at the
24  * beginning of each isochronous transfer payload, the webcam sends a
25  * single header per image (on its own in a packet), followed by
26  * packets containing data only.
27  *
28  * Offset   Size (bytes)        Description
29  * ------------------------------------------------------------------
30  * 0x00         1       Header length
31  * 0x01         1       Flags (UVC-compliant)
32  * 0x02         4       Always equal to '11223344'
33  * 0x06         8       Always equal to 'deadbeefdeadface'
34  * 0x0e         16      Unknown
35  *
36  * The header can be prefixed by an optional, unknown-purpose byte.
37  */
38
39 static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
40                 const __u8 *data, unsigned int len)
41 {
42         static const __u8 hdr[] = {
43                 0x11, 0x22, 0x33, 0x44,
44                 0xde, 0xad, 0xbe, 0xef,
45                 0xde, 0xad, 0xfa, 0xce
46         };
47
48         unsigned int maxlen, nbytes;
49         __u8 *mem;
50         int is_header = 0;
51
52         if (buf == NULL)
53                 return 0;
54
55         if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) ||
56             (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) {
57                 uvc_trace(UVC_TRACE_FRAME, "iSight header found\n");
58                 is_header = 1;
59         }
60
61         /* Synchronize to the input stream by waiting for a header packet. */
62         if (buf->state != UVC_BUF_STATE_ACTIVE) {
63                 if (!is_header) {
64                         uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of "
65                                   "sync).\n");
66                         return 0;
67                 }
68
69                 buf->state = UVC_BUF_STATE_ACTIVE;
70         }
71
72         /* Mark the buffer as done if we're at the beginning of a new frame.
73          *
74          * Empty buffers (bytesused == 0) don't trigger end of frame detection
75          * as it doesn't make sense to return an empty buffer.
76          */
77         if (is_header && buf->buf.bytesused != 0) {
78                 buf->state = UVC_BUF_STATE_DONE;
79                 return -EAGAIN;
80         }
81
82         /* Copy the video data to the buffer. Skip header packets, as they
83          * contain no data.
84          */
85         if (!is_header) {
86                 maxlen = buf->buf.length - buf->buf.bytesused;
87                 mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
88                 nbytes = min(len, maxlen);
89                 memcpy(mem, data, nbytes);
90                 buf->buf.bytesused += nbytes;
91
92                 if (len > maxlen || buf->buf.bytesused == buf->buf.length) {
93                         uvc_trace(UVC_TRACE_FRAME, "Frame complete "
94                                   "(overflow).\n");
95                         buf->state = UVC_BUF_STATE_DONE;
96                 }
97         }
98
99         return 0;
100 }
101
102 void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
103                 struct uvc_buffer *buf)
104 {
105         int ret, i;
106
107         for (i = 0; i < urb->number_of_packets; ++i) {
108                 if (urb->iso_frame_desc[i].status < 0) {
109                         uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
110                                   "lost (%d).\n",
111                                   urb->iso_frame_desc[i].status);
112                 }
113
114                 /* Decode the payload packet.
115                  * uvc_video_decode is entered twice when a frame transition
116                  * has been detected because the end of frame can only be
117                  * reliably detected when the first packet of the new frame
118                  * is processed. The first pass detects the transition and
119                  * closes the previous frame's buffer, the second pass
120                  * processes the data of the first payload of the new frame.
121                  */
122                 do {
123                         ret = isight_decode(&video->queue, buf,
124                                         urb->transfer_buffer +
125                                         urb->iso_frame_desc[i].offset,
126                                         urb->iso_frame_desc[i].actual_length);
127
128                         if (buf == NULL)
129                                 break;
130
131                         if (buf->state == UVC_BUF_STATE_DONE ||
132                             buf->state == UVC_BUF_STATE_ERROR)
133                                 buf = uvc_queue_next_buffer(&video->queue, buf);
134                 } while (ret == -EAGAIN);
135         }
136 }