uvc_isight.c (3779B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * uvc_isight.c -- USB Video Class driver - iSight support 4 * 5 * Copyright (C) 2006-2007 6 * Ivan N. Zlatev <contact@i-nz.net> 7 * Copyright (C) 2008-2009 8 * Laurent Pinchart <laurent.pinchart@ideasonboard.com> 9 */ 10 11#include <linux/usb.h> 12#include <linux/kernel.h> 13#include <linux/mm.h> 14 15#include "uvcvideo.h" 16 17/* Built-in iSight webcams implements most of UVC 1.0 except a 18 * different packet format. Instead of sending a header at the 19 * beginning of each isochronous transfer payload, the webcam sends a 20 * single header per image (on its own in a packet), followed by 21 * packets containing data only. 22 * 23 * Offset Size (bytes) Description 24 * ------------------------------------------------------------------ 25 * 0x00 1 Header length 26 * 0x01 1 Flags (UVC-compliant) 27 * 0x02 4 Always equal to '11223344' 28 * 0x06 8 Always equal to 'deadbeefdeadface' 29 * 0x0e 16 Unknown 30 * 31 * The header can be prefixed by an optional, unknown-purpose byte. 32 */ 33 34static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, 35 const u8 *data, unsigned int len) 36{ 37 static const u8 hdr[] = { 38 0x11, 0x22, 0x33, 0x44, 39 0xde, 0xad, 0xbe, 0xef, 40 0xde, 0xad, 0xfa, 0xce 41 }; 42 43 struct uvc_streaming *stream = uvc_queue_to_stream(queue); 44 unsigned int maxlen, nbytes; 45 u8 *mem; 46 int is_header = 0; 47 48 if (buf == NULL) 49 return 0; 50 51 if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) || 52 (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) { 53 uvc_dbg(stream->dev, FRAME, "iSight header found\n"); 54 is_header = 1; 55 } 56 57 /* Synchronize to the input stream by waiting for a header packet. */ 58 if (buf->state != UVC_BUF_STATE_ACTIVE) { 59 if (!is_header) { 60 uvc_dbg(stream->dev, FRAME, 61 "Dropping packet (out of sync)\n"); 62 return 0; 63 } 64 65 buf->state = UVC_BUF_STATE_ACTIVE; 66 } 67 68 /* Mark the buffer as done if we're at the beginning of a new frame. 69 * 70 * Empty buffers (bytesused == 0) don't trigger end of frame detection 71 * as it doesn't make sense to return an empty buffer. 72 */ 73 if (is_header && buf->bytesused != 0) { 74 buf->state = UVC_BUF_STATE_DONE; 75 return -EAGAIN; 76 } 77 78 /* Copy the video data to the buffer. Skip header packets, as they 79 * contain no data. 80 */ 81 if (!is_header) { 82 maxlen = buf->length - buf->bytesused; 83 mem = buf->mem + buf->bytesused; 84 nbytes = min(len, maxlen); 85 memcpy(mem, data, nbytes); 86 buf->bytesused += nbytes; 87 88 if (len > maxlen || buf->bytesused == buf->length) { 89 uvc_dbg(stream->dev, FRAME, 90 "Frame complete (overflow)\n"); 91 buf->state = UVC_BUF_STATE_DONE; 92 } 93 } 94 95 return 0; 96} 97 98void uvc_video_decode_isight(struct uvc_urb *uvc_urb, struct uvc_buffer *buf, 99 struct uvc_buffer *meta_buf) 100{ 101 struct urb *urb = uvc_urb->urb; 102 struct uvc_streaming *stream = uvc_urb->stream; 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_dbg(stream->dev, FRAME, 108 "USB isochronous frame 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(&stream->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(&stream->queue, 132 buf); 133 } while (ret == -EAGAIN); 134 } 135}