Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      uvc_isight.c  --  USB Video Class driver - iSight support
0004  *
0005  *  Copyright (C) 2006-2007
0006  *      Ivan N. Zlatev <contact@i-nz.net>
0007  *  Copyright (C) 2008-2009
0008  *      Laurent Pinchart <laurent.pinchart@ideasonboard.com>
0009  */
0010 
0011 #include <linux/usb.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mm.h>
0014 
0015 #include "uvcvideo.h"
0016 
0017 /*
0018  * Built-in iSight webcams implements most of UVC 1.0 except a
0019  * different packet format. Instead of sending a header at the
0020  * beginning of each isochronous transfer payload, the webcam sends a
0021  * single header per image (on its own in a packet), followed by
0022  * packets containing data only.
0023  *
0024  * Offset   Size (bytes)    Description
0025  * ------------------------------------------------------------------
0026  * 0x00 1   Header length
0027  * 0x01 1   Flags (UVC-compliant)
0028  * 0x02 4   Always equal to '11223344'
0029  * 0x06 8   Always equal to 'deadbeefdeadface'
0030  * 0x0e 16  Unknown
0031  *
0032  * The header can be prefixed by an optional, unknown-purpose byte.
0033  */
0034 
0035 static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
0036         const u8 *data, unsigned int len)
0037 {
0038     static const u8 hdr[] = {
0039         0x11, 0x22, 0x33, 0x44,
0040         0xde, 0xad, 0xbe, 0xef,
0041         0xde, 0xad, 0xfa, 0xce
0042     };
0043 
0044     struct uvc_streaming *stream = uvc_queue_to_stream(queue);
0045     unsigned int maxlen, nbytes;
0046     u8 *mem;
0047     int is_header = 0;
0048 
0049     if (buf == NULL)
0050         return 0;
0051 
0052     if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) ||
0053         (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) {
0054         uvc_dbg(stream->dev, FRAME, "iSight header found\n");
0055         is_header = 1;
0056     }
0057 
0058     /* Synchronize to the input stream by waiting for a header packet. */
0059     if (buf->state != UVC_BUF_STATE_ACTIVE) {
0060         if (!is_header) {
0061             uvc_dbg(stream->dev, FRAME,
0062                 "Dropping packet (out of sync)\n");
0063             return 0;
0064         }
0065 
0066         buf->state = UVC_BUF_STATE_ACTIVE;
0067     }
0068 
0069     /*
0070      * Mark the buffer as done if we're at the beginning of a new frame.
0071      *
0072      * Empty buffers (bytesused == 0) don't trigger end of frame detection
0073      * as it doesn't make sense to return an empty buffer.
0074      */
0075     if (is_header && buf->bytesused != 0) {
0076         buf->state = UVC_BUF_STATE_DONE;
0077         return -EAGAIN;
0078     }
0079 
0080     /*
0081      * Copy the video data to the buffer. Skip header packets, as they
0082      * contain no data.
0083      */
0084     if (!is_header) {
0085         maxlen = buf->length - buf->bytesused;
0086         mem = buf->mem + buf->bytesused;
0087         nbytes = min(len, maxlen);
0088         memcpy(mem, data, nbytes);
0089         buf->bytesused += nbytes;
0090 
0091         if (len > maxlen || buf->bytesused == buf->length) {
0092             uvc_dbg(stream->dev, FRAME,
0093                 "Frame complete (overflow)\n");
0094             buf->state = UVC_BUF_STATE_DONE;
0095         }
0096     }
0097 
0098     return 0;
0099 }
0100 
0101 void uvc_video_decode_isight(struct uvc_urb *uvc_urb, struct uvc_buffer *buf,
0102             struct uvc_buffer *meta_buf)
0103 {
0104     struct urb *urb = uvc_urb->urb;
0105     struct uvc_streaming *stream = uvc_urb->stream;
0106     int ret, i;
0107 
0108     for (i = 0; i < urb->number_of_packets; ++i) {
0109         if (urb->iso_frame_desc[i].status < 0) {
0110             uvc_dbg(stream->dev, FRAME,
0111                 "USB isochronous frame lost (%d)\n",
0112                 urb->iso_frame_desc[i].status);
0113         }
0114 
0115         /*
0116          * Decode the payload packet.
0117          *
0118          * uvc_video_decode is entered twice when a frame transition
0119          * has been detected because the end of frame can only be
0120          * reliably detected when the first packet of the new frame
0121          * is processed. The first pass detects the transition and
0122          * closes the previous frame's buffer, the second pass
0123          * processes the data of the first payload of the new frame.
0124          */
0125         do {
0126             ret = isight_decode(&stream->queue, buf,
0127                     urb->transfer_buffer +
0128                     urb->iso_frame_desc[i].offset,
0129                     urb->iso_frame_desc[i].actual_length);
0130 
0131             if (buf == NULL)
0132                 break;
0133 
0134             if (buf->state == UVC_BUF_STATE_DONE ||
0135                 buf->state == UVC_BUF_STATE_ERROR)
0136                 buf = uvc_queue_next_buffer(&stream->queue,
0137                             buf);
0138         } while (ret == -EAGAIN);
0139     }
0140 }