Laurent Pinchart | c0efd23 | 2008-06-30 15:04:50 -0300 | [diff] [blame] | 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 | } |