1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * USB video class driver: V4L2 interface implementation.
29  */
30 
31 #include <sys/usb/usba.h>
32 #include <sys/fcntl.h>
33 #include <sys/cmn_err.h>
34 
35 #include <sys/usb/clients/video/usbvc/usbvc_var.h>
36 #include <sys/usb/clients/video/usbvc/usbvc.h>
37 #include <sys/videodev2.h>
38 
39 static int usbvc_v4l2_set_format(usbvc_state_t *, struct v4l2_format *);
40 static int usbvc_v4l2_get_format(usbvc_state_t *, struct v4l2_format *);
41 static void usbvc_v4l2_query_buf(usbvc_state_t *, usbvc_buf_t *,
42 				struct v4l2_buffer *);
43 static int usbvc_v4l2_enqueue_buf(usbvc_state_t *, usbvc_buf_t *,
44 				struct v4l2_buffer *);
45 static int usbvc_v4l2_dequeue_buffer(usbvc_state_t *,
46 				struct v4l2_buffer *, int);
47 static int usbvc_v4l2_query_ctrl(usbvc_state_t *, struct v4l2_queryctrl *);
48 static int usbvc_v4l2_get_ctrl(usbvc_state_t *, struct v4l2_control *);
49 static int usbvc_v4l2_set_ctrl(usbvc_state_t *, struct v4l2_control *);
50 static int usbvc_v4l2_set_parm(usbvc_state_t *, struct v4l2_streamparm *);
51 static int usbvc_v4l2_get_parm(usbvc_state_t *, struct v4l2_streamparm *);
52 /* Video controls that supported by usbvc driver */
53 static usbvc_v4l2_ctrl_map_t usbvc_v4l2_ctrls[] = {
54 	{
55 		"Brightness",
56 		PU_BRIGHTNESS_CONTROL,
57 		2,
58 		0,
59 		V4L2_CTRL_TYPE_INTEGER
60 	},
61 	{
62 		"Contrast",
63 		PU_CONTRAST_CONTROL,
64 		2,
65 		1,
66 		V4L2_CTRL_TYPE_INTEGER
67 	},
68 	{
69 		"Saturation",
70 		PU_SATURATION_CONTROL,
71 		2,
72 		3,
73 		V4L2_CTRL_TYPE_INTEGER
74 	},
75 	{
76 		"Hue",
77 		PU_HUE_CONTROL,
78 		2,
79 		2,
80 		V4L2_CTRL_TYPE_INTEGER
81 	},
82 	{
83 		"Gamma",
84 		PU_GAMMA_CONTROL,
85 		2,
86 		5,
87 		V4L2_CTRL_TYPE_INTEGER
88 	}
89 };
90 
91 
92 /*
93  * V4L2 colorspaces.
94  */
95 static const uint8_t color_primaries[] = {
96 		0,
97 		V4L2_COLORSPACE_SRGB,
98 		V4L2_COLORSPACE_470_SYSTEM_M,
99 		V4L2_COLORSPACE_470_SYSTEM_BG,
100 		V4L2_COLORSPACE_SMPTE170M,
101 		V4L2_COLORSPACE_SMPTE240M,
102 };
103 
104 /* V4L2 ioctls */
105 int
106 usbvc_v4l2_ioctl(usbvc_state_t *usbvcp, int cmd, intptr_t arg, int mode)
107 {
108 	int	rv = 0;
109 
110 	switch (cmd) {
111 	case VIDIOC_QUERYCAP:	/* Query capabilities */
112 	{
113 		struct v4l2_capability caps;
114 
115 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
116 		    "V4L2 ioctl: VIDIOC_QUERYCAP");
117 		bzero(&caps, sizeof (caps));
118 		(void) strncpy((char *)&caps.driver, "usbvc",
119 		    sizeof (caps.driver));
120 		if (usbvcp->usbvc_reg->dev_product) {
121 			(void) strncpy((char *)&caps.card,
122 			    usbvcp->usbvc_reg->dev_product, sizeof (caps.card));
123 		} else {
124 			(void) strncpy((char *)&caps.card, "Generic USB video"
125 			    "class device", sizeof (caps.card));
126 		}
127 		(void) strncpy((char *)&caps.bus_info, "usb",
128 		    sizeof (caps.bus_info));
129 		caps.version = 1;
130 		caps.capabilities = V4L2_CAP_VIDEO_CAPTURE
131 		    | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
132 		USBVC_COPYOUT(caps);
133 
134 		break;
135 	}
136 	case VIDIOC_ENUM_FMT:
137 	{
138 		struct v4l2_fmtdesc	fmtdesc;
139 		usbvc_format_group_t	*fmtgrp;
140 		usbvc_stream_if_t	*strm_if;
141 
142 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
143 		    "V4L2 ioctl: VIDIOC_ENUM_FMT");
144 		USBVC_COPYIN(fmtdesc);
145 		mutex_enter(&usbvcp->usbvc_mutex);
146 		strm_if = usbvcp->usbvc_curr_strm;
147 		if (fmtdesc.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
148 		    fmtdesc.index >= strm_if->fmtgrp_cnt) {
149 			rv = EINVAL;
150 			mutex_exit(&usbvcp->usbvc_mutex);
151 
152 			break;
153 		}
154 		fmtgrp = &strm_if->format_group[fmtdesc.index];
155 		fmtdesc.pixelformat = fmtgrp->v4l2_pixelformat;
156 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
157 		    "V4L2 ioctl: VIDIOC_ENUM_FMT, idx=%d, grpcnt=%d",
158 		    fmtdesc.index, strm_if->fmtgrp_cnt);
159 
160 		switch (fmtgrp->format->bDescriptorSubType) {
161 		case VS_FORMAT_MJPEG:
162 			fmtdesc.flags = V4L2_FMT_FLAG_COMPRESSED;
163 			(void) strncpy(fmtdesc.description, "MJPEG",
164 			    sizeof (fmtdesc.description));
165 
166 			break;
167 		case VS_FORMAT_UNCOMPRESSED:
168 			fmtdesc.flags = 0;
169 			if (fmtdesc.pixelformat == V4L2_PIX_FMT_YUYV) {
170 				(void) strncpy(fmtdesc.description, "YUYV",
171 				    sizeof (fmtdesc.description));
172 			} else if (fmtdesc.pixelformat == V4L2_PIX_FMT_NV12) {
173 				(void) strncpy(fmtdesc.description, "NV12",
174 				    sizeof (fmtdesc.description));
175 			} else {
176 				(void) strncpy(fmtdesc.description,
177 				    "Unknown format",
178 				    sizeof (fmtdesc.description));
179 			}
180 
181 			break;
182 		default:
183 			fmtdesc.flags = 0;
184 			(void) strncpy(fmtdesc.description, "Unknown format",
185 			    sizeof (fmtdesc.description));
186 		}
187 
188 		mutex_exit(&usbvcp->usbvc_mutex);
189 		USBVC_COPYOUT(fmtdesc);
190 
191 		break;
192 	}
193 	case VIDIOC_S_FMT:
194 	{
195 		struct v4l2_format	fmt;
196 		usbvc_stream_if_t	*strm_if;
197 
198 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
199 		    "V4L2 ioctl: VIDIOC_S_FMT");
200 		mutex_enter(&usbvcp->usbvc_mutex);
201 		strm_if = usbvcp->usbvc_curr_strm;
202 
203 		/* If data I/O is in progress */
204 		if (strm_if->start_polling == 1) {
205 			rv = EBUSY;
206 			mutex_exit(&usbvcp->usbvc_mutex);
207 
208 			break;
209 		}
210 		mutex_exit(&usbvcp->usbvc_mutex);
211 
212 		USBVC_COPYIN(fmt);
213 		if (usbvc_v4l2_set_format(usbvcp, &fmt) != USB_SUCCESS) {
214 			rv = EFAULT;
215 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
216 			    usbvcp->usbvc_log_handle,
217 			    "V4L2 ioctl VIDIOC_S_FMT fail");
218 		}
219 		USBVC_COPYOUT(fmt);
220 
221 		break;
222 	}
223 	case VIDIOC_G_FMT:
224 	{
225 		struct v4l2_format	fmt;
226 
227 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
228 		    "V4L2 ioctl: VIDIOC_G_FMT");
229 		USBVC_COPYIN(fmt);
230 
231 		if ((rv = usbvc_v4l2_get_format(usbvcp, &fmt)) != 0) {
232 
233 			break;
234 		}
235 
236 		USBVC_COPYOUT(fmt);
237 
238 		break;
239 	}
240 	case VIDIOC_REQBUFS: /* for memory mapping IO method */
241 	{
242 		struct v4l2_requestbuffers	reqbuf;
243 		uint_t				bufsize;
244 		usbvc_stream_if_t		*strm_if;
245 
246 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
247 		    "V4L2 ioctl: VIDIOC_REQBUFS");
248 		USBVC_COPYIN(reqbuf);
249 		if (reqbuf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
250 		    reqbuf.memory != V4L2_MEMORY_MMAP) {
251 			rv = EINVAL;
252 
253 			break;
254 		}
255 		mutex_enter(&usbvcp->usbvc_mutex);
256 		strm_if = usbvcp->usbvc_curr_strm;
257 		if (!strm_if) {
258 			mutex_exit(&usbvcp->usbvc_mutex);
259 			rv = EINVAL;
260 
261 			break;
262 		}
263 		if (reqbuf.count > USBVC_MAX_MAP_BUF_NUM) {
264 			mutex_exit(&usbvcp->usbvc_mutex);
265 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
266 			    usbvcp->usbvc_log_handle,
267 			    "V4L2 ioctl: req too many buffers, fail");
268 			rv = EINVAL;
269 
270 			break;
271 		}
272 
273 		/* If some bufs were already allocated */
274 		if (strm_if->buf_map.buf_cnt) {
275 			/*
276 			 * According to v4l2 spec, application can change the
277 			 * buffer number and also free all buffers if set
278 			 * count to 0
279 			 */
280 			if (reqbuf.count == 0) {
281 				if (strm_if->start_polling == 1) {
282 					mutex_exit(&usbvcp->usbvc_mutex);
283 					usb_pipe_stop_isoc_polling(
284 					    strm_if->datain_ph,
285 					    USB_FLAGS_SLEEP);
286 					mutex_enter(&usbvcp->usbvc_mutex);
287 					strm_if->start_polling = 0;
288 				}
289 				usbvc_free_map_bufs(usbvcp, strm_if);
290 				mutex_exit(&usbvcp->usbvc_mutex);
291 
292 				break;
293 			}
294 			if (reqbuf.count == strm_if->buf_map.buf_cnt) {
295 				mutex_exit(&usbvcp->usbvc_mutex);
296 				USB_DPRINTF_L2(PRINT_MASK_IOCTL,
297 				    usbvcp->usbvc_log_handle,
298 				    "v4l2 ioctls: req the same buffers"
299 				    " as we already have, just return success");
300 
301 				break;
302 			} else {
303 				/*
304 				 * req different number of bufs, according to
305 				 * v4l2 spec, this is not allowed when there
306 				 * are some bufs still mapped.
307 				 */
308 				mutex_exit(&usbvcp->usbvc_mutex);
309 				USB_DPRINTF_L2(PRINT_MASK_IOCTL,
310 				    usbvcp->usbvc_log_handle,
311 				    "v4l2 ioctls: req different number bufs"
312 				    "than the exist ones, fail");
313 				rv = EINVAL;
314 
315 				break;
316 			}
317 		}
318 
319 		if (reqbuf.count == 0) {
320 			mutex_exit(&usbvcp->usbvc_mutex);
321 			rv = EINVAL;
322 
323 			break;
324 		}
325 		LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, bufsize);
326 		if ((reqbuf.count =
327 		    (uint32_t)usbvc_alloc_map_bufs(usbvcp, strm_if,
328 		    reqbuf.count, bufsize)) == 0) {
329 			mutex_exit(&usbvcp->usbvc_mutex);
330 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
331 			    usbvcp->usbvc_log_handle,
332 			    "V4L2 ioctl: VIDIOC_REQBUFS: alloc fail");
333 			rv = EINVAL;
334 
335 			break;
336 		}
337 		mutex_exit(&usbvcp->usbvc_mutex);
338 
339 		/*
340 		 * return buf number that acctually allocated to application
341 		 */
342 		USBVC_COPYOUT(reqbuf);
343 
344 		break;
345 	}
346 	case VIDIOC_QUERYBUF: /* for memory mapping IO method */
347 	{
348 		struct v4l2_buffer	buf;
349 		usbvc_buf_grp_t		*usbvc_bufg;
350 
351 		USBVC_COPYIN(buf);
352 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
353 		    "V4L2 ioctl: VIDIOC_QUERYBUF: idx=%d", buf.index);
354 		mutex_enter(&usbvcp->usbvc_mutex);
355 		usbvc_bufg = &usbvcp->usbvc_curr_strm->buf_map;
356 		if ((buf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
357 		    (buf.index >= usbvc_bufg->buf_cnt)) {
358 			mutex_exit(&usbvcp->usbvc_mutex);
359 			rv = EINVAL;
360 
361 			break;
362 		}
363 
364 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
365 		    "V4L2 ioctl: VIDIOC_QUERYBUF: len=%d",
366 		    usbvc_bufg->buf_head[buf.index].v4l2_buf.length);
367 
368 		usbvc_v4l2_query_buf(usbvcp, &usbvc_bufg->buf_head[buf.index],
369 		    &buf);
370 		mutex_exit(&usbvcp->usbvc_mutex);
371 		USBVC_COPYOUT(buf);
372 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
373 		    "V4L2 ioctl: VIDIOC_QUERYBUF,(index=%d)len=%d",
374 		    buf.index, buf.length);
375 
376 		break;
377 	}
378 	case VIDIOC_QBUF:
379 	{
380 		struct v4l2_buffer	buf;
381 		usbvc_buf_grp_t		*usbvc_bufg;
382 
383 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
384 		    "V4L2 ioctl: VIDIOC_QBUF");
385 		USBVC_COPYIN(buf);
386 		mutex_enter(&usbvcp->usbvc_mutex);
387 		usbvc_bufg = &usbvcp->usbvc_curr_strm->buf_map;
388 
389 		if ((buf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
390 		    (buf.index >= usbvc_bufg->buf_cnt) ||
391 		    (buf.memory != V4L2_MEMORY_MMAP)) {
392 			mutex_exit(&usbvcp->usbvc_mutex);
393 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
394 			    usbvcp->usbvc_log_handle,  "V4L2 ioctl: "
395 			    "VIDIOC_QBUF error:index=%d,type=%d,memory=%d",
396 			    buf.index, buf.type, buf.memory);
397 			rv = EINVAL;
398 
399 			break;
400 		}
401 		rv = usbvc_v4l2_enqueue_buf(usbvcp,
402 		    &usbvc_bufg->buf_head[buf.index], &buf);
403 		if (rv < 0) {
404 			mutex_exit(&usbvcp->usbvc_mutex);
405 
406 			break;
407 		}
408 		mutex_exit(&usbvcp->usbvc_mutex);
409 		USBVC_COPYOUT(buf);
410 
411 		break;
412 	}
413 
414 	case VIDIOC_DQBUF:
415 	{
416 		struct v4l2_buffer	buf;
417 
418 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
419 		    "V4L2 ioctl: VIDIOC_DQBUF");
420 		USBVC_COPYIN(buf);
421 		mutex_enter(&usbvcp->usbvc_mutex);
422 		if ((rv = usbvc_v4l2_dequeue_buffer(usbvcp, &buf, mode)) != 0) {
423 			mutex_exit(&usbvcp->usbvc_mutex);
424 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
425 			    usbvcp->usbvc_log_handle, "V4L2 ioctl: "
426 			    "VIDIOC_DQBUF: fail, rv=%d", rv);
427 
428 			break;
429 		}
430 		mutex_exit(&usbvcp->usbvc_mutex);
431 		USBVC_COPYOUT(buf);
432 
433 		break;
434 	}
435 
436 	case VIDIOC_STREAMON:
437 	{
438 		int			type; /* v4l2_buf_type */
439 		usbvc_stream_if_t	*strm_if;
440 
441 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
442 		    "V4L2 ioctl: VIDIOC_STREAMON");
443 		USBVC_COPYIN(type);
444 		mutex_enter(&usbvcp->usbvc_mutex);
445 		strm_if = usbvcp->usbvc_curr_strm;
446 		if (!strm_if) {
447 			mutex_exit(&usbvcp->usbvc_mutex);
448 			rv = EINVAL;
449 
450 			break;
451 		}
452 		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
453 			mutex_exit(&usbvcp->usbvc_mutex);
454 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
455 			    usbvcp->usbvc_log_handle, "V4L2 ioctl: "
456 			    "VIDIOC_STREAMON: fail. Only capture type is"
457 			    " supported by now.");
458 			rv = EINVAL;
459 
460 			break;
461 		}
462 		/* if the first read, open isoc pipe */
463 		if (!strm_if->datain_ph) {
464 			if (usbvc_open_isoc_pipe(usbvcp, strm_if) !=
465 			    USB_SUCCESS) {
466 				mutex_exit(&usbvcp->usbvc_mutex);
467 				USB_DPRINTF_L2(PRINT_MASK_IOCTL,
468 				    usbvcp->usbvc_log_handle, "V4L2 ioctl:"
469 				    " first read, open pipe fail");
470 				rv = EINVAL;
471 
472 				break;
473 			}
474 		}
475 		/* If it is already started */
476 		if (strm_if->start_polling == 1) {
477 			mutex_exit(&usbvcp->usbvc_mutex);
478 
479 			break;
480 		}
481 		/* At present, VIDIOC_STREAMON supports mmap io only. */
482 		if (usbvc_start_isoc_polling(usbvcp, strm_if,
483 		    V4L2_MEMORY_MMAP) != USB_SUCCESS) {
484 			rv = EFAULT;
485 			mutex_exit(&usbvcp->usbvc_mutex);
486 
487 			break;
488 		}
489 		strm_if->start_polling = 1;
490 
491 		mutex_exit(&usbvcp->usbvc_mutex);
492 
493 		break;
494 	}
495 
496 	case VIDIOC_STREAMOFF:
497 	{
498 		int			type;	/* v4l2_buf_type */
499 		usbvc_stream_if_t	*strm_if;
500 
501 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
502 		    "V4L2 ioctl: VIDIOC_STREAMOFF");
503 		USBVC_COPYIN(type);
504 		mutex_enter(&usbvcp->usbvc_mutex);
505 		strm_if = usbvcp->usbvc_curr_strm;
506 		if (!strm_if) {
507 			mutex_exit(&usbvcp->usbvc_mutex);
508 			rv = EINVAL;
509 
510 			break;
511 		}
512 		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
513 			mutex_exit(&usbvcp->usbvc_mutex);
514 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
515 			    usbvcp->usbvc_log_handle, "V4L2 ioctl: "
516 			    "VIDIOC_STREAMON: fail. Only capture type is "
517 			    "supported by now.");
518 			rv = EINVAL;
519 
520 			break;
521 		}
522 
523 		/* Need close the isoc data pipe if any reads are performed. */
524 		strm_if = usbvcp->usbvc_curr_strm;
525 		if (strm_if->start_polling == 1) {
526 			mutex_exit(&usbvcp->usbvc_mutex);
527 			usb_pipe_stop_isoc_polling(strm_if->datain_ph,
528 			    USB_FLAGS_SLEEP);
529 			mutex_enter(&usbvcp->usbvc_mutex);
530 			strm_if->start_polling = 0;
531 		}
532 		mutex_exit(&usbvcp->usbvc_mutex);
533 
534 		break;
535 	}
536 
537 	case VIDIOC_ENUMINPUT:
538 	{
539 		struct v4l2_input input;
540 
541 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
542 		    "V4L2 ioctl: ENUMINPUT");
543 		USBVC_COPYIN(input);
544 
545 		if (input.index != 0) { /* Support only one INPUT now */
546 			rv = EINVAL;
547 
548 			break;
549 		}
550 		(void) strncpy((char *)input.name, "Camera Terminal",
551 		    sizeof (input.name));
552 		input.type = V4L2_INPUT_TYPE_CAMERA;
553 		USBVC_COPYOUT(input);
554 
555 		break;
556 	}
557 
558 	case VIDIOC_G_INPUT:
559 	{
560 		int input_idx = 0;	/* Support only one input now */
561 
562 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
563 		    "V4L2 ioctl: G_INPUT");
564 		USBVC_COPYOUT(input_idx);
565 
566 		break;
567 	}
568 
569 	case VIDIOC_S_INPUT:
570 	{
571 		int input_idx;
572 
573 		USBVC_COPYIN(input_idx);
574 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
575 		    "V4L2 ioctl: S_INPUT");
576 		if (input_idx != 0) {	/* Support only one input now */
577 			rv = EINVAL;
578 		}
579 
580 		break;
581 	}
582 
583 	/* Query the device that what kinds of video ctrls are supported */
584 	case VIDIOC_QUERYCTRL:
585 	{
586 		struct v4l2_queryctrl queryctrl;
587 
588 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
589 		    "V4L2 ioctl: QUERYCTRL");
590 		USBVC_COPYIN(queryctrl);
591 
592 		if (usbvc_v4l2_query_ctrl(usbvcp, &queryctrl) != USB_SUCCESS) {
593 			rv = EINVAL;
594 
595 			break;
596 		}
597 
598 		USBVC_COPYOUT(queryctrl);
599 
600 		break;
601 	}
602 	case VIDIOC_G_CTRL:
603 	{
604 		struct v4l2_control ctrl;
605 
606 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
607 		    "V4L2 ioctl: G_CTRL");
608 		USBVC_COPYIN(ctrl);
609 		if (usbvc_v4l2_get_ctrl(usbvcp, &ctrl) != USB_SUCCESS) {
610 			rv = EINVAL;
611 
612 			break;
613 		}
614 
615 		USBVC_COPYOUT(ctrl);
616 
617 		break;
618 	}
619 	case VIDIOC_S_CTRL:
620 	{
621 		struct v4l2_control ctrl;
622 
623 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
624 		    "V4L2 ioctl: S_CTRL");
625 		USBVC_COPYIN(ctrl);
626 		if (usbvc_v4l2_set_ctrl(usbvcp, &ctrl) != USB_SUCCESS) {
627 			rv = EINVAL;
628 
629 			break;
630 		}
631 
632 		USBVC_COPYOUT(ctrl);
633 
634 		break;
635 	}
636 	case VIDIOC_S_PARM:
637 	{
638 		struct v4l2_streamparm	parm;
639 		usbvc_stream_if_t	*strm_if;
640 
641 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
642 		    "V4L2 ioctl: VIDIOC_S_PARM");
643 		mutex_enter(&usbvcp->usbvc_mutex);
644 		strm_if = usbvcp->usbvc_curr_strm;
645 
646 		/* If data I/O is in progress */
647 		if (strm_if->start_polling == 1) {
648 			rv = EBUSY;
649 			mutex_exit(&usbvcp->usbvc_mutex);
650 
651 			break;
652 		}
653 		mutex_exit(&usbvcp->usbvc_mutex);
654 
655 		USBVC_COPYIN(parm);
656 
657 		/* Support capture only, so far. */
658 		if (parm.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
659 			rv = EINVAL;
660 
661 			break;
662 		}
663 
664 		if (usbvc_v4l2_set_parm(usbvcp, &parm) != USB_SUCCESS) {
665 			rv = EINVAL;
666 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
667 			    usbvcp->usbvc_log_handle,
668 			    "V4L2 ioctl VIDIOC_S_PARM fail");
669 		}
670 		USBVC_COPYOUT(parm);
671 
672 		break;
673 	}
674 	case VIDIOC_G_PARM:
675 	{
676 		struct v4l2_streamparm	parm;
677 
678 		USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
679 		    "V4L2 ioctl: VIDIOC_G_PARM");
680 		USBVC_COPYIN(parm);
681 
682 		/* Support capture only, so far. */
683 		if (parm.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
684 			rv = EINVAL;
685 
686 			break;
687 		}
688 
689 		if ((rv = usbvc_v4l2_get_parm(usbvcp, &parm)) != USB_SUCCESS) {
690 
691 			break;
692 		}
693 
694 		USBVC_COPYOUT(parm);
695 
696 		break;
697 	}
698 	/* These ioctls are for analog video standards. */
699 	case VIDIOC_G_STD:
700 	case VIDIOC_S_STD:
701 	case VIDIOC_ENUMSTD:
702 	case VIDIOC_QUERYSTD:
703 		rv = EINVAL;
704 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
705 		    "usbvc_v4l2_ioctl: not a supported cmd, cmd=%x", cmd);
706 
707 		break;
708 	default:
709 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
710 		    "usbvc_v4l2_ioctl: not a valid cmd value, cmd=%x", cmd);
711 		rv = ENOTTY;
712 	}
713 
714 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
715 	    "usbvc_v4l2_ioctl: exit, rv=%d", rv);
716 
717 	return (rv);
718 
719 }
720 
721 
722 /*
723  * Convert GUID in uncompressed format descriptor to the pixelformat element
724  * in struct v4l2_pix_format
725  */
726 uint32_t
727 usbvc_v4l2_guid2fcc(uint8_t *guid)
728 {
729 	uint32_t ret;
730 
731 	uint8_t y[16] = USBVC_FORMAT_GUID_YUY2;
732 	uint8_t n[16] = USBVC_FORMAT_GUID_NV12;
733 	if (!memcmp((void *)guid, (void *) &y[0], 16)) {
734 		ret = V4L2_PIX_FMT_YUYV;
735 
736 		return (ret);
737 	}
738 	if (!memcmp((void *)guid, (void *) &n, 16)) {
739 		ret = V4L2_PIX_FMT_NV12;
740 
741 		return (ret);
742 	}
743 
744 	return (0);
745 }
746 
747 
748 /*
749  * Find a frame which has the closest image size as the input args
750  * (width, height)
751  */
752 static usbvc_frames_t *
753 usbvc_match_image_size(uint32_t width, uint32_t height,
754     usbvc_format_group_t *fmtgrp)
755 {
756 	uint32_t w, h, diff, sz, i;
757 	usbvc_frames_t *frame = NULL;
758 	usbvc_frame_descr_t *descr;
759 
760 	diff = 0xffffffff;
761 
762 	for (i = 0; i < fmtgrp->frame_cnt; i++) {
763 
764 		descr = fmtgrp->frames[i].descr;
765 		if (descr == NULL) {
766 
767 			continue;
768 		}
769 		LE_TO_UINT16(descr->wWidth, 0, w);
770 		LE_TO_UINT16(descr->wHeight, 0, h);
771 
772 		sz = min(w, width) * min(h, height);
773 		sz = (w * h + width * height - sz * 2);
774 		if (sz < diff) {
775 			frame = &fmtgrp->frames[i];
776 			diff = sz;
777 		}
778 
779 		if (diff == 0) {
780 
781 			return (frame);
782 		}
783 	}
784 
785 	return (frame);
786 }
787 
788 
789 /* Implement ioctl VIDIOC_S_FMT, set a video format */
790 static int
791 usbvc_v4l2_set_format(usbvc_state_t *usbvcp, struct v4l2_format *format)
792 {
793 	usbvc_vs_probe_commit_t	ctrl, ctrl_max, ctrl_min, ctrl_curr;
794 	usbvc_stream_if_t	*strm_if;
795 	usbvc_format_group_t	*fmtgrp;
796 	usbvc_frames_t		*frame;
797 	uint32_t		w, h, interval, bandwidth;
798 	uint8_t			type, i;
799 
800 	mutex_enter(&usbvcp->usbvc_mutex);
801 
802 	/*
803 	 * Get the first stream interface. Todo: deal with multi stream
804 	 * interfaces.
805 	 */
806 	strm_if = usbvcp->usbvc_curr_strm;
807 
808 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
809 	    "usbvc_v4l2_set_format: strm_if->fmtgrp_cnt=%d",
810 	    strm_if->fmtgrp_cnt);
811 
812 	/* Find the proper format group according to compress type and guid */
813 	for (i = 0; i < strm_if->fmtgrp_cnt; i++) {
814 		fmtgrp = &strm_if->format_group[i];
815 
816 		/*
817 		 * If v4l2_pixelformat is NULL, then that means there is not
818 		 * a parsed format in format_group[i].
819 		 */
820 		if (!fmtgrp->v4l2_pixelformat || fmtgrp->frame_cnt == 0) {
821 			USB_DPRINTF_L3(PRINT_MASK_DEVCTRL,
822 			    usbvcp->usbvc_log_handle,
823 			    "usbvc_set_default_stream_fmt: no frame, fail");
824 
825 			continue;
826 		}
827 		type = fmtgrp->format->bDescriptorSubType;
828 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
829 		    "usbvc_v4l2_set_format: type =%x, i =%d", type, i);
830 
831 		if ((type == VS_FORMAT_MJPEG) ||
832 		    (type == VS_FORMAT_UNCOMPRESSED)) {
833 			if (format->fmt.pix.pixelformat ==
834 			    fmtgrp->v4l2_pixelformat) {
835 
836 				break;
837 			}
838 		}
839 	}
840 
841 	if (i >= strm_if->fmtgrp_cnt) {
842 		mutex_exit(&usbvcp->usbvc_mutex);
843 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
844 		    "usbvc_v4l2_set_format: can't find a proper format, "
845 		    "pixelformat=%x", format->fmt.pix.pixelformat);
846 
847 		return (USB_FAILURE);
848 	}
849 
850 	fmtgrp = &strm_if->format_group[i];
851 
852 	frame = usbvc_match_image_size(format->fmt.pix.width,
853 	    format->fmt.pix.height, fmtgrp);
854 
855 	if (frame == NULL) {
856 		mutex_exit(&usbvcp->usbvc_mutex);
857 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
858 		    "usbvc_v4l2_set_format: can't find a proper frame, rw=%d, "
859 		    "rh=%d", format->fmt.pix.width, format->fmt.pix.height);
860 
861 		return (USB_FAILURE);
862 	}
863 
864 	/* frame interval */
865 	LE_TO_UINT32(frame->descr->dwDefaultFrameInterval, 0, interval);
866 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
867 	    "usbvc_v4l2_set_format: Default Frame Interval=%x", interval);
868 
869 	/*
870 	 * Begin negotiate formats.
871 	 */
872 	bzero((void *)&ctrl, sizeof (usbvc_vs_probe_commit_t));
873 
874 	/* dwFrameInterval is fixed */
875 	ctrl.bmHint[0] = 1;
876 
877 	ctrl.bFormatIndex = fmtgrp->format->bFormatIndex;
878 	ctrl.bFrameIndex = frame->descr->bFrameIndex;
879 	UINT32_TO_LE(interval, 0, ctrl.dwFrameInterval);
880 
881 	mutex_exit(&usbvcp->usbvc_mutex);
882 
883 	/* Probe, just a test before the real try */
884 	if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl, VS_PROBE_CONTROL)
885 	    != USB_SUCCESS) {
886 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
887 		    "usbvc_v4l2_set_format: set probe failed");
888 
889 		return (USB_FAILURE);
890 	}
891 
892 	/* Get max values */
893 	if (usbvc_vs_get_probe(usbvcp, strm_if, &ctrl_max, GET_MAX) !=
894 	    USB_SUCCESS) {
895 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
896 		    "usbvc_v4l2_set_format: get probe MAX failed");
897 
898 		return (USB_FAILURE);
899 	}
900 
901 	/* Use the best quality first */
902 	bcopy(&ctrl_max.wCompQuality, &ctrl.wCompQuality, 2);
903 
904 	/*
905 	 * By now, we've get some parametres of ctrl req, next try to set ctrl.
906 	 */
907 	for (i = 0; i < 2; i++) {
908 
909 		/* Probe */
910 		if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl,
911 		    VS_PROBE_CONTROL) != USB_SUCCESS) {
912 
913 			return (USB_FAILURE);
914 		}
915 
916 		/* Get current value after probe */
917 		if (usbvc_vs_get_probe(usbvcp, strm_if, &ctrl_curr, GET_CUR)
918 		    != USB_SUCCESS) {
919 
920 			return (USB_FAILURE);
921 		}
922 		LE_TO_UINT32(ctrl_curr.dwMaxPayloadTransferSize, 0, bandwidth);
923 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
924 		    "usbvc_v4l2_set_format: bandwidth=%x", bandwidth);
925 
926 		/*
927 		 * If the bandwidth does not exceed the max value of all the
928 		 * alternatives in this interface, we done.
929 		 */
930 		if (bandwidth <= strm_if->max_isoc_payload) {
931 
932 			break;
933 		}
934 		if (i >= 1) {
935 
936 			return (USB_FAILURE);
937 		}
938 
939 		/* Get minimum values since the bandwidth is not enough */
940 		if (usbvc_vs_get_probe(usbvcp, strm_if, &ctrl_min, GET_MIN) !=
941 		    USB_SUCCESS) {
942 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
943 			    usbvcp->usbvc_log_handle,
944 			    "usbvc_v4l2_set_format: get probe MIN failed");
945 
946 			return (USB_FAILURE);
947 		}
948 
949 		/* To keep simple, just use some minimum values to try again */
950 		bcopy(&ctrl_min.wKeyFrameRate, &ctrl_curr.wKeyFrameRate, 2);
951 		bcopy(&ctrl_min.wPFrameRate, &ctrl_curr.wPFrameRate, 2);
952 		bcopy(&ctrl_min.wCompWindowSize, &ctrl_curr.wCompWindowSize, 2);
953 		bcopy(&ctrl_max.wCompQuality, &ctrl_curr.wCompQuality, 2);
954 
955 		bcopy(&ctrl_curr, &ctrl,
956 		    sizeof (usbvc_vs_probe_commit_t));
957 	}
958 
959 	bcopy(&ctrl_curr, &ctrl, sizeof (usbvc_vs_probe_commit_t));
960 
961 	/* commit the values we negotiated above */
962 	if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl,
963 	    VS_COMMIT_CONTROL) != USB_SUCCESS) {
964 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
965 		    "usbvc_v4l2_set_format: set probe failed, i=%d", i);
966 
967 		return (USB_FAILURE);
968 	}
969 	mutex_enter(&usbvcp->usbvc_mutex);
970 
971 	/*
972 	 * It's good to check index here before use it. bFormatIndex is based
973 	 * on 1, and format_group[i] is based on 0, so minus 1
974 	 */
975 	i = ctrl.bFormatIndex - 1;
976 	if (i < strm_if->fmtgrp_cnt) {
977 		strm_if->cur_format_group = &strm_if->format_group[i];
978 	} else {
979 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
980 		    "usbvc_v4l2_set_format: format index out of range");
981 		mutex_exit(&usbvcp->usbvc_mutex);
982 
983 		return (USB_FAILURE);
984 	}
985 
986 	/* bFrameIndex is based on 1, and frames[i] is based on 0, so minus 1 */
987 	i = ctrl.bFrameIndex -1;
988 	if (i < strm_if->cur_format_group->frame_cnt) {
989 		strm_if->cur_format_group->cur_frame =
990 		    &strm_if->cur_format_group->frames[i];
991 	} else {
992 		mutex_exit(&usbvcp->usbvc_mutex);
993 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
994 		    "usbvc_v4l2_set_format: frame index out of range");
995 
996 		return (USB_FAILURE);
997 	}
998 
999 	/*
1000 	 * by now, the video format is set successfully. record the current
1001 	 * setting to strm_if->ctrl_pc
1002 	 */
1003 	bcopy(&ctrl_curr, &strm_if->ctrl_pc, sizeof (usbvc_vs_probe_commit_t));
1004 
1005 	format->fmt.pix.colorspace = fmtgrp->v4l2_color;
1006 	format->fmt.pix.field = V4L2_FIELD_NONE;
1007 	format->fmt.pix.priv = 0;
1008 
1009 	LE_TO_UINT16(frame->descr->wWidth, 0, w);
1010 	LE_TO_UINT16(frame->descr->wHeight, 0, h);
1011 	format->fmt.pix.width = w;
1012 	format->fmt.pix.height = h;
1013 	format->fmt.pix.bytesperline = fmtgrp->v4l2_bpp * w;
1014 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0,
1015 	    format->fmt.pix.sizeimage);
1016 
1017 	mutex_exit(&usbvcp->usbvc_mutex);
1018 
1019 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1020 	    "usbvc_v4l2_set_format: dwMaxVideoFrameSize=%x, w=%x, h=%x",
1021 	    format->fmt.pix.sizeimage, w, h);
1022 
1023 	return (USB_SUCCESS);
1024 }
1025 
1026 
1027 /* Implement ioctl VIDIOC_G_FMT, get the current video format */
1028 static int
1029 usbvc_v4l2_get_format(usbvc_state_t *usbvcp, struct v4l2_format *format)
1030 {
1031 	usbvc_stream_if_t	*strm_if;
1032 	usbvc_format_group_t	*fmtgrp;
1033 	uint16_t		w, h;
1034 
1035 	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1036 
1037 		return (EINVAL);
1038 	}
1039 	mutex_enter(&usbvcp->usbvc_mutex);
1040 
1041 	/* get the current interface. */
1042 	strm_if = usbvcp->usbvc_curr_strm;
1043 	fmtgrp = strm_if->cur_format_group;
1044 
1045 	if (!fmtgrp || !fmtgrp->cur_frame) {
1046 		mutex_exit(&usbvcp->usbvc_mutex);
1047 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1048 		    "usbvc_v4l2_get_format: fail, no current format or frame,"
1049 		    "fmtgrp=%p", (void *)fmtgrp);
1050 
1051 		return (EINVAL);
1052 	}
1053 	format->fmt.pix.colorspace = fmtgrp->v4l2_color;
1054 	format->fmt.pix.priv = 0;
1055 	format->fmt.pix.pixelformat = fmtgrp->v4l2_pixelformat;
1056 
1057 	LE_TO_UINT16(fmtgrp->cur_frame->descr->wWidth, 0, w);
1058 	LE_TO_UINT16(fmtgrp->cur_frame->descr->wHeight, 0, h);
1059 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1060 	    "v4l2 ioctl get format ");
1061 	format->fmt.pix.width = w;
1062 	format->fmt.pix.height = h;
1063 
1064 	format->fmt.pix.field = V4L2_FIELD_NONE;
1065 	format->fmt.pix.bytesperline = fmtgrp->v4l2_bpp * w;
1066 
1067 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0,
1068 	    format->fmt.pix.sizeimage);
1069 
1070 	mutex_exit(&usbvcp->usbvc_mutex);
1071 
1072 	return (0);
1073 }
1074 
1075 
1076 /*
1077  * Convert color space descriptor's bColorPrimaries to the colorspace element
1078  * in struct v4l2_pix_format
1079  */
1080 uint8_t
1081 usbvc_v4l2_colorspace(uint8_t color_prim)
1082 {
1083 
1084 	if (color_prim < NELEM(color_primaries)) {
1085 
1086 		return (color_primaries[color_prim]);
1087 	}
1088 
1089 	return (0);
1090 }
1091 
1092 
1093 /* Implement ioctl VIDIOC_QUERYBUF, get the buf status */
1094 static void
1095 usbvc_v4l2_query_buf(usbvc_state_t *usbvcp, usbvc_buf_t *usbvc_buf,
1096 	struct v4l2_buffer *v4l2_buf)
1097 {
1098 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1099 
1100 	bcopy(&(usbvc_buf->v4l2_buf), v4l2_buf, sizeof (struct v4l2_buffer));
1101 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1102 	    "usbvc_v4l2_query_buf: uv_buf_len=%d, len=%d",
1103 	    usbvc_buf->v4l2_buf.length, v4l2_buf->length);
1104 
1105 	if (usbvc_buf->status >= USBVC_BUF_MAPPED) {
1106 		v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
1107 	}
1108 
1109 	switch (usbvc_buf->status) {
1110 	case USBVC_BUF_DONE:
1111 	case USBVC_BUF_ERR:
1112 		v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
1113 
1114 		break;
1115 	case USBVC_BUF_EMPTY:
1116 		v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1117 
1118 		break;
1119 	case USBVC_BUF_INIT:
1120 	default:
1121 
1122 		break;
1123 	}
1124 }
1125 
1126 
1127 /* Implement ioctl VIDIOC_QBUF, queue a empty buf to the free list */
1128 static int
1129 usbvc_v4l2_enqueue_buf(usbvc_state_t *usbvcp, usbvc_buf_t *usbvc_buf,
1130 	struct v4l2_buffer *buf)
1131 {
1132 	usbvc_buf_t	*donebuf;
1133 	boolean_t	queued = B_FALSE;
1134 	usbvc_buf_grp_t	*bufgrp;
1135 
1136 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1137 
1138 	bufgrp = &usbvcp->usbvc_curr_strm->buf_map;
1139 
1140 	if (usbvc_buf == bufgrp->buf_filling) {
1141 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1142 		    "enqueue_buffer(%d) , want to queue buf_filling, "
1143 		    "just return success", buf->index);
1144 
1145 		return (0);
1146 	}
1147 
1148 	if (!list_is_empty(&bufgrp->uv_buf_done)) {
1149 		donebuf = (usbvc_buf_t *)list_head(&bufgrp->uv_buf_done);
1150 		while (donebuf) {
1151 
1152 			if (donebuf == &(bufgrp->buf_head[buf->index])) {
1153 				queued = B_TRUE;
1154 
1155 				break;
1156 			}
1157 			donebuf = (usbvc_buf_t *)list_next(&bufgrp->uv_buf_done,
1158 			    donebuf);
1159 		}
1160 	}
1161 	if (queued) {
1162 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1163 		    "enqueue_buffer(%d), still in done list, don't insert to"
1164 		    " free list", buf->index);
1165 
1166 		return (0);
1167 	}
1168 
1169 	if (usbvc_buf->status == USBVC_BUF_EMPTY) {
1170 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1171 		    "enqueue buffer(%d), already queued.", buf->index);
1172 
1173 		return (0);
1174 
1175 	}
1176 	if (usbvc_buf->status < USBVC_BUF_MAPPED) {
1177 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1178 		    "enqueue buffer(%d), state error, not mapped.", buf->index);
1179 
1180 		return (EINVAL);
1181 	}
1182 
1183 	/*
1184 	 * The buf is put to the buf free list when allocated, so, if the buf
1185 	 * is the first time to enqueue, just change the state to empty is
1186 	 * enough.
1187 	 */
1188 	if (usbvc_buf->status == USBVC_BUF_MAPPED) {
1189 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1190 		    "queue_buffer(%d), 1st time queue this buf", buf->index);
1191 
1192 		usbvc_buf->status = USBVC_BUF_EMPTY;
1193 
1194 	} else {
1195 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1196 		    "enqueue_buffer(%d) , USBVC_BUF_EMPTY", buf->index);
1197 
1198 		usbvc_buf->status = USBVC_BUF_EMPTY;
1199 		usbvc_buf->v4l2_buf.bytesused = 0;
1200 		list_insert_tail(&bufgrp->uv_buf_free, usbvc_buf);
1201 	}
1202 	buf->flags &= ~V4L2_BUF_FLAG_DONE;
1203 	buf->flags |= V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
1204 
1205 	return (0);
1206 }
1207 
1208 
1209 /* Implement ioctl VIDIOC_DQBUF, pick a buf from done list */
1210 static int
1211 usbvc_v4l2_dequeue_buffer(usbvc_state_t *usbvcp, struct v4l2_buffer *buf,
1212 	int mode)
1213 {
1214 	usbvc_buf_t *buf_done;
1215 
1216 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1217 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1218 	    "usbvc_v4l2_dequeue_buffer: idx=%x", buf->index);
1219 
1220 	/* v4l2 spec: app just set type and memory field */
1221 	if ((buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
1222 	    (buf->memory != V4L2_MEMORY_MMAP)) {
1223 
1224 		return (EINVAL);
1225 	}
1226 	if ((mode & (O_NDELAY|O_NONBLOCK)) &&
1227 	    (list_is_empty(&usbvcp->usbvc_curr_strm->buf_map.uv_buf_done))) {
1228 
1229 		/* non-blocking */
1230 		return (EAGAIN);
1231 	}
1232 
1233 	/* no available buffers, block here */
1234 	while (list_is_empty(&usbvcp->usbvc_curr_strm->buf_map.uv_buf_done)) {
1235 		USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1236 		    "usbvc_v4l2_dequeue_buffer: wait for done buf");
1237 		if (cv_wait_sig(&usbvcp->usbvc_mapio_cv, &usbvcp->usbvc_mutex)
1238 		    <= 0) {
1239 
1240 			/* no done buf and is signaled */
1241 			return (EINTR);
1242 		}
1243 		if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
1244 
1245 			/* Device is disconnected. */
1246 			return (EINTR);
1247 		}
1248 	}
1249 
1250 	buf_done = list_head(&usbvcp->usbvc_curr_strm->buf_map.uv_buf_done);
1251 
1252 	list_remove(&usbvcp->usbvc_curr_strm->buf_map.uv_buf_done, buf_done);
1253 
1254 	/*
1255 	 * just copy the v4l2_buf structure because app need only the index
1256 	 * value to locate the mapped memory
1257 	 */
1258 	bcopy(&buf_done->v4l2_buf, buf, sizeof (struct v4l2_buffer));
1259 	buf->flags |= V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_MAPPED;
1260 	buf->bytesused = buf_done->filled;
1261 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1262 	    "usbvc_v4l2_dequeue_buffer: bytesused=%d, idx=%x, status=%d",
1263 	    buf->bytesused, buf->index, buf_done->status);
1264 
1265 	return (0);
1266 }
1267 
1268 
1269 /*
1270  * Check if a ctrl_id is supported by the device, if yes, find the
1271  * corresponding processing unit and fill usbvc_v4l2_ctrl_t
1272  */
1273 static int
1274 usbvc_v4l2_match_ctrl(usbvc_state_t *usbvcp, usbvc_v4l2_ctrl_t *ctrl,
1275     uint32_t ctrl_id)
1276 {
1277 	uint8_t		idx;
1278 	usbvc_units_t	*unit;
1279 	uchar_t		bit;
1280 
1281 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1282 	    "usbvc_v4l2_match_ctrl: ctrl_id=%x", ctrl_id);
1283 	if (ctrl_id >= V4L2_CID_PRIVATE_BASE) {
1284 
1285 		return (USB_FAILURE);
1286 	}
1287 	if (ctrl_id < V4L2_CID_BASE) {
1288 
1289 		return (USB_FAILURE);
1290 	}
1291 
1292 	/* get the idx of ctrl array usbvc_v4l2_ctrl */
1293 	idx = ctrl_id - V4L2_CID_BASE;
1294 	if (ctrl_id == V4L2_CID_GAMMA) {
1295 
1296 		/* The 4th one is for Gamma ctrl */
1297 		bit = usbvc_v4l2_ctrls[4].bit;
1298 	} else if ((ctrl_id >= V4L2_CID_BRIGHTNESS) &&
1299 	    (ctrl_id <= V4L2_CID_HUE)) {
1300 
1301 		/* The idxth one is for this ctrl */
1302 		bit = usbvc_v4l2_ctrls[idx].bit;
1303 	} else {
1304 
1305 		return (USB_FAILURE);
1306 	}
1307 	unit = (usbvc_units_t *)list_head(&usbvcp->usbvc_unit_list);
1308 
1309 	/*
1310 	 * Check if there is a processing unit supportting this ctrl.
1311 	 * Todo: check if the ctrl and the unit is really for the right
1312 	 * stream interface in case of multi stream interfaces.
1313 	 */
1314 	while (unit != NULL) {
1315 
1316 		if (unit->descr->bDescriptorSubType == VC_PROCESSING_UNIT) {
1317 
1318 			if (bit >=
1319 			    (unit->descr->unit.processing.bControlSize * 8)) {
1320 
1321 				/*
1322 				 * If this unit's bmControls size is smaller
1323 				 * than bit, then next
1324 				 */
1325 				unit = (usbvc_units_t *)
1326 				    list_next(&usbvcp->usbvc_unit_list, unit);
1327 
1328 				continue;
1329 			} else {
1330 
1331 				/*
1332 				 * The first two bytes of bmControls are
1333 				 * for ctrls
1334 				 */
1335 				if ((bit < 8) &&
1336 				    unit->bmControls[0] & (0x1 << bit)) {
1337 
1338 					break;
1339 				}
1340 				if ((bit >= 8 && bit < 16) &&
1341 				    unit->bmControls[1] & (0x1 << bit)) {
1342 
1343 					break;
1344 				}
1345 			}
1346 		}
1347 		unit = (usbvc_units_t *)list_next(&usbvcp->usbvc_unit_list,
1348 		    unit);
1349 	}
1350 	if (unit == NULL) {
1351 
1352 		return (USB_FAILURE);
1353 	}
1354 	ctrl->entity_id = unit->descr->bUnitID;
1355 	if (ctrl_id == V4L2_CID_GAMMA) {
1356 		ctrl->ctrl_map = &usbvc_v4l2_ctrls[4];
1357 	} else {
1358 		ctrl->ctrl_map = &usbvc_v4l2_ctrls[idx];
1359 	}
1360 
1361 	return (USB_SUCCESS);
1362 }
1363 
1364 
1365 /*
1366  * Implement ioctl VIDIOC_QUERYCTRL, query the ctrl types that the device
1367  * supports
1368  */
1369 static int
1370 usbvc_v4l2_query_ctrl(usbvc_state_t *usbvcp, struct v4l2_queryctrl *queryctrl)
1371 {
1372 	usbvc_v4l2_ctrl_t	ctrl;
1373 	mblk_t			*data;
1374 	char			req[16];
1375 
1376 	if (usbvc_v4l2_match_ctrl(usbvcp, &ctrl, queryctrl->id) !=
1377 	    USB_SUCCESS) {
1378 
1379 		return (USB_FAILURE);
1380 	}
1381 	if ((data = allocb(ctrl.ctrl_map->len, BPRI_LO)) == NULL) {
1382 
1383 		return (USB_FAILURE);
1384 	}
1385 
1386 	if (usbvc_vc_get_ctrl(usbvcp, GET_MIN, ctrl.entity_id,
1387 	    ctrl.ctrl_map->selector, ctrl.ctrl_map->len, data) !=
1388 	    USB_SUCCESS) {
1389 		(void) strncpy(&req[0], "GET_MIN", sizeof (req));
1390 
1391 		goto fail;
1392 	}
1393 	LE_TO_UINT16(data->b_rptr, 0, queryctrl->minimum);
1394 	if (usbvc_vc_get_ctrl(usbvcp, GET_MAX, ctrl.entity_id,
1395 	    ctrl.ctrl_map->selector, ctrl.ctrl_map->len, data) != USB_SUCCESS) {
1396 		(void) strncpy(&req[0], "GET_MAX", sizeof (req));
1397 
1398 		goto fail;
1399 	}
1400 	LE_TO_UINT16(data->b_rptr, 0, queryctrl->maximum);
1401 
1402 	if (usbvc_vc_get_ctrl(usbvcp, GET_RES, ctrl.entity_id,
1403 	    ctrl.ctrl_map->selector, ctrl.ctrl_map->len, data) != USB_SUCCESS) {
1404 		(void) strncpy(&req[0], "GET_RES", sizeof (req));
1405 
1406 		goto fail;
1407 	}
1408 	LE_TO_UINT16(data->b_rptr, 0, queryctrl->step);
1409 
1410 	if (usbvc_vc_get_ctrl(usbvcp, GET_DEF, ctrl.entity_id,
1411 	    ctrl.ctrl_map->selector, ctrl.ctrl_map->len, data) != USB_SUCCESS) {
1412 		(void) strncpy(&req[0], "GET_DEF", sizeof (req));
1413 
1414 		goto fail;
1415 	}
1416 	LE_TO_UINT16(data->b_rptr, 0, queryctrl->default_value);
1417 
1418 	(void) strncpy(queryctrl->name, ctrl.ctrl_map->name,
1419 	    sizeof (queryctrl->name));
1420 	queryctrl->type = ctrl.ctrl_map->type;
1421 	queryctrl->flags = 0;
1422 
1423 	if (data) {
1424 		freemsg(data);
1425 	}
1426 
1427 	return (USB_SUCCESS);
1428 
1429 fail:
1430 	if (data) {
1431 		freemsg(data);
1432 	}
1433 	USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1434 	    "usbvc_v4l2_query_ctrl: fail when %s", req);
1435 
1436 	return (USB_FAILURE);
1437 
1438 }
1439 
1440 
1441 /* Implement ioctl VIDIOC_G_CTRL, get current ctrl */
1442 static int
1443 usbvc_v4l2_get_ctrl(usbvc_state_t *usbvcp, struct v4l2_control *v4l2_ctrl)
1444 {
1445 	usbvc_v4l2_ctrl_t	ctrl;
1446 	mblk_t			*data;
1447 
1448 	if (usbvc_v4l2_match_ctrl(usbvcp, &ctrl, v4l2_ctrl->id) !=
1449 	    USB_SUCCESS) {
1450 
1451 		return (USB_FAILURE);
1452 	}
1453 	if ((data = allocb(ctrl.ctrl_map->len, BPRI_LO)) == NULL) {
1454 
1455 		return (USB_FAILURE);
1456 	}
1457 
1458 	if (usbvc_vc_get_ctrl(usbvcp, GET_CUR, ctrl.entity_id,
1459 	    ctrl.ctrl_map->selector, ctrl.ctrl_map->len, data) != USB_SUCCESS) {
1460 		if (data) {
1461 			freemsg(data);
1462 		}
1463 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1464 		    "usbvc_v4l2_get_ctrl: fail");
1465 
1466 		return (USB_FAILURE);
1467 	}
1468 	LE_TO_UINT16(data->b_rptr, 0, v4l2_ctrl->value);
1469 
1470 	if (data) {
1471 		freemsg(data);
1472 	}
1473 
1474 	return (USB_SUCCESS);
1475 }
1476 
1477 
1478 /* Implement ioctl VIDIOC_S_CTRL */
1479 static int
1480 usbvc_v4l2_set_ctrl(usbvc_state_t *usbvcp, struct v4l2_control *v4l2_ctrl)
1481 {
1482 	usbvc_v4l2_ctrl_t	ctrl;
1483 	mblk_t			*data;
1484 
1485 	if (usbvc_v4l2_match_ctrl(usbvcp, &ctrl, v4l2_ctrl->id) !=
1486 	    USB_SUCCESS) {
1487 
1488 		return (USB_FAILURE);
1489 	}
1490 	if ((data = allocb(ctrl.ctrl_map->len, BPRI_LO)) == NULL) {
1491 
1492 		return (USB_FAILURE);
1493 	}
1494 
1495 	UINT16_TO_LE(v4l2_ctrl->value, 0, data->b_wptr);
1496 	data->b_wptr += 2;
1497 	if (usbvc_vc_set_ctrl(usbvcp, SET_CUR, ctrl.entity_id,
1498 	    ctrl.ctrl_map->selector, ctrl.ctrl_map->len, data) !=
1499 	    USB_SUCCESS) {
1500 		if (data) {
1501 			freemsg(data);
1502 		}
1503 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1504 		    "usbvc_v4l2_set_ctrl: fail");
1505 
1506 		return (USB_FAILURE);
1507 	}
1508 	if (data) {
1509 		freemsg(data);
1510 	}
1511 
1512 	return (USB_SUCCESS);
1513 }
1514 
1515 /* For the given interval, find the closest frame interval to it. */
1516 static uint32_t
1517 usbvc_find_interval(usbvc_frames_t *frame, uint32_t interval)
1518 {
1519 	uint32_t step, i, closest, index, approx1, approx2;
1520 
1521 
1522 	/*
1523 	 * for continuous case, there is a min and a max, and also a step
1524 	 * value. The available intervals are those between min and max
1525 	 * values.
1526 	 */
1527 	if (!frame->descr->bFrameIntervalType) {
1528 		step = frame->dwFrameIntervalStep;
1529 
1530 		if (step == 0) {
1531 		/* a malfunction device */
1532 
1533 			return (0);
1534 		} else if (interval <= frame->dwMinFrameInterval) {
1535 		/* return the most possible interval we can handle */
1536 
1537 			return (frame->dwMinFrameInterval);
1538 		} else if (interval >= frame->dwMaxFrameInterval) {
1539 		/* return the most possible interval we can handle */
1540 
1541 			return (frame->dwMaxFrameInterval);
1542 		}
1543 
1544 		approx1 = (interval / step) * step;
1545 		approx2 = approx1 + step;
1546 		closest = ((interval - approx1) < (approx2 - interval)) ?
1547 		    approx1 : approx2;
1548 
1549 		return (closest);
1550 	}
1551 
1552 	/*
1553 	 * for discrete case, search all the available intervals, find the
1554 	 * closest one.
1555 	 */
1556 	closest = 0;
1557 	approx2 = (uint32_t)-1;
1558 	for (index = 0; index < frame->descr->bFrameIntervalType; index++) {
1559 		LE_TO_UINT32(frame->dwFrameInterval, index * 4, i);
1560 		approx1 = (i > interval) ? (i - interval) : (interval - i);
1561 
1562 		if (approx1 == 0) {
1563 		/* find the matched one, return it immediately */
1564 			return (i);
1565 		}
1566 
1567 		if (approx1 < approx2) {
1568 			approx2 = approx1;
1569 			closest = i;
1570 		}
1571 	}
1572 
1573 	return (closest);
1574 }
1575 
1576 /* Implement ioctl VIDIOC_S_PARM. Support capture only, so far. */
1577 static int
1578 usbvc_v4l2_set_parm(usbvc_state_t *usbvcp, struct v4l2_streamparm *parm)
1579 {
1580 	usbvc_stream_if_t	*strm_if;
1581 	usbvc_format_group_t	*cur_fmt;
1582 	usbvc_frames_t			*cur_frame;
1583 	uint32_t n, d, c, i;
1584 	usbvc_vs_probe_commit_t	ctrl;
1585 
1586 	mutex_enter(&usbvcp->usbvc_mutex);
1587 	strm_if = usbvcp->usbvc_curr_strm;
1588 
1589 	if (!strm_if->cur_format_group ||
1590 	    !strm_if->cur_format_group->cur_frame) {
1591 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1592 		    "usbvc_v4l2_set_parm: current format or"
1593 		    " frame is not set. cur_fmt=%p",
1594 		    (void *)strm_if->cur_format_group);
1595 
1596 		mutex_exit(&usbvcp->usbvc_mutex);
1597 
1598 		return (USB_FAILURE);
1599 	}
1600 
1601 	cur_fmt = strm_if->cur_format_group;
1602 	cur_frame = cur_fmt->cur_frame;
1603 
1604 	mutex_exit(&usbvcp->usbvc_mutex);
1605 	if (parm->parm.capture.readbuffers > USBVC_MAX_READ_BUF_NUM) {
1606 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1607 		    "usbvc_v4l2_set_parm: ask too many read buffers,"
1608 		    " readbuffers=%d",
1609 		    parm->parm.capture.readbuffers);
1610 
1611 		return (USB_FAILURE);
1612 	}
1613 
1614 	n = parm->parm.capture.timeperframe.numerator;
1615 	d = parm->parm.capture.timeperframe.denominator;
1616 
1617 	/* check the values passed in, in case of zero devide */
1618 	if (d == 0) {
1619 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1620 		    "usbvc_v4l2_set_parm: invalid denominator=%d", d);
1621 
1622 		return (USB_FAILURE);
1623 	}
1624 
1625 	/*
1626 	 * UVC frame intervals are in 100ns units, need convert from
1627 	 * 1s unit to 100ns unit
1628 	 */
1629 	c = USBVC_FRAME_INTERVAL_DENOMINATOR;
1630 
1631 	/* check the values passed in, in case of overflow */
1632 	if (n / d >= ((uint32_t)-1) / c) {
1633 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1634 		    "usbvc_v4l2_set_parm: overflow, numerator=%d,"
1635 		    " denominator=%d", n, d);
1636 
1637 		return (USB_FAILURE);
1638 	}
1639 
1640 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1641 	    "usbvc_v4l2_set_parm: numerator=%d, denominator=%d", n, d);
1642 
1643 	/* compute the interval in 100ns unit */
1644 	if (n <= ((uint32_t)-1) / c) {
1645 		i = (n * c) / d;
1646 	} else {
1647 		do {
1648 			n >>= 1;
1649 			d >>= 1;
1650 		/* decrease both n and d, in case overflow */
1651 		} while (n && d && n > ((uint32_t)-1) / c);
1652 
1653 		if (!d) {
1654 			USB_DPRINTF_L2(PRINT_MASK_IOCTL,
1655 			    usbvcp->usbvc_log_handle,
1656 			    "usbvc_v4l2_set_parm: can't compute interval,"
1657 			    " denominator=%d", d);
1658 
1659 			return (USB_FAILURE);
1660 		}
1661 		i = (n * c) / d;
1662 	}
1663 
1664 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1665 	    "usbvc_v4l2_set_parm: want interval=%d, n=%d, d=%d, c=%d",
1666 	    i, n, d, c);
1667 
1668 	/*
1669 	 * Begin negotiate frame intervals.
1670 	 */
1671 	bcopy(&strm_if->ctrl_pc, &ctrl, sizeof (usbvc_vs_probe_commit_t));
1672 	i = usbvc_find_interval(cur_frame, i);
1673 
1674 	if (i == 0) {
1675 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1676 		    "usbvc_v4l2_set_parm: can not find an proper interval."
1677 		    " i=%d, n=%d, d=%d", i, n, d);
1678 
1679 		return (USB_FAILURE);
1680 	}
1681 
1682 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1683 	    "usbvc_v4l2_set_parm: get interval=%d", i);
1684 
1685 	UINT32_TO_LE(i, 0, ctrl.dwFrameInterval);
1686 
1687 	/* Probe, just a test before the real try */
1688 	if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl, VS_PROBE_CONTROL)
1689 	    != USB_SUCCESS) {
1690 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1691 		    "usbvc_v4l2_set_parm: set probe failed");
1692 
1693 		return (USB_FAILURE);
1694 	}
1695 
1696 	/* Commit the frame interval. */
1697 	if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl, VS_COMMIT_CONTROL)
1698 	    != USB_SUCCESS) {
1699 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
1700 		    "usbvc_v4l2_set_parm: set commit failed");
1701 
1702 		return (USB_FAILURE);
1703 	}
1704 
1705 	bcopy(&ctrl, &strm_if->ctrl_pc, sizeof (usbvc_vs_probe_commit_t));
1706 
1707 	LE_TO_UINT32(ctrl.dwFrameInterval, 0, i);
1708 	parm->parm.capture.timeperframe.numerator = i;
1709 	parm->parm.capture.timeperframe.denominator = c;
1710 
1711 	mutex_enter(&usbvcp->usbvc_mutex);
1712 	/*
1713 	 * According to ioctl VIDIOC_S_PARM, zero value of readbuffers will not
1714 	 * be set. And the current value is expected to return to application.
1715 	 */
1716 	if (parm->parm.capture.readbuffers != 0) {
1717 		strm_if->buf_read_num = parm->parm.capture.readbuffers;
1718 	} else {
1719 		parm->parm.capture.readbuffers = strm_if->buf_read_num;
1720 	}
1721 	mutex_exit(&usbvcp->usbvc_mutex);
1722 
1723 	return (USB_SUCCESS);
1724 }
1725 
1726 /* Implement ioctl VIDIOC_G_PARM. */
1727 static int
1728 usbvc_v4l2_get_parm(usbvc_state_t *usbvcp, struct v4l2_streamparm *parm)
1729 {
1730 	usbvc_stream_if_t	*strm_if;
1731 	uint32_t n, d;
1732 
1733 	bzero(parm, sizeof (*parm));
1734 
1735 	mutex_enter(&usbvcp->usbvc_mutex);
1736 	strm_if = usbvcp->usbvc_curr_strm;
1737 
1738 	/* return the actual number of buffers allocated for read() I/O */
1739 	parm->parm.capture.readbuffers = strm_if->buf_read.buf_cnt;
1740 
1741 	/* in 100ns units */
1742 	LE_TO_UINT32(strm_if->ctrl_pc.dwFrameInterval, 0, n);
1743 	mutex_exit(&usbvcp->usbvc_mutex);
1744 
1745 	/*
1746 	 * According to UVC payload specs, the dwFrameInterval in frame
1747 	 * descriptors is in 100ns unit.
1748 	 */
1749 	d = USBVC_FRAME_INTERVAL_DENOMINATOR;
1750 	parm->parm.capture.timeperframe.numerator = n;
1751 	parm->parm.capture.timeperframe.denominator = d;
1752 
1753 	/* Support capture only, so far. */
1754 	parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1755 	parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
1756 	parm->parm.capture.capturemode = 0; /* no high quality imaging mode */
1757 	parm->parm.capture.extendedmode = 0; /* no driver specific parameters */
1758 
1759 	/* Always success for current support of this command */
1760 	return (USB_SUCCESS);
1761 }
1762