linux/drivers/media/video/uvc/uvc_isight.c
<<
>>
Prefs
   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
  39static 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
 102void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
 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(&stream->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(&stream->queue,
 134                                                        buf);
 135                } while (ret == -EAGAIN);
 136        }
 137}
 138