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