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