xref: /illumos-gate/usr/src/uts/common/io/usb/clients/video/usbvc/usbvc.c (revision cb6207858a9fcc2feaee22e626912fba281ac969)
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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * USB video class driver (usbvc(7D))
30  *
31  * 1. Overview
32  * ------------
33  *
34  * This driver supports USB video class devices that used to capture video,
35  * e.g., some webcams. It is developed according to "USB Device Class
36  * Definition for Video Devices" spec. This spec defines detail info needed by
37  * designing a USB video device. It is available at:
38  * http://www.usb.org/developers/devclass_docs
39  *
40  * This driver implements:
41  *
42  *   - V4L2 interfaces for applications to communicate with video devices.
43  *     V4L2 is an API that is widely used by video applications, like Ekiga,
44  *     luvcview, etc. The API spec is at:
45  *     http://www.thedirks.org/v4l2/
46  *     This driver is according to V4L2 spec version 0.20
47  *
48  *   - Video capture function. (Video output is not supported by now.)
49  *
50  *   - Isochronous transfer for video data. (Bulk transfer is not supported.)
51  *
52  *   - read & mmap I/O methods for userland video applications to get video
53  *     data. Userland video applications can use read() system call directly,
54  *     it is the simplest way but not the most efficient way. Applications can
55  *     also use mmap() system call to map several bufs (they are linked as a
56  *     buf list), and then use some specific ioctls to start/stop isoc polling,
57  *     to queue/dequeue bufs.
58  *
59  * 2. Source and header files
60  * ---------------------------
61  *
62  * There are two source files and three header files for this driver:
63  *
64  *   - usbvc.c		Main source file, implements usb video class spec.
65  *
66  *   - usbvc_v4l2.c	V4L2 interface specific code.
67  *
68  *   - usbvc_var.h	Main header file, includes soft state structure.
69  *
70  *   - usbvc.h		The descriptors in usb video class spec.
71  *
72  *   - videodev2.h	This header file is included in V4L2 spec. It defines
73  *     ioctls and data structures that used as an interface between video
74  *     applications and video drivers. This is the only header file that
75  *     usbvc driver should export to userland application.
76  *
77  * 3. USB video class devices overview
78  * -----------------------------------
79  * According to UVC spec, there must be one control interface in a UVC device.
80  * Control interface is used to receive control commands from user, all the
81  * commands are sent through default ctrl pipe. usbvc driver implements V4L2
82  * API, so ioctls are implemented to relay user commands to UVC device.
83  *
84  * There can be no or multiple stream interfaces in a UVC device. Stream
85  * interfaces are used to do video data I/O. In practice, if no stream
86  * interface, the video device can do nothing since it has no data I/O.
87  *
88  * usbvc driver parses descriptors of control interface and stream interfaces.
89  * The descriptors tell the function layout and the capability of the device.
90  * During attach, usbvc driver set up some key data structures according to
91  * the descriptors.
92  *
93  * 4. I/O methods
94  * ---------------
95  *
96  * Userland applications use ioctls to set/get video formats of the device,
97  * and control brightness, contrast, image size, etc.
98  *
99  * Besides implementing standard read I/O method to get video data from
100  * the device, usbvc driver also implements some specific ioctls to implement
101  * mmap I/O method.
102  *
103  * A view from userland application: ioctl and mmap flow chart:
104  *
105  * REQBUFS -> QUERYBUF -> mmap() ->
106  *
107  *    -> QBUF -> STREAMON -> DQBUF -> process image -> QBUF
108  *			       ^			|
109  *			       |			|
110  *			       |			v
111  *			       |---<--------------------
112  *
113  * The above queue and dequeue buf operations can be stopped by issuing a
114  * STREAMOFF ioctl.
115  *
116  * 5. Device states
117  * ----------------
118  *
119  * The device has four states (refer to usbai.h):
120  *
121  *	- USB_DEV_ONLINE: In action or ready for action.
122  *
123  *	- USB_DEV_DISCONNECTED: Hotplug removed, or device not present/correct
124  *				on resume (CPR).
125  *
126  *	- USB_DEV_SUSPENDED: Device has been suspended along with the system.
127  *
128  *	- USB_DEV_PWRED_DOWN: Device has been powered down.  (Note that this
129  *		driver supports only two power states, powered down and
130  *		full power.)
131  *
132  * 6. Serialize
133  * -------------
134  * In order to avoid race conditions between driver entry points, access to
135  * the device is serialized. All the ioctls, and read, open/close are
136  * serialized. The functions usbvc_serialize/release_access are implemented
137  * for this purpose.
138  *
139  * 7. PM & CPR
140  * ------------
141  * PM & CPR are supported. pm_busy_component and pm_idle_component mark
142  * the device as busy or idle to the system.
143  */
144 
145 #if defined(lint) && !defined(DEBUG)
146 #define	DEBUG
147 #endif
148 
149 #define	USBDRV_MAJOR_VER	2
150 #define	USBDRV_MINOR_VER	0
151 
152 #include <sys/usb/usba.h>
153 #include <sys/fcntl.h>
154 #include <sys/cmn_err.h>
155 #include <sys/usb/clients/video/usbvc/usbvc_var.h>
156 #include <sys/videodev2.h> /* V4L2 API header file */
157 
158 /* Descriptors according to USB video class spec */
159 #include <sys/usb/clients/video/usbvc/usbvc.h>
160 
161 static uint_t	usbvc_errmask		= (uint_t)PRINT_MASK_ALL;
162 static uint_t	usbvc_errlevel = 4;
163 static uint_t	usbvc_instance_debug = (uint_t)-1;
164 
165 static char	*name = "usbvc";	/* Driver name, used all over. */
166 
167 /*
168  * Function Prototypes
169  */
170 
171 /* Entries */
172 static int	usbvc_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
173 static int	usbvc_attach(dev_info_t *, ddi_attach_cmd_t);
174 static int	usbvc_detach(dev_info_t *, ddi_detach_cmd_t);
175 static void	usbvc_cleanup(dev_info_t *, usbvc_state_t *);
176 static int	usbvc_open(dev_t *, int, int, cred_t *);
177 static int	usbvc_close(dev_t, int, int, cred_t *);
178 static int	usbvc_read(dev_t, struct uio *uip_p, cred_t *);
179 static int	usbvc_strategy(struct buf *);
180 static void	usbvc_minphys(struct buf *);
181 static int	usbvc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
182 static int	usbvc_devmap(dev_t, devmap_cookie_t, offset_t,
183 		    size_t, size_t *, uint_t);
184 
185 /* pm and cpr */
186 static int	usbvc_power(dev_info_t *, int, int);
187 static void	usbvc_init_power_mgmt(usbvc_state_t *);
188 static void	usbvc_destroy_power_mgmt(usbvc_state_t *);
189 static void	usbvc_pm_busy_component(usbvc_state_t *);
190 static void	usbvc_pm_idle_component(usbvc_state_t *);
191 static int	usbvc_pwrlvl0(usbvc_state_t *);
192 static int	usbvc_pwrlvl1(usbvc_state_t *);
193 static int	usbvc_pwrlvl2(usbvc_state_t *);
194 static int	usbvc_pwrlvl3(usbvc_state_t *);
195 static void	usbvc_cpr_suspend(dev_info_t *);
196 static void	usbvc_cpr_resume(dev_info_t *);
197 static void	usbvc_restore_device_state(dev_info_t *, usbvc_state_t *);
198 
199 /* Events */
200 static int	usbvc_disconnect_event_cb(dev_info_t *);
201 static int	usbvc_reconnect_event_cb(dev_info_t *);
202 
203 /* Sync objs and lists */
204 static void	usbvc_init_sync_objs(usbvc_state_t *);
205 static void	usbvc_fini_sync_objs(usbvc_state_t *);
206 static void	usbvc_init_lists(usbvc_state_t *);
207 static void	usbvc_fini_lists(usbvc_state_t *);
208 static void	usbvc_free_ctrl_descr(usbvc_state_t *);
209 static void	usbvc_free_stream_descr(usbvc_state_t *);
210 
211 /* Parse descriptors */
212 static int	usbvc_chk_descr_len(uint8_t, uint8_t, uint8_t,
213 		    usb_cvs_data_t *);
214 static usbvc_stream_if_t *usbvc_parse_stream_if(usbvc_state_t *, int);
215 static int	usbvc_parse_ctrl_if(usbvc_state_t *);
216 static int	usbvc_parse_stream_ifs(usbvc_state_t *);
217 static void	usbvc_parse_color_still(usbvc_state_t *,
218 		    usbvc_format_group_t *, usb_cvs_data_t *, uint_t, uint_t);
219 static void	usbvc_parse_frames(usbvc_state_t *, usbvc_format_group_t *,
220 		    usb_cvs_data_t *, uint_t, uint_t);
221 static int	usbvc_parse_format_group(usbvc_state_t *,
222 		    usbvc_format_group_t *, usb_cvs_data_t *, uint_t, uint_t);
223 static int	usbvc_parse_format_groups(usbvc_state_t *, usbvc_stream_if_t *);
224 static int	usbvc_parse_stream_header(usbvc_state_t *, usbvc_stream_if_t *);
225 
226 /* read I/O functions */
227 static int	usbvc_alloc_read_bufs(usbvc_state_t *, usbvc_stream_if_t *);
228 static int	usbvc_read_buf(usbvc_state_t *, struct buf *);
229 static void	usbvc_free_read_buf(usbvc_buf_t *);
230 static void	usbvc_free_read_bufs(usbvc_state_t *, usbvc_stream_if_t *);
231 static void	usbvc_close_isoc_pipe(usbvc_state_t *, usbvc_stream_if_t *);
232 
233 /* callbacks */
234 static void	usbvc_isoc_cb(usb_pipe_handle_t, usb_isoc_req_t *);
235 static void	usbvc_isoc_exc_cb(usb_pipe_handle_t, usb_isoc_req_t *);
236 
237 /* Others */
238 static int	usbvc_set_alt(usbvc_state_t *, usbvc_stream_if_t *);
239 static int	usbvc_decode_stream_header(usbvc_state_t *, usbvc_buf_grp_t *,
240 		    mblk_t *, int);
241 static int	usbvc_serialize_access(usbvc_state_t *, boolean_t);
242 static void	usbvc_release_access(usbvc_state_t *);
243 static int		usbvc_set_default_stream_fmt(usbvc_state_t *);
244 
245 static usb_event_t usbvc_events = {
246 	usbvc_disconnect_event_cb,
247 	usbvc_reconnect_event_cb,
248 	NULL, NULL
249 };
250 
251 /* module loading stuff */
252 struct cb_ops usbvc_cb_ops = {
253 	usbvc_open,		/* open  */
254 	usbvc_close,		/* close */
255 	usbvc_strategy,	/* strategy */
256 	nulldev,		/* print */
257 	nulldev,		/* dump */
258 	usbvc_read,		/* read */
259 	nodev,			/* write */
260 	usbvc_ioctl,		/* ioctl */
261 	usbvc_devmap,		/* devmap */
262 	nodev,			/* mmap */
263 	ddi_devmap_segmap,	/* segmap */
264 	nochpoll,		/* poll */
265 	ddi_prop_op,		/* cb_prop_op */
266 	NULL,			/* streamtab  */
267 	D_MP | D_DEVMAP
268 };
269 
270 static struct dev_ops usbvc_ops = {
271 	DEVO_REV,		/* devo_rev, */
272 	0,			/* refcnt  */
273 	usbvc_info,		/* info */
274 	nulldev,		/* identify */
275 	nulldev,		/* probe */
276 	usbvc_attach,		/* attach */
277 	usbvc_detach,		/* detach */
278 	nodev,			/* reset */
279 	&usbvc_cb_ops,	/* driver operations */
280 	NULL,			/* bus operations */
281 	usbvc_power		/* power */
282 };
283 
284 static struct modldrv usbvc_modldrv =	{
285 	&mod_driverops,
286 	"USB video class driver %I%",
287 	&usbvc_ops
288 };
289 
290 static struct modlinkage modlinkage = {
291 	MODREV_1,
292 	&usbvc_modldrv,
293 	NULL
294 };
295 
296 /* Soft state structures */
297 #define	USBVC_INITIAL_SOFT_SPACE	1
298 static void *usbvc_statep;
299 
300 
301 /*
302  * Module-wide initialization routine.
303  */
304 int
305 _init(void)
306 {
307 	int rval;
308 
309 	if ((rval = ddi_soft_state_init(&usbvc_statep,
310 	    sizeof (usbvc_state_t), USBVC_INITIAL_SOFT_SPACE)) != 0) {
311 
312 		return (rval);
313 	}
314 
315 	if ((rval = mod_install(&modlinkage)) != 0) {
316 		ddi_soft_state_fini(&usbvc_statep);
317 	}
318 
319 	return (rval);
320 }
321 
322 
323 /*
324  * Module-wide tear-down routine.
325  */
326 int
327 _fini(void)
328 {
329 	int rval;
330 
331 	if ((rval = mod_remove(&modlinkage)) != 0) {
332 
333 		return (rval);
334 	}
335 
336 	ddi_soft_state_fini(&usbvc_statep);
337 
338 	return (rval);
339 }
340 
341 
342 int
343 _info(struct modinfo *modinfop)
344 {
345 	return (mod_info(&modlinkage, modinfop));
346 }
347 
348 
349 /*
350  * usbvc_info:
351  *	Get minor number, soft state structure, etc.
352  */
353 /*ARGSUSED*/
354 static int
355 usbvc_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
356 			void *arg, void **result)
357 {
358 	usbvc_state_t	*usbvcp;
359 	int error = DDI_FAILURE;
360 
361 	switch (infocmd) {
362 	case DDI_INFO_DEVT2DEVINFO:
363 		if ((usbvcp = ddi_get_soft_state(usbvc_statep,
364 		    getminor((dev_t)arg))) != NULL) {
365 			*result = usbvcp->usbvc_dip;
366 			if (*result != NULL) {
367 				error = DDI_SUCCESS;
368 			}
369 		} else {
370 			*result = NULL;
371 		}
372 		break;
373 	case DDI_INFO_DEVT2INSTANCE:
374 		*result = (void *)(uintptr_t)getminor((dev_t)arg);
375 		error = DDI_SUCCESS;
376 		break;
377 	default:
378 		break;
379 	}
380 
381 	return (error);
382 }
383 
384 
385 /*
386  * Entry functions.
387  */
388 
389 /*
390  * usbvc_attach:
391  *	Attach or resume.
392  *
393  *	For attach, initialize state and device, including:
394  *		state variables, locks, device node
395  *		device registration with system
396  *		power management, hotplugging
397  *	For resume, restore device and state
398  */
399 static int
400 usbvc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
401 {
402 	int			instance = ddi_get_instance(dip);
403 	usbvc_state_t		*usbvcp = NULL;
404 	int			status;
405 
406 	switch (cmd) {
407 	case DDI_ATTACH:
408 
409 		break;
410 	case DDI_RESUME:
411 		usbvc_cpr_resume(dip);
412 
413 		return (DDI_SUCCESS);
414 	default:
415 
416 		return (DDI_FAILURE);
417 	}
418 
419 	if (ddi_soft_state_zalloc(usbvc_statep, instance) == DDI_SUCCESS) {
420 		usbvcp = ddi_get_soft_state(usbvc_statep, instance);
421 	}
422 	if (usbvcp == NULL)  {
423 
424 		return (DDI_FAILURE);
425 	}
426 
427 	usbvcp->usbvc_dip = dip;
428 
429 	usbvcp->usbvc_log_handle = usb_alloc_log_hdl(dip,
430 				"usbvc", &usbvc_errlevel,
431 				&usbvc_errmask, &usbvc_instance_debug, 0);
432 
433 	USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
434 		    "usbvc_attach: enter");
435 
436 	if ((status = usb_client_attach(dip, USBDRV_VERSION, 0)) !=
437 	    USB_SUCCESS) {
438 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
439 		    "usbvc_attach: usb_client_attach failed, error code:%d",
440 		    status);
441 
442 		goto fail;
443 	}
444 
445 	if ((status = usb_get_dev_data(dip, &usbvcp->usbvc_reg,
446 	    USB_PARSE_LVL_ALL, 0)) != USB_SUCCESS) {
447 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
448 		    "usbvc_attach: usb_get_dev_data failed, error code:%d",
449 		    status);
450 
451 		goto fail;
452 	}
453 	usbvc_init_sync_objs(usbvcp);
454 
455 	/* create minor node */
456 	if ((status = ddi_create_minor_node(dip, name, S_IFCHR, instance,
457 	    "usb_video", 0)) != DDI_SUCCESS) {
458 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
459 		    "usbvc_attach: Error creating minor node, error code:%d",
460 		    status);
461 
462 		goto fail;
463 	}
464 
465 	mutex_enter(&usbvcp->usbvc_mutex);
466 	usbvc_init_lists(usbvcp);
467 
468 	usbvcp->usbvc_default_ph = usbvcp->usbvc_reg->dev_default_ph;
469 
470 	/* Put online before PM init as can get power managed afterward. */
471 	usbvcp->usbvc_dev_state = USB_DEV_ONLINE;
472 	mutex_exit(&usbvcp->usbvc_mutex);
473 
474 	/* initialize power management */
475 	usbvc_init_power_mgmt(usbvcp);
476 
477 	if ((status = usbvc_parse_ctrl_if(usbvcp)) != USB_SUCCESS) {
478 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
479 		    "usbvc_attach: parse ctrl interface fail, error code:%d",
480 		    status);
481 
482 		goto fail;
483 	}
484 	if ((status = usbvc_parse_stream_ifs(usbvcp)) != USB_SUCCESS) {
485 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
486 		    "usbvc_attach: parse stream interfaces fail, error code:%d",
487 		    status);
488 
489 		goto fail;
490 	}
491 	(void) usbvc_set_default_stream_fmt(usbvcp);
492 
493 	/* Register for events */
494 	if ((status = usb_register_event_cbs(dip, &usbvc_events, 0)) !=
495 	    USB_SUCCESS) {
496 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
497 		    "usbvc_attach: register_event_cbs failed, error code:%d",
498 		    status);
499 
500 		goto fail;
501 	}
502 
503 	/* Report device */
504 	ddi_report_dev(dip);
505 
506 	return (DDI_SUCCESS);
507 
508 fail:
509 	if (usbvcp) {
510 		usbvc_cleanup(dip, usbvcp);
511 	}
512 
513 	return (DDI_FAILURE);
514 }
515 
516 
517 /*
518  * usbvc_detach:
519  *	detach or suspend driver instance
520  *
521  * Note: in detach, only contention threads is from pm and disconnnect.
522  */
523 static int
524 usbvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
525 {
526 	int		instance = ddi_get_instance(dip);
527 	usbvc_state_t	*usbvcp = ddi_get_soft_state(usbvc_statep, instance);
528 	int		rval = USB_FAILURE;
529 
530 	switch (cmd) {
531 	case DDI_DETACH:
532 		mutex_enter(&usbvcp->usbvc_mutex);
533 		ASSERT((usbvcp->usbvc_drv_state & USBVC_OPEN) == 0);
534 		mutex_exit(&usbvcp->usbvc_mutex);
535 
536 		USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
537 		    "usbvc_detach: enter for detach");
538 
539 		usbvc_cleanup(dip, usbvcp);
540 		rval = USB_SUCCESS;
541 
542 		break;
543 	case DDI_SUSPEND:
544 		USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
545 		    "usbvc_detach: enter for suspend");
546 
547 		usbvc_cpr_suspend(dip);
548 		rval = USB_SUCCESS;
549 
550 		break;
551 	default:
552 
553 		break;
554 	}
555 
556 	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
557 }
558 
559 
560 /*
561  * usbvc_cleanup:
562  *	clean up the driver state for detach
563  */
564 static void
565 usbvc_cleanup(dev_info_t *dip, usbvc_state_t *usbvcp)
566 {
567 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
568 	    "Cleanup: enter");
569 
570 	if (usbvcp->usbvc_locks_initialized) {
571 
572 		/* This must be done 1st to prevent more events from coming. */
573 		usb_unregister_event_cbs(dip, &usbvc_events);
574 
575 		/*
576 		 * At this point, no new activity can be initiated. The driver
577 		 * has disabled hotplug callbacks. The Solaris framework has
578 		 * disabled new opens on a device being detached, and does not
579 		 * allow detaching an open device.
580 		 *
581 		 * The following ensures that all driver activity has drained.
582 		 */
583 		mutex_enter(&usbvcp->usbvc_mutex);
584 		(void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
585 		usbvc_release_access(usbvcp);
586 		mutex_exit(&usbvcp->usbvc_mutex);
587 
588 		/* All device activity has died down. */
589 		usbvc_destroy_power_mgmt(usbvcp);
590 		mutex_enter(&usbvcp->usbvc_mutex);
591 		usbvc_fini_lists(usbvcp);
592 		mutex_exit(&usbvcp->usbvc_mutex);
593 
594 		ddi_remove_minor_node(dip, NULL);
595 		usbvc_fini_sync_objs(usbvcp);
596 	}
597 
598 	usb_client_detach(dip, usbvcp->usbvc_reg);
599 	usb_free_log_hdl(usbvcp->usbvc_log_handle);
600 	ddi_soft_state_free(usbvc_statep, ddi_get_instance(dip));
601 	ddi_prop_remove_all(dip);
602 }
603 
604 
605 /*ARGSUSED*/
606 static int
607 usbvc_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
608 {
609 	usbvc_state_t	*usbvcp =
610 			    ddi_get_soft_state(usbvc_statep, getminor(*devp));
611 
612 	if (usbvcp == NULL) {
613 
614 		return (ENXIO);
615 	}
616 
617 	/*
618 	 * Keep it simple: one client at a time.
619 	 * Exclusive open only
620 	 */
621 	mutex_enter(&usbvcp->usbvc_mutex);
622 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
623 	    "usbvc_open: enter, dev_stat=%d", usbvcp->usbvc_dev_state);
624 
625 	if (usbvcp->usbvc_dev_state == USB_DEV_DISCONNECTED) {
626 		mutex_exit(&usbvcp->usbvc_mutex);
627 
628 		return (ENODEV);
629 	}
630 	if (usbvcp->usbvc_dev_state == USB_DEV_SUSPENDED) {
631 		mutex_exit(&usbvcp->usbvc_mutex);
632 
633 		return (EIO);
634 	}
635 	if ((usbvcp->usbvc_drv_state & USBVC_OPEN) != 0) {
636 		mutex_exit(&usbvcp->usbvc_mutex);
637 
638 		return (EBUSY);
639 	}
640 	usbvcp->usbvc_drv_state |= USBVC_OPEN;
641 
642 	if (usbvc_serialize_access(usbvcp, USBVC_SER_SIG) == 0) {
643 		usbvcp->usbvc_drv_state &= ~USBVC_OPEN;
644 		usbvcp->usbvc_serial_inuse = B_FALSE;
645 		mutex_exit(&usbvcp->usbvc_mutex);
646 
647 		return (EINTR);
648 	}
649 
650 	/* raise power */
651 	usbvc_pm_busy_component(usbvcp);
652 	if (usbvcp->usbvc_pm->usbvc_current_power != USB_DEV_OS_FULL_PWR) {
653 		usbvcp->usbvc_pm->usbvc_raise_power = B_TRUE;
654 		mutex_exit(&usbvcp->usbvc_mutex);
655 		(void) pm_raise_power(usbvcp->usbvc_dip,
656 					0, USB_DEV_OS_FULL_PWR);
657 		mutex_enter(&usbvcp->usbvc_mutex);
658 		usbvcp->usbvc_pm->usbvc_raise_power = B_FALSE;
659 	}
660 
661 	/* Device is idle until it is used. */
662 	usbvc_release_access(usbvcp);
663 	mutex_exit(&usbvcp->usbvc_mutex);
664 
665 	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
666 	    "usbvc_open: end.");
667 
668 	return (0);
669 }
670 
671 
672 /*ARGSUSED*/
673 static int
674 usbvc_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
675 {
676 	usbvc_stream_if_t *strm_if;
677 	int		if_num;
678 	usbvc_state_t	*usbvcp =
679 	    ddi_get_soft_state(usbvc_statep, getminor(dev));
680 
681 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
682 	    "close: enter");
683 
684 	mutex_enter(&usbvcp->usbvc_mutex);
685 	(void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
686 	mutex_exit(&usbvcp->usbvc_mutex);
687 
688 	/* Perform device session cleanup here. */
689 
690 	USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
691 	    "close: cleaning up...");
692 
693 	/*
694 	 * USBA automatically flushes/resets active non-default pipes
695 	 * when they are closed.  We can't reset default pipe, but we
696 	 * can wait for all requests on it from this dip to drain.
697 	 */
698 	(void) usb_pipe_drain_reqs(usbvcp->usbvc_dip,
699 	    usbvcp->usbvc_reg->dev_default_ph, 0,
700 	    USB_FLAGS_SLEEP, NULL, 0);
701 
702 	mutex_enter(&usbvcp->usbvc_mutex);
703 	strm_if = usbvcp->usbvc_curr_strm;
704 	if (strm_if->start_polling == 1) {
705 		mutex_exit(&usbvcp->usbvc_mutex);
706 		usb_pipe_stop_isoc_polling(strm_if->datain_ph, USB_FLAGS_SLEEP);
707 		mutex_enter(&usbvcp->usbvc_mutex);
708 		strm_if->start_polling = 0;
709 	}
710 	usbvc_close_isoc_pipe(usbvcp, strm_if);
711 	if_num = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
712 	mutex_exit(&usbvcp->usbvc_mutex);
713 
714 	/* reset alternate to the default one. */
715 	(void) usb_set_alt_if(usbvcp->usbvc_dip, if_num, 0,
716 	    USB_FLAGS_SLEEP, NULL, NULL);
717 	mutex_enter(&usbvcp->usbvc_mutex);
718 
719 	usbvc_free_read_bufs(usbvcp, strm_if);
720 	usbvc_free_map_bufs(usbvcp, strm_if);
721 	usbvcp->usbvc_drv_state &= ~USBVC_OPEN;
722 
723 	usbvc_release_access(usbvcp);
724 	usbvc_pm_idle_component(usbvcp);
725 	mutex_exit(&usbvcp->usbvc_mutex);
726 
727 	return (0);
728 }
729 
730 
731 /*ARGSUSED*/
732 /* Read isoc data from usb video devices */
733 static int
734 usbvc_read(dev_t dev, struct uio *uio_p, cred_t *cred_p)
735 {
736 	int			rval;
737 	usbvc_stream_if_t	*strm_if;
738 	usbvc_state_t	*usbvcp =
739 			    ddi_get_soft_state(usbvc_statep, getminor(dev));
740 
741 	USB_DPRINTF_L4(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
742 	    "usbvc_read: enter");
743 	mutex_enter(&usbvcp->usbvc_mutex);
744 	if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
745 		USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
746 		    "usbvc_read: Device is not available,"
747 		    " dev_stat=%d", usbvcp->usbvc_dev_state);
748 		mutex_exit(&usbvcp->usbvc_mutex);
749 
750 		return (EFAULT);
751 	}
752 	if ((uio_p->uio_fmode & (FNDELAY|FNONBLOCK)) &&
753 	    (usbvcp->usbvc_serial_inuse != B_FALSE)) {
754 		USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
755 		    "usbvc_read: non-blocking read, return fail.");
756 		mutex_exit(&usbvcp->usbvc_mutex);
757 
758 		return (EAGAIN);
759 	}
760 	if (usbvc_serialize_access(usbvcp, USBVC_SER_SIG) <= 0) {
761 		USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
762 		    "usbvc_read: serialize_access failed.");
763 		rval = EFAULT;
764 
765 		goto fail;
766 	}
767 
768 	/* Get the first stream interface */
769 	strm_if = usbvcp->usbvc_curr_strm;
770 	if (!strm_if) {
771 		USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
772 		    "usbvc_read: no stream interfaces");
773 		rval = EFAULT;
774 
775 		goto fail;
776 	}
777 
778 	/*
779 	 * If it is the first read, open isoc pipe and allocate bufs for
780 	 * read I/O method.
781 	 */
782 	if (strm_if->datain_ph == NULL) {
783 		if (usbvc_open_isoc_pipe(usbvcp, strm_if) != USB_SUCCESS) {
784 			USB_DPRINTF_L2(PRINT_MASK_READ,
785 			    usbvcp->usbvc_log_handle,
786 			    "usbvc_read: first read, open pipe fail");
787 			rval = EFAULT;
788 
789 			goto fail;
790 		}
791 		if (usbvc_alloc_read_bufs(usbvcp, strm_if) != USB_SUCCESS) {
792 			USB_DPRINTF_L2(PRINT_MASK_READ,
793 			    usbvcp->usbvc_log_handle,
794 			    "usbvc_read: allocate rw bufs fail");
795 			rval = EFAULT;
796 
797 			goto fail;
798 		}
799 	}
800 
801 	/* start polling if it is not started yet */
802 	if (strm_if->start_polling != 1) {
803 		if (usbvc_start_isoc_polling(usbvcp, strm_if, NULL) !=
804 		    USB_SUCCESS) {
805 			USB_DPRINTF_L2(PRINT_MASK_READ,
806 			    usbvcp->usbvc_log_handle,
807 			    "usbvc_read: usbvc_start_isoc_polling fail");
808 			rval = EFAULT;
809 
810 			goto fail;
811 		}
812 		strm_if->start_polling = 1;
813 	}
814 
815 	if (list_is_empty(&strm_if->buf_read.uv_buf_done)) {
816 		USB_DPRINTF_L3(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
817 		    "usbvc_read: full buf list is empty.");
818 
819 		if (uio_p->uio_fmode & (FNDELAY | FNONBLOCK)) {
820 			USB_DPRINTF_L2(PRINT_MASK_READ,
821 			    usbvcp->usbvc_log_handle, "usbvc_read: fail, "
822 			    "non-blocking read, done buf is empty.");
823 			rval = EAGAIN;
824 
825 			goto fail;
826 		}
827 
828 		/* no available buffers, block here */
829 		while (list_is_empty(&strm_if->buf_read.uv_buf_done)) {
830 			USB_DPRINTF_L3(PRINT_MASK_READ,
831 			    usbvcp->usbvc_log_handle,
832 			    "usbvc_read: wait for done buf");
833 			if (cv_wait_sig(&usbvcp->usbvc_read_cv,
834 			    &usbvcp->usbvc_mutex) <= 0) {
835 				/* no done buf and cv is signaled */
836 				rval = EINTR;
837 
838 				goto fail;
839 			}
840 			if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
841 
842 				/* Device is disconnected. */
843 				rval = EINTR;
844 
845 				goto fail;
846 			}
847 		}
848 
849 	}
850 
851 	mutex_exit(&usbvcp->usbvc_mutex);
852 	rval = physio(usbvc_strategy, NULL, dev, B_READ,
853 		    usbvc_minphys, uio_p);
854 
855 	mutex_enter(&usbvcp->usbvc_mutex);
856 	usbvc_release_access(usbvcp);
857 	mutex_exit(&usbvcp->usbvc_mutex);
858 
859 	return (rval);
860 
861 fail:
862 	usbvc_release_access(usbvcp);
863 	mutex_exit(&usbvcp->usbvc_mutex);
864 
865 	return (rval);
866 }
867 
868 
869 /*
870  * strategy:
871  *	Called through physio to setup and start the transfer.
872  */
873 static int
874 usbvc_strategy(struct buf *bp)
875 {
876 	usbvc_state_t *usbvcp = ddi_get_soft_state(usbvc_statep,
877 				    getminor(bp->b_edev));
878 
879 	USB_DPRINTF_L4(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
880 	    "usbvc_strategy: enter");
881 
882 	/*
883 	 * Initialize residual count here in case transfer doesn't even get
884 	 * started.
885 	 */
886 	bp->b_resid = bp->b_bcount;
887 
888 	/* Needed as this is a character driver. */
889 	if (bp->b_flags & (B_PHYS | B_PAGEIO)) {
890 		bp_mapin(bp);
891 	}
892 
893 	mutex_enter(&usbvcp->usbvc_mutex);
894 
895 	/* Make sure device has not been disconnected. */
896 	if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
897 		USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
898 		    "usbvc_strategy: device can't be accessed");
899 		mutex_exit(&usbvcp->usbvc_mutex);
900 
901 		goto fail;
902 	}
903 
904 	/* read data from uv_buf_done list */
905 	if (usbvc_read_buf(usbvcp, bp) != USB_SUCCESS) {
906 		USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
907 		    "usbvc_strategy: read full buf list fail");
908 		mutex_exit(&usbvcp->usbvc_mutex);
909 
910 		goto fail;
911 	}
912 
913 	mutex_exit(&usbvcp->usbvc_mutex);
914 
915 	biodone(bp);
916 
917 	return (0);
918 
919 fail:
920 	USB_DPRINTF_L2(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
921 	    "usbvc_strategy: strategy fail");
922 	bp->b_private = NULL;
923 
924 	bioerror(bp, EIO);
925 	biodone(bp);
926 
927 	return (0);
928 }
929 
930 
931 static void
932 usbvc_minphys(struct buf *bp)
933 {
934 	dev_t			dev = bp->b_edev;
935 	usbvc_stream_if_t	*strm_if;
936 	uint32_t		maxsize;
937 	usbvc_state_t	*usbvcp =
938 			    ddi_get_soft_state(usbvc_statep, getminor(dev));
939 
940 	mutex_enter(&usbvcp->usbvc_mutex);
941 	strm_if = usbvcp->usbvc_curr_strm;
942 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, maxsize);
943 	USB_DPRINTF_L3(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
944 	    "usbvc_minphys: max read size=%d", maxsize);
945 
946 	if (bp->b_bcount > maxsize) {
947 		bp->b_bcount = maxsize;
948 	}
949 	mutex_exit(&usbvcp->usbvc_mutex);
950 }
951 
952 
953 /*
954  * ioctl entry.
955  */
956 /*ARGSUSED*/
957 static int
958 usbvc_ioctl(dev_t dev, int cmd, intptr_t arg,
959 		int mode, cred_t *cred_p, int *rval_p)
960 {
961 	int		rv = 0;
962 	usbvc_state_t	*usbvcp =
963 	    ddi_get_soft_state(usbvc_statep, getminor(dev));
964 
965 	if (usbvcp == NULL) {
966 
967 		return (ENXIO);
968 	}
969 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
970 	    "ioctl enter, cmd=%x", cmd);
971 	mutex_enter(&usbvcp->usbvc_mutex);
972 	if (usbvcp->usbvc_dev_state != USB_DEV_ONLINE) {
973 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
974 		    "ioctl: Device is not online,"
975 		    " dev_stat=%d", usbvcp->usbvc_dev_state);
976 		mutex_exit(&usbvcp->usbvc_mutex);
977 
978 		return (EFAULT);
979 	}
980 	if (usbvc_serialize_access(usbvcp, USBVC_SER_SIG) <= 0) {
981 		usbvcp->usbvc_serial_inuse = B_FALSE;
982 		mutex_exit(&usbvcp->usbvc_mutex);
983 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
984 		    "serialize_access failed.");
985 
986 		return (EFAULT);
987 	}
988 	mutex_exit(&usbvcp->usbvc_mutex);
989 
990 	rv = usbvc_v4l2_ioctl(usbvcp, cmd, arg, mode);
991 
992 	mutex_enter(&usbvcp->usbvc_mutex);
993 	usbvc_release_access(usbvcp);
994 	mutex_exit(&usbvcp->usbvc_mutex);
995 
996 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
997 	    "usbvc_ioctl exit");
998 
999 	return (rv);
1000 }
1001 
1002 
1003 /* Entry for mmap system call */
1004 static int
1005 usbvc_devmap(dev_t dev, devmap_cookie_t handle, offset_t off,
1006 	size_t len, size_t *maplen, uint_t model)
1007 {
1008 	usbvc_state_t		*usbvcp;
1009 	int			error, i;
1010 	usbvc_buf_t		*buf = NULL;
1011 	usbvc_stream_if_t	*strm_if;
1012 	usbvc_buf_grp_t		*bufgrp;
1013 
1014 	usbvcp = ddi_get_soft_state(usbvc_statep, getminor(dev));
1015 	if (usbvcp == NULL) {
1016 		USB_DPRINTF_L2(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1017 		    "usbvc_devmap: usbvcp == NULL");
1018 
1019 		return (ENXIO);
1020 	}
1021 
1022 	USB_DPRINTF_L3(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1023 	    "devmap: memory map for instance(%d), off=%llx, len=%d, maplen=%d,"
1024 	    " model=%d", getminor(dev), off, len, maplen, model);
1025 
1026 	mutex_enter(&usbvcp->usbvc_mutex);
1027 	(void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
1028 	strm_if = usbvcp->usbvc_curr_strm;
1029 	if (!strm_if) {
1030 		USB_DPRINTF_L2(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1031 		    "usbvc_devmap: No current strm if");
1032 		mutex_exit(&usbvcp->usbvc_mutex);
1033 
1034 		return (ENXIO);
1035 	}
1036 	bufgrp = &strm_if->buf_map;
1037 	for (i = 0; i < bufgrp->buf_cnt; i++) {
1038 		if (bufgrp->buf_head[i].v4l2_buf.m.offset == off) {
1039 			buf = &bufgrp->buf_head[i];
1040 
1041 			break;
1042 		}
1043 	}
1044 	USB_DPRINTF_L3(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1045 	    "usbvc_devmap: idx=%d", i);
1046 	if (buf == NULL) {
1047 		mutex_exit(&usbvcp->usbvc_mutex);
1048 
1049 		return (ENXIO);
1050 	}
1051 	/*
1052 	 * round up len to a multiple of a page size, according to chapter
1053 	 * 10 of "writing device drivers"
1054 	 */
1055 	len = ptob(btopr(len));
1056 	if (len > ptob(btopr(buf->len))) {
1057 		USB_DPRINTF_L2(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1058 		    "usbvc_devmap: len=%x", len);
1059 		mutex_exit(&usbvcp->usbvc_mutex);
1060 
1061 		return (ENXIO);
1062 	}
1063 	mutex_exit(&usbvcp->usbvc_mutex);
1064 
1065 	error = devmap_umem_setup(handle, usbvcp->usbvc_dip, NULL,
1066 		buf->umem_cookie, off, len, PROT_ALL, DEVMAP_DEFAULTS, NULL);
1067 	mutex_enter(&usbvcp->usbvc_mutex);
1068 	*maplen = len;
1069 	if (error == 0 && buf->status == USBVC_BUF_INIT) {
1070 		buf->status = USBVC_BUF_MAPPED;
1071 	} else {
1072 		USB_DPRINTF_L3(PRINT_MASK_DEVMAP, usbvcp->usbvc_log_handle,
1073 		    "usbvc_devmap: devmap_umem_setup, err=%d", error);
1074 	}
1075 
1076 	(void) usbvc_release_access(usbvcp);
1077 	mutex_exit(&usbvcp->usbvc_mutex);
1078 
1079 	return (error);
1080 }
1081 
1082 /*
1083  * pm and cpr
1084  */
1085 
1086 /*
1087  * usbvc_power :
1088  *	Power entry point, the workhorse behind pm_raise_power, pm_lower_power,
1089  *	usb_req_raise_power and usb_req_lower_power.
1090  */
1091 /* ARGSUSED */
1092 static int
1093 usbvc_power(dev_info_t *dip, int comp, int level)
1094 {
1095 	usbvc_state_t	*usbvcp;
1096 	usbvc_power_t	*pm;
1097 	int		rval = USB_FAILURE;
1098 
1099 	usbvcp = ddi_get_soft_state(usbvc_statep, ddi_get_instance(dip));
1100 	mutex_enter(&usbvcp->usbvc_mutex);
1101 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1102 	    "usbvc_power: enter: level = %d, dev_state: %x",
1103 	    level, usbvcp->usbvc_dev_state);
1104 
1105 	if (usbvcp->usbvc_pm == NULL) {
1106 
1107 		goto done;
1108 	}
1109 
1110 	pm = usbvcp->usbvc_pm;
1111 
1112 	/* Check if we are transitioning to a legal power level */
1113 	if (USB_DEV_PWRSTATE_OK(pm->usbvc_pwr_states, level)) {
1114 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
1115 		    "usbvc_power: illegal power level = %d "
1116 		    "pwr_states: %x", level, pm->usbvc_pwr_states);
1117 
1118 		goto done;
1119 	}
1120 	/*
1121 	 * if we are about to raise power and asked to lower power, fail
1122 	 */
1123 	if (pm->usbvc_raise_power && (level < (int)pm->usbvc_current_power)) {
1124 
1125 		goto done;
1126 	}
1127 	switch (level) {
1128 	case USB_DEV_OS_PWR_OFF :
1129 		rval = usbvc_pwrlvl0(usbvcp);
1130 
1131 		break;
1132 	case USB_DEV_OS_PWR_1 :
1133 		rval = usbvc_pwrlvl1(usbvcp);
1134 
1135 		break;
1136 	case USB_DEV_OS_PWR_2 :
1137 		rval = usbvc_pwrlvl2(usbvcp);
1138 
1139 		break;
1140 	case USB_DEV_OS_FULL_PWR :
1141 		rval = usbvc_pwrlvl3(usbvcp);
1142 
1143 		break;
1144 	}
1145 
1146 done:
1147 	mutex_exit(&usbvcp->usbvc_mutex);
1148 
1149 	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1150 }
1151 
1152 
1153 /*
1154  * usbvc_init_power_mgmt:
1155  *	Initialize power management and remote wakeup functionality.
1156  *	No mutex is necessary in this function as it's called only by attach.
1157  */
1158 static void
1159 usbvc_init_power_mgmt(usbvc_state_t *usbvcp)
1160 {
1161 	usbvc_power_t	*usbvcpm;
1162 	uint_t		pwr_states;
1163 
1164 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1165 	    "init_power_mgmt enter");
1166 
1167 	/* Allocate the state structure */
1168 	usbvcpm = kmem_zalloc(sizeof (usbvc_power_t), KM_SLEEP);
1169 	mutex_enter(&usbvcp->usbvc_mutex);
1170 	usbvcp->usbvc_pm = usbvcpm;
1171 	usbvcpm->usbvc_state = usbvcp;
1172 	usbvcpm->usbvc_pm_capabilities = 0;
1173 	usbvcpm->usbvc_current_power = USB_DEV_OS_FULL_PWR;
1174 	mutex_exit(&usbvcp->usbvc_mutex);
1175 
1176 	if (usb_create_pm_components(usbvcp->usbvc_dip, &pwr_states) ==
1177 		USB_SUCCESS) {
1178 		USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1179 		    "usbvc_init_power_mgmt: created PM components");
1180 
1181 		if (usb_handle_remote_wakeup(usbvcp->usbvc_dip,
1182 		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1183 			usbvcpm->usbvc_wakeup_enabled = 1;
1184 		} else {
1185 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
1186 			    usbvcp->usbvc_log_handle, "usbvc_init_power_mgmt:"
1187 			    " remote wakeup not supported");
1188 		}
1189 
1190 		mutex_enter(&usbvcp->usbvc_mutex);
1191 		usbvcpm->usbvc_pwr_states = (uint8_t)pwr_states;
1192 		usbvc_pm_busy_component(usbvcp);
1193 		usbvcpm->usbvc_raise_power = B_TRUE;
1194 		mutex_exit(&usbvcp->usbvc_mutex);
1195 
1196 		(void) pm_raise_power(
1197 		    usbvcp->usbvc_dip, 0, USB_DEV_OS_FULL_PWR);
1198 
1199 		mutex_enter(&usbvcp->usbvc_mutex);
1200 		usbvcpm->usbvc_raise_power = B_FALSE;
1201 		usbvc_pm_idle_component(usbvcp);
1202 		mutex_exit(&usbvcp->usbvc_mutex);
1203 
1204 	}
1205 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1206 	    "usbvc_init_power_mgmt: end");
1207 }
1208 
1209 
1210 /*
1211  * usbvc_destroy_power_mgmt:
1212  *	Shut down and destroy power management and remote wakeup functionality.
1213  */
1214 static void
1215 usbvc_destroy_power_mgmt(usbvc_state_t *usbvcp)
1216 {
1217 	usbvc_power_t	*pm;
1218 	int		rval;
1219 
1220 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1221 	    "destroy_power_mgmt enter");
1222 	mutex_enter(&usbvcp->usbvc_mutex);
1223 	pm = usbvcp->usbvc_pm;
1224 	if (pm && (usbvcp->usbvc_dev_state != USB_DEV_DISCONNECTED)) {
1225 
1226 		usbvc_pm_busy_component(usbvcp);
1227 		if (pm->usbvc_wakeup_enabled) {
1228 			pm->usbvc_raise_power = B_TRUE;
1229 			mutex_exit(&usbvcp->usbvc_mutex);
1230 
1231 			/* First bring the device to full power */
1232 			(void) pm_raise_power(usbvcp->usbvc_dip, 0,
1233 			    USB_DEV_OS_FULL_PWR);
1234 			if ((rval = usb_handle_remote_wakeup(
1235 			    usbvcp->usbvc_dip,
1236 			    USB_REMOTE_WAKEUP_DISABLE)) !=
1237 			    USB_SUCCESS) {
1238 				USB_DPRINTF_L2(PRINT_MASK_ATTA,
1239 				    usbvcp->usbvc_log_handle,
1240 				    "usbvc_destroy_power_mgmt: "
1241 				    "Error disabling rmt wakeup: rval = %d",
1242 				    rval);
1243 			}
1244 			mutex_enter(&usbvcp->usbvc_mutex);
1245 			pm->usbvc_raise_power = B_FALSE;
1246 
1247 		}
1248 		mutex_exit(&usbvcp->usbvc_mutex);
1249 
1250 		/*
1251 		 * Since remote wakeup is disabled now,
1252 		 * no one can raise power
1253 		 * and get to device once power is lowered here.
1254 		 */
1255 		(void) pm_lower_power(usbvcp->usbvc_dip, 0, USB_DEV_OS_PWR_OFF);
1256 		mutex_enter(&usbvcp->usbvc_mutex);
1257 		usbvc_pm_idle_component(usbvcp);
1258 	}
1259 
1260 	if (pm) {
1261 		kmem_free(pm, sizeof (usbvc_power_t));
1262 		usbvcp->usbvc_pm = NULL;
1263 	}
1264 	mutex_exit(&usbvcp->usbvc_mutex);
1265 }
1266 
1267 
1268 static void
1269 usbvc_pm_busy_component(usbvc_state_t *usbvcp)
1270 {
1271 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1272 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1273 	    "usbvc_pm_busy_component: enter");
1274 
1275 	usbvcp->usbvc_pm->usbvc_pm_busy++;
1276 	mutex_exit(&usbvcp->usbvc_mutex);
1277 
1278 	if (pm_busy_component(usbvcp->usbvc_dip, 0) !=
1279 	    DDI_SUCCESS) {
1280 		mutex_enter(&usbvcp->usbvc_mutex);
1281 		USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1282 		    "usbvc_pm_busy_component: pm busy fail, usbvc_pm_busy=%d",
1283 		    usbvcp->usbvc_pm->usbvc_pm_busy);
1284 
1285 		usbvcp->usbvc_pm->usbvc_pm_busy--;
1286 		mutex_exit(&usbvcp->usbvc_mutex);
1287 	}
1288 	mutex_enter(&usbvcp->usbvc_mutex);
1289 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1290 	    "usbvc_pm_busy_component: exit");
1291 }
1292 
1293 
1294 static void
1295 usbvc_pm_idle_component(usbvc_state_t *usbvcp)
1296 {
1297 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1298 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1299 	    "usbvc_pm_idle_component: enter");
1300 
1301 	if (usbvcp->usbvc_pm != NULL) {
1302 		mutex_exit(&usbvcp->usbvc_mutex);
1303 		if (pm_idle_component(usbvcp->usbvc_dip, 0) ==
1304 		    DDI_SUCCESS) {
1305 			mutex_enter(&usbvcp->usbvc_mutex);
1306 			ASSERT(usbvcp->usbvc_pm->usbvc_pm_busy > 0);
1307 			usbvcp->usbvc_pm->usbvc_pm_busy--;
1308 			mutex_exit(&usbvcp->usbvc_mutex);
1309 		}
1310 		mutex_enter(&usbvcp->usbvc_mutex);
1311 		USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1312 		    "usbvc_pm_idle_component: %d",
1313 		    usbvcp->usbvc_pm->usbvc_pm_busy);
1314 	}
1315 }
1316 
1317 
1318 /*
1319  * usbvc_pwrlvl0:
1320  * Functions to handle power transition for OS levels 0 -> 3
1321  */
1322 static int
1323 usbvc_pwrlvl0(usbvc_state_t *usbvcp)
1324 {
1325 	int rval;
1326 
1327 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1328 	    "usbvc_pwrlvl0, dev_state: %x", usbvcp->usbvc_dev_state);
1329 
1330 	switch (usbvcp->usbvc_dev_state) {
1331 	case USB_DEV_ONLINE:
1332 		/* Deny the powerdown request if the device is busy */
1333 		if (usbvcp->usbvc_pm->usbvc_pm_busy != 0) {
1334 		USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1335 		    "usbvc_pwrlvl0: usbvc_pm_busy");
1336 
1337 			return (USB_FAILURE);
1338 		}
1339 
1340 		/* Issue USB D3 command to the device here */
1341 		rval = usb_set_device_pwrlvl3(usbvcp->usbvc_dip);
1342 		ASSERT(rval == USB_SUCCESS);
1343 
1344 		usbvcp->usbvc_dev_state = USB_DEV_PWRED_DOWN;
1345 		usbvcp->usbvc_pm->usbvc_current_power =
1346 						USB_DEV_OS_PWR_OFF;
1347 		/* FALLTHRU */
1348 	case USB_DEV_DISCONNECTED:
1349 	case USB_DEV_SUSPENDED:
1350 		/* allow a disconnect/cpr'ed device to go to lower power */
1351 
1352 		return (USB_SUCCESS);
1353 	case USB_DEV_PWRED_DOWN:
1354 	default:
1355 		USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1356 		    "usbvc_pwrlvl0: illegal dev state");
1357 
1358 		return (USB_FAILURE);
1359 	}
1360 }
1361 
1362 
1363 /*
1364  * usbvc_pwrlvl1:
1365  *	Functions to handle power transition to OS levels -> 2
1366  */
1367 static int
1368 usbvc_pwrlvl1(usbvc_state_t *usbvcp)
1369 {
1370 	int	rval;
1371 
1372 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1373 	    "usbvc_pwrlvl1");
1374 
1375 	/* Issue USB D2 command to the device here */
1376 	rval = usb_set_device_pwrlvl2(usbvcp->usbvc_dip);
1377 	ASSERT(rval == USB_SUCCESS);
1378 
1379 	return (USB_FAILURE);
1380 }
1381 
1382 
1383 /*
1384  * usbvc_pwrlvl2:
1385  *	Functions to handle power transition to OS levels -> 1
1386  */
1387 static int
1388 usbvc_pwrlvl2(usbvc_state_t *usbvcp)
1389 {
1390 	int	rval;
1391 
1392 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1393 	    "usbvc_pwrlvl2");
1394 
1395 	/* Issue USB D1 command to the device here */
1396 	rval = usb_set_device_pwrlvl1(usbvcp->usbvc_dip);
1397 	ASSERT(rval == USB_SUCCESS);
1398 
1399 	return (USB_FAILURE);
1400 }
1401 
1402 
1403 /*
1404  * usbvc_pwrlvl3:
1405  *	Functions to handle power transition to OS level -> 0
1406  */
1407 static int
1408 usbvc_pwrlvl3(usbvc_state_t *usbvcp)
1409 {
1410 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1411 	    "usbvc_pwrlvl3, dev_stat=%d", usbvcp->usbvc_dev_state);
1412 
1413 	switch (usbvcp->usbvc_dev_state) {
1414 	case USB_DEV_PWRED_DOWN:
1415 		/* Issue USB D0 command to the device here */
1416 		(void) usb_set_device_pwrlvl0(usbvcp->usbvc_dip);
1417 
1418 		usbvcp->usbvc_dev_state = USB_DEV_ONLINE;
1419 		usbvcp->usbvc_pm->usbvc_current_power =
1420 		    USB_DEV_OS_FULL_PWR;
1421 
1422 		/* FALLTHRU */
1423 	case USB_DEV_ONLINE:
1424 		/* we are already in full power */
1425 		/* FALLTHRU */
1426 	case USB_DEV_DISCONNECTED:
1427 	case USB_DEV_SUSPENDED:
1428 		/*
1429 		 * PM framework tries to put us in full power
1430 		 * during system shutdown. If we are disconnected/cpr'ed
1431 		 * return success anyways
1432 		 */
1433 
1434 		return (USB_SUCCESS);
1435 	default:
1436 		USB_DPRINTF_L2(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1437 		    "usbvc_pwrlvl3: illegal dev state");
1438 
1439 		return (USB_FAILURE);
1440 	}
1441 }
1442 
1443 
1444 /*
1445  * usbvc_cpr_suspend:
1446  *	Clean up device.
1447  *	Wait for any IO to finish, then close pipes.
1448  *	Quiesce device.
1449  */
1450 static void
1451 usbvc_cpr_suspend(dev_info_t *dip)
1452 {
1453 	int		instance = ddi_get_instance(dip);
1454 	usbvc_state_t	*usbvcp = ddi_get_soft_state(usbvc_statep,
1455 							instance);
1456 
1457 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1458 	    "usbvc_cpr_suspend enter");
1459 
1460 	mutex_enter(&usbvcp->usbvc_mutex);
1461 
1462 	/*
1463 	 * Set dev_state to suspended so other driver threads don't start any
1464 	 * new I/O.
1465 	 */
1466 	usbvcp->usbvc_dev_state = USB_DEV_SUSPENDED;
1467 
1468 	/*
1469 	 * Wake up the read threads in case there are any threads are blocking.
1470 	 * After being waked up, those threads will quit immediately since the
1471 	 * dev_state is not ONLINE
1472 	 */
1473 	if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
1474 		cv_broadcast(&usbvcp->usbvc_mapio_cv);
1475 	} else {
1476 		cv_broadcast(&usbvcp->usbvc_read_cv);
1477 	}
1478 	/* Wait for the other threads to quit */
1479 	(void) usbvc_serialize_access(usbvcp, USBVC_SER_NOSIG);
1480 	usbvc_release_access(usbvcp);
1481 	mutex_exit(&usbvcp->usbvc_mutex);
1482 
1483 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
1484 	    "usbvc_cpr_suspend: return");
1485 }
1486 
1487 
1488 /*
1489  * usbvc_cpr_resume:
1490  *
1491  *	usbvc_restore_device_state marks success by putting device back online
1492  */
1493 static void
1494 usbvc_cpr_resume(dev_info_t *dip)
1495 {
1496 	int		instance = ddi_get_instance(dip);
1497 	usbvc_state_t	*usbvcp = ddi_get_soft_state(usbvc_statep,
1498 							instance);
1499 
1500 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
1501 	    "resume: enter");
1502 
1503 	/*
1504 	 * NOTE: A pm_raise_power in usbvc_restore_device_state will bring
1505 	 * the power-up state of device into synch with the system.
1506 	 */
1507 	mutex_enter(&usbvcp->usbvc_mutex);
1508 	usbvc_restore_device_state(dip, usbvcp);
1509 	mutex_exit(&usbvcp->usbvc_mutex);
1510 }
1511 
1512 
1513 /*
1514  * usbvc_restore_device_state:
1515  *	Called during hotplug-reconnect and resume.
1516  *		reenable power management
1517  *		Verify the device is the same as before the disconnect/suspend.
1518  *		Restore device state
1519  *		Thaw any IO which was frozen.
1520  *		Quiesce device.  (Other routines will activate if thawed IO.)
1521  *		Set device online.
1522  *		Leave device disconnected if there are problems.
1523  */
1524 static void
1525 usbvc_restore_device_state(dev_info_t *dip, usbvc_state_t *usbvcp)
1526 {
1527 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1528 	    "usbvc_restore_device_state: enter");
1529 
1530 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
1531 
1532 	ASSERT((usbvcp->usbvc_dev_state == USB_DEV_DISCONNECTED) ||
1533 	    (usbvcp->usbvc_dev_state == USB_DEV_SUSPENDED));
1534 
1535 	usbvc_pm_busy_component(usbvcp);
1536 	usbvcp->usbvc_pm->usbvc_raise_power = B_TRUE;
1537 	mutex_exit(&usbvcp->usbvc_mutex);
1538 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1539 
1540 	/* Check if we are talking to the same device */
1541 	if (usb_check_same_device(dip, usbvcp->usbvc_log_handle,
1542 	    USB_LOG_L0, PRINT_MASK_ALL,
1543 	    USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
1544 
1545 		goto fail;
1546 	}
1547 
1548 	mutex_enter(&usbvcp->usbvc_mutex);
1549 	usbvcp->usbvc_pm->usbvc_raise_power = B_FALSE;
1550 	usbvcp->usbvc_dev_state = USB_DEV_ONLINE;
1551 	mutex_exit(&usbvcp->usbvc_mutex);
1552 
1553 	if (usbvcp->usbvc_pm->usbvc_wakeup_enabled) {
1554 
1555 		/* Failure here means device disappeared again. */
1556 		if (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) !=
1557 		    USB_SUCCESS) {
1558 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
1559 			    usbvcp->usbvc_log_handle,
1560 			    "device may or may not be accessible. "
1561 			    "Please verify reconnection");
1562 		}
1563 	}
1564 	mutex_enter(&usbvcp->usbvc_mutex);
1565 
1566 	usbvc_pm_idle_component(usbvcp);
1567 
1568 	USB_DPRINTF_L4(PRINT_MASK_PM, usbvcp->usbvc_log_handle,
1569 	    "usbvc_restore_device_state: end");
1570 
1571 	return;
1572 
1573 fail:
1574 	/* change the device state from suspended to disconnected */
1575 	mutex_enter(&usbvcp->usbvc_mutex);
1576 	usbvcp->usbvc_dev_state = USB_DEV_DISCONNECTED;
1577 	usbvc_pm_idle_component(usbvcp);
1578 }
1579 
1580 
1581 /* Events */
1582 
1583 /*
1584  * usbvc_disconnect_event_cb:
1585  *	Called when device hotplug-removed.
1586  *		Close pipes. (This does not attempt to contact device.)
1587  *		Set state to DISCONNECTED
1588  */
1589 static int
1590 usbvc_disconnect_event_cb(dev_info_t *dip)
1591 {
1592 	int		instance = ddi_get_instance(dip);
1593 	usbvc_state_t	*usbvcp =
1594 			    ddi_get_soft_state(usbvc_statep, instance);
1595 
1596 	USB_DPRINTF_L4(PRINT_MASK_HOTPLUG, usbvcp->usbvc_log_handle,
1597 	    "disconnect: enter");
1598 
1599 	mutex_enter(&usbvcp->usbvc_mutex);
1600 	/*
1601 	 * Save any state of device or IO in progress required by
1602 	 * usbvc_restore_device_state for proper device "thawing" later.
1603 	 */
1604 	usbvcp->usbvc_dev_state = USB_DEV_DISCONNECTED;
1605 
1606 	/*
1607 	 * wake up the read threads in case there are any threads are blocking,
1608 	 * after being waked up, those threads will quit fail immediately since
1609 	 * we have changed the dev_stat.
1610 	 */
1611 	if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
1612 		cv_broadcast(&usbvcp->usbvc_mapio_cv);
1613 	} else {
1614 		cv_broadcast(&usbvcp->usbvc_read_cv);
1615 	}
1616 	/* Wait for the other threads to quit */
1617 	(void) usbvc_serialize_access(usbvcp, USBVC_SER_SIG);
1618 	usbvc_release_access(usbvcp);
1619 	mutex_exit(&usbvcp->usbvc_mutex);
1620 
1621 	return (USB_SUCCESS);
1622 }
1623 
1624 
1625 /*
1626  * usbvc_reconnect_event_cb:
1627  *	Called with device hotplug-inserted
1628  *		Restore state
1629  */
1630 static int
1631 usbvc_reconnect_event_cb(dev_info_t *dip)
1632 {
1633 	int		instance = ddi_get_instance(dip);
1634 	usbvc_state_t	*usbvcp = ddi_get_soft_state(usbvc_statep, instance);
1635 
1636 	USB_DPRINTF_L4(PRINT_MASK_HOTPLUG, usbvcp->usbvc_log_handle,
1637 	    "reconnect: enter");
1638 
1639 	mutex_enter(&usbvcp->usbvc_mutex);
1640 	(void) usbvc_serialize_access(usbvcp, USBVC_SER_SIG);
1641 	usbvc_restore_device_state(dip, usbvcp);
1642 	usbvc_release_access(usbvcp);
1643 	mutex_exit(&usbvcp->usbvc_mutex);
1644 
1645 	return (USB_SUCCESS);
1646 }
1647 
1648 /* Sync objs and lists */
1649 
1650 /*
1651  * init/fini sync objects during attach
1652  */
1653 static void
1654 usbvc_init_sync_objs(usbvc_state_t *usbvcp)
1655 {
1656 	mutex_init(&usbvcp->usbvc_mutex, NULL, MUTEX_DRIVER,
1657 			usbvcp->usbvc_reg->dev_iblock_cookie);
1658 
1659 	cv_init(&usbvcp->usbvc_serial_cv, NULL, CV_DRIVER, NULL);
1660 	cv_init(&usbvcp->usbvc_read_cv, NULL, CV_DRIVER, NULL);
1661 	cv_init(&usbvcp->usbvc_mapio_cv, NULL, CV_DRIVER, NULL);
1662 
1663 	usbvcp->usbvc_serial_inuse = B_FALSE;
1664 
1665 	usbvcp->usbvc_locks_initialized = B_TRUE;
1666 }
1667 
1668 
1669 static void
1670 usbvc_fini_sync_objs(usbvc_state_t *usbvcp)
1671 {
1672 	cv_destroy(&usbvcp->usbvc_serial_cv);
1673 	cv_destroy(&usbvcp->usbvc_read_cv);
1674 	cv_destroy(&usbvcp->usbvc_mapio_cv);
1675 
1676 	mutex_destroy(&usbvcp->usbvc_mutex);
1677 }
1678 
1679 
1680 static void
1681 usbvc_init_lists(usbvc_state_t *usbvcp)
1682 {
1683 	/* video terminals */
1684 	list_create(&(usbvcp->usbvc_term_list), sizeof (usbvc_terms_t),
1685 	    offsetof(usbvc_terms_t, term_node));
1686 
1687 	/* video units */
1688 	list_create(&(usbvcp->usbvc_unit_list), sizeof (usbvc_units_t),
1689 	    offsetof(usbvc_units_t, unit_node));
1690 
1691 	/* stream interfaces */
1692 	list_create(&(usbvcp->usbvc_stream_list), sizeof (usbvc_stream_if_t),
1693 	    offsetof(usbvc_stream_if_t, stream_if_node));
1694 }
1695 
1696 
1697 /*
1698  * Free all the data structures allocated when parsing descriptors of ctrl
1699  * and stream interfaces. It is safe to call this function because it always
1700  * checks the pointer before free mem.
1701  */
1702 static void
1703 usbvc_fini_lists(usbvc_state_t *usbvcp)
1704 {
1705 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1706 	    "usbvc_fini_lists: enter");
1707 
1708 	usbvc_free_ctrl_descr(usbvcp);
1709 
1710 	/* Free all video stream structure and the sub-structures */
1711 	usbvc_free_stream_descr(usbvcp);
1712 
1713 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1714 	    "usbvc_fini_lists: end");
1715 }
1716 
1717 
1718 /*
1719  * Free all the data structures allocated when parsing descriptors of ctrl
1720  * interface.
1721  */
1722 static void
1723 usbvc_free_ctrl_descr(usbvc_state_t *usbvcp)
1724 {
1725 	usbvc_terms_t	*term;
1726 	usbvc_units_t	*unit;
1727 
1728 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1729 	    "usbvc_free_ctrl_descr: enter");
1730 
1731 	if (usbvcp->usbvc_vc_header) {
1732 		kmem_free(usbvcp->usbvc_vc_header, sizeof (usbvc_vc_header_t));
1733 	}
1734 
1735 	/* Free all video terminal structure */
1736 	while (!list_is_empty(&usbvcp->usbvc_term_list)) {
1737 			term = list_head(&usbvcp->usbvc_term_list);
1738 			if (term != NULL) {
1739 				list_remove(&(usbvcp->usbvc_term_list), term);
1740 				kmem_free(term, sizeof (usbvc_terms_t));
1741 			}
1742 	}
1743 
1744 	/* Free all video unit structure */
1745 	while (!list_is_empty(&usbvcp->usbvc_unit_list)) {
1746 			unit = list_head(&usbvcp->usbvc_unit_list);
1747 			if (unit != NULL) {
1748 				list_remove(&(usbvcp->usbvc_unit_list), unit);
1749 				kmem_free(unit, sizeof (usbvc_units_t));
1750 			}
1751 	}
1752 }
1753 
1754 
1755 /*
1756  * Free all the data structures allocated when parsing descriptors of stream
1757  * interfaces.
1758  */
1759 static void
1760 usbvc_free_stream_descr(usbvc_state_t *usbvcp)
1761 {
1762 	usbvc_stream_if_t	*strm;
1763 	usbvc_input_header_t	*in_hdr;
1764 	usbvc_output_header_t	*out_hdr;
1765 	uint8_t			fmt_cnt, frm_cnt;
1766 
1767 	while (!list_is_empty(&usbvcp->usbvc_stream_list)) {
1768 		USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
1769 		    "usbvc_fini_lists: stream list not empty.");
1770 
1771 		strm = list_head(&usbvcp->usbvc_stream_list);
1772 		if (strm != NULL) {
1773 
1774 			/* unlink this stream's data structure from the list */
1775 			list_remove(&(usbvcp->usbvc_stream_list), strm);
1776 		} else {
1777 
1778 			/* No real stream data structure in the list */
1779 			return;
1780 		}
1781 
1782 		in_hdr = strm->input_header;
1783 		out_hdr = strm->output_header;
1784 
1785 		if (in_hdr) {
1786 			fmt_cnt = in_hdr->descr->bNumFormats;
1787 		} else if (out_hdr) {
1788 			fmt_cnt = out_hdr->descr->bNumFormats;
1789 		}
1790 
1791 		USB_DPRINTF_L3(PRINT_MASK_CLOSE,
1792 		    usbvcp->usbvc_log_handle, "usbvc_fini_lists:"
1793 		    " fmtgrp cnt=%d", fmt_cnt);
1794 
1795 		/* Free headers */
1796 		if (in_hdr) {
1797 			kmem_free(in_hdr, sizeof (usbvc_input_header_t));
1798 		}
1799 		if (out_hdr) {
1800 			kmem_free(out_hdr, sizeof (usbvc_output_header_t));
1801 		}
1802 
1803 		/* Free format descriptors */
1804 		if (strm->format_group) {
1805 			int i;
1806 			usbvc_format_group_t *fmtgrp;
1807 
1808 			for (i = 0; i < fmt_cnt; i++) {
1809 				fmtgrp = &strm->format_group[i];
1810 				if (fmtgrp->format == NULL) {
1811 
1812 					break;
1813 				}
1814 				if (fmtgrp->still) {
1815 					kmem_free(fmtgrp->still,
1816 					    sizeof (usbvc_still_image_frame_t));
1817 				}
1818 				frm_cnt = fmtgrp->format->bNumFrameDescriptors;
1819 
1820 				USB_DPRINTF_L3(PRINT_MASK_CLOSE,
1821 				    usbvcp->usbvc_log_handle,
1822 				    "usbvc_fini_lists:"
1823 				    " frame cnt=%d", frm_cnt);
1824 
1825 				if (fmtgrp->frames) {
1826 					kmem_free(fmtgrp->frames,
1827 					    sizeof (usbvc_frames_t) * frm_cnt);
1828 				}
1829 			}
1830 			kmem_free(strm->format_group,
1831 			    sizeof (usbvc_format_group_t) * fmt_cnt);
1832 		}
1833 		USB_DPRINTF_L3(PRINT_MASK_CLOSE,
1834 		    usbvcp->usbvc_log_handle, "usbvc_fini_lists:"
1835 		    " free stream_if_t");
1836 
1837 		kmem_free(strm, sizeof (usbvc_stream_if_t));
1838 	}
1839 }
1840 
1841 /*
1842  * Parse class specific descriptors of the video device
1843  */
1844 
1845 /*
1846  * Check the length of a class specific descriptor. Make sure cvs_buf_len is
1847  * not less than the length expected according to uvc spec.
1848  *
1849  * Args:
1850  * - off_num: the cvs_buf offset of the descriptor element that
1851  *   indicates the number of variable descriptor elements;
1852  * - size: the size of each variable descriptor element, if zero, then the
1853  *   size value is offered by off_size;
1854  * - off_size: the cvs_buf offset of the descriptor element that indicates
1855  *   the size of each variable descriptor element;
1856  */
1857 static int
1858 usbvc_chk_descr_len(uint8_t off_num, uint8_t size, uint8_t off_size,
1859     usb_cvs_data_t *cvs_data)
1860 {
1861 	uchar_t			*cvs_buf;
1862 	uint_t			cvs_buf_len;
1863 
1864 	cvs_buf = cvs_data->cvs_buf;
1865 	cvs_buf_len = cvs_data->cvs_buf_len;
1866 
1867 	if (size == 0) {
1868 		if (cvs_buf_len > off_size) {
1869 			size = cvs_buf[off_size];
1870 		} else {
1871 
1872 			return (USB_FAILURE);
1873 		}
1874 	}
1875 	if (cvs_buf_len < (off_num + 1)) {
1876 
1877 		return (USB_FAILURE);
1878 	}
1879 
1880 	if (cvs_buf_len < (cvs_buf[off_num] * size + off_num +1)) {
1881 
1882 		return (USB_FAILURE);
1883 	}
1884 
1885 	return (USB_SUCCESS);
1886 }
1887 
1888 
1889 /* Parse the descriptors of control interface */
1890 static int
1891 usbvc_parse_ctrl_if(usbvc_state_t *usbvcp)
1892 {
1893 	int			if_num;
1894 	int			cvs_num;
1895 	usb_alt_if_data_t	*if_alt_data;
1896 	usb_cvs_data_t		*cvs_data;
1897 	uchar_t			*cvs_buf;
1898 	uint_t			cvs_buf_len;
1899 	uint16_t		version;
1900 
1901 	if_num = usbvcp->usbvc_reg->dev_curr_if;
1902 	if_alt_data = usbvcp->usbvc_reg->dev_curr_cfg->cfg_if[if_num].if_alt;
1903 	cvs_data = if_alt_data->altif_cvs;
1904 
1905 	for (cvs_num = 0; cvs_num < if_alt_data->altif_n_cvs; cvs_num++) {
1906 		cvs_buf = cvs_data[cvs_num].cvs_buf;
1907 		cvs_buf_len = cvs_data[cvs_num].cvs_buf_len;
1908 		USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
1909 		    "usbvc_parse_ctrl_if: cvs_num= %d, cvs_buf_len=%d",
1910 		    cvs_num, cvs_buf_len);
1911 
1912 		/*
1913 		 * parse interface cvs descriptors here; by checking
1914 		 * bDescriptorType (cvs_buf[1])
1915 		 */
1916 		if (cvs_buf[1] != CS_INTERFACE) {
1917 
1918 			continue;
1919 		}
1920 
1921 		/*
1922 		 * Different descriptors in VC interface; according to
1923 		 * bDescriptorSubType (cvs_buf[2])
1924 		 */
1925 		switch (cvs_buf[2]) {
1926 		case VC_HEADER:
1927 
1928 			/*
1929 			 * According to uvc spec, there must be one and only
1930 			 * be one header. If more than one, return failure.
1931 			 */
1932 			if (usbvcp->usbvc_vc_header) {
1933 
1934 				return (USB_FAILURE);
1935 			}
1936 			/*
1937 			 * Check if it is a valid HEADER descriptor in case of
1938 			 * a device not compliant to uvc spec. This descriptor
1939 			 * is critical, return failure if not a valid one.
1940 			 */
1941 			if (usbvc_chk_descr_len(11, 1, 0, cvs_data) !=
1942 			    USB_SUCCESS) {
1943 
1944 				return (USB_FAILURE);
1945 			}
1946 			usbvcp->usbvc_vc_header =
1947 			    (usbvc_vc_header_t *)kmem_zalloc(
1948 			    sizeof (usbvc_vc_header_t), KM_SLEEP);
1949 			usbvcp->usbvc_vc_header->descr =
1950 			(usbvc_vc_header_descr_t *)&cvs_buf[0];
1951 
1952 			LE_TO_UINT16(usbvcp->usbvc_vc_header->descr->bcdUVC,
1953 			    0, version);
1954 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
1955 			    usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if:"
1956 			    " VC header, bcdUVC=%x", version);
1957 			if (usbvcp->usbvc_vc_header->descr->bInCollection ==
1958 			    0) {
1959 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1960 				    usbvcp->usbvc_log_handle,
1961 				    "usbvc_parse_ctrl_if: no strm interfaces");
1962 
1963 				break;
1964 			}
1965 
1966 			/* stream interface numbers */
1967 			usbvcp->usbvc_vc_header->baInterfaceNr = &cvs_buf[12];
1968 
1969 			break;
1970 		case VC_INPUT_TERMINAL:
1971 		{
1972 			usbvc_terms_t *term;
1973 
1974 			/*
1975 			 * Check if it is a valid descriptor in case of a
1976 			 * device not compliant to uvc spec
1977 			 */
1978 			if (cvs_buf_len < USBVC_I_TERM_LEN_MIN) {
1979 
1980 				break;
1981 			}
1982 			term = (usbvc_terms_t *)
1983 			    kmem_zalloc(sizeof (usbvc_terms_t), KM_SLEEP);
1984 			term->descr = (usbvc_term_descr_t *)cvs_buf;
1985 
1986 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
1987 			    usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
1988 			    "input term type=%x", term->descr->wTerminalType);
1989 			if (term->descr->wTerminalType == ITT_CAMERA) {
1990 				if (usbvc_chk_descr_len(14, 1, 0, cvs_data) !=
1991 				    USB_SUCCESS) {
1992 					kmem_free(term, sizeof (usbvc_terms_t));
1993 
1994 					break;
1995 				}
1996 				term->bmControls = &cvs_buf[15];
1997 			} else if (cvs_buf_len > 8) { /* other input terms */
1998 				term->bSpecific = &cvs_buf[8];
1999 			}
2000 			list_insert_tail(&(usbvcp->usbvc_term_list), term);
2001 
2002 			break;
2003 		}
2004 		case VC_OUTPUT_TERMINAL:
2005 		{
2006 			usbvc_terms_t *term;
2007 
2008 			if (cvs_buf_len < USBVC_O_TERM_LEN_MIN) {
2009 
2010 				break;
2011 			}
2012 			term = (usbvc_terms_t *)
2013 			    kmem_zalloc(sizeof (usbvc_terms_t), KM_SLEEP);
2014 			term->descr = (usbvc_term_descr_t *)cvs_buf;
2015 
2016 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
2017 			    usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if:"
2018 			    " output term id= %x", term->descr->bTerminalID);
2019 			if (cvs_buf_len > 9) {
2020 				term->bSpecific = &cvs_buf[9];
2021 			}
2022 			list_insert_tail(&(usbvcp->usbvc_term_list), term);
2023 
2024 			break;
2025 		}
2026 		case VC_PROCESSING_UNIT:
2027 		{
2028 			uint8_t sz;
2029 			usbvc_units_t *unit;
2030 
2031 			if (usbvc_chk_descr_len(7, 1, 0, cvs_data) !=
2032 			    USB_SUCCESS) {
2033 
2034 				break;
2035 			}
2036 
2037 			/* bControlSize */
2038 			sz = cvs_buf[7];
2039 
2040 			if ((sz + 8) >= cvs_buf_len) {
2041 
2042 				break;
2043 			}
2044 			unit = (usbvc_units_t *)
2045 			    kmem_zalloc(sizeof (usbvc_units_t), KM_SLEEP);
2046 
2047 			unit->descr = (usbvc_unit_descr_t *)cvs_buf;
2048 
2049 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
2050 			    usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2051 			    "unit type=%x", unit->descr->bDescriptorSubType);
2052 
2053 			if (sz != 0) {
2054 				unit->bmControls = &cvs_buf[8];
2055 			}
2056 			unit->iProcessing = cvs_buf[8 + sz];
2057 
2058 			/*
2059 			 * video class 1.1 version add one element
2060 			 * (bmVideoStandards) to processing unit descriptor
2061 			 */
2062 			if (cvs_buf_len > (9 + sz)) {
2063 				unit->bmVideoStandards = cvs_buf[9 + sz];
2064 			}
2065 			list_insert_tail(&(usbvcp->usbvc_unit_list), unit);
2066 
2067 			break;
2068 		}
2069 		case VC_SELECTOR_UNIT:
2070 		{
2071 			uint8_t  pins;
2072 			usbvc_units_t *unit;
2073 
2074 			if (usbvc_chk_descr_len(4, 1, 0, cvs_data) !=
2075 			    USB_SUCCESS) {
2076 
2077 				break;
2078 			}
2079 			pins = cvs_buf[4];
2080 			if ((pins + 5) >= cvs_buf_len) {
2081 
2082 				break;
2083 			}
2084 			unit = (usbvc_units_t *)
2085 			    kmem_zalloc(sizeof (usbvc_units_t), KM_SLEEP);
2086 
2087 			unit->descr = (usbvc_unit_descr_t *)cvs_buf;
2088 
2089 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
2090 			    usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2091 			    "unit type=%x", unit->descr->bDescriptorSubType);
2092 			if (pins > 0) {
2093 				unit->baSourceID = &cvs_buf[5];
2094 			}
2095 			unit->iSelector = cvs_buf[5 + pins];
2096 
2097 			list_insert_tail(&(usbvcp->usbvc_unit_list), unit);
2098 
2099 			break;
2100 		}
2101 		case VC_EXTENSION_UNIT:
2102 		{
2103 			uint8_t  pins, n;
2104 			usbvc_units_t *unit;
2105 
2106 			if (usbvc_chk_descr_len(21, 1, 0, cvs_data) !=
2107 			    USB_SUCCESS) {
2108 
2109 				break;
2110 			}
2111 			pins = cvs_buf[21];
2112 			if ((pins + 22) >= cvs_buf_len) {
2113 
2114 				break;
2115 			}
2116 
2117 			/* Size of bmControls */
2118 			n = cvs_buf[pins + 22];
2119 
2120 			if (usbvc_chk_descr_len(pins + 22, 1, 0, cvs_data) !=
2121 			    USB_SUCCESS) {
2122 
2123 				break;
2124 			}
2125 			if ((23 + pins + n) >= cvs_buf_len) {
2126 
2127 				break;
2128 			}
2129 			unit = (usbvc_units_t *)
2130 			    kmem_zalloc(sizeof (usbvc_units_t), KM_SLEEP);
2131 
2132 			unit->descr = (usbvc_unit_descr_t *)cvs_buf;
2133 
2134 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
2135 			    usbvcp->usbvc_log_handle, "usbvc_parse_ctrl_if: "
2136 			    "unit type=%x", unit->descr->bDescriptorSubType);
2137 			if (pins != 0) {
2138 				unit->baSourceID = &cvs_buf[22];
2139 			}
2140 			unit->bControlSize = cvs_buf[22 + pins];
2141 
2142 			if (unit->bControlSize != 0) {
2143 				unit->bmControls = &cvs_buf[23 + pins];
2144 			}
2145 			unit->iExtension = cvs_buf[23 + pins + n];
2146 
2147 			list_insert_tail(&(usbvcp->usbvc_unit_list), unit);
2148 
2149 			break;
2150 		}
2151 		default:
2152 
2153 			break;
2154 		}
2155 	}
2156 
2157 	return (USB_SUCCESS);
2158 }
2159 
2160 
2161 /* Parse all the cvs descriptors in one stream interface. */
2162 usbvc_stream_if_t *
2163 usbvc_parse_stream_if(usbvc_state_t *usbvcp, int if_num)
2164 {
2165 	usb_alt_if_data_t	*if_alt_data;
2166 	uint_t			i, j;
2167 	usbvc_stream_if_t	*strm_if;
2168 	uint16_t		pktsize;
2169 	uint8_t			ep_adr;
2170 
2171 	strm_if = (usbvc_stream_if_t *)kmem_zalloc(sizeof (usbvc_stream_if_t),
2172 	    KM_SLEEP);
2173 	strm_if->if_descr = &usbvcp->usbvc_reg->dev_curr_cfg->cfg_if[if_num];
2174 	if_alt_data = strm_if->if_descr->if_alt;
2175 	if (usbvc_parse_stream_header(usbvcp, strm_if) != USB_SUCCESS) {
2176 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2177 		    "usbvc_parse_stream_if: parse header fail");
2178 		kmem_free(strm_if, sizeof (usbvc_stream_if_t));
2179 
2180 		return (NULL);
2181 	}
2182 	if (usbvc_parse_format_groups(usbvcp, strm_if) != USB_SUCCESS) {
2183 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2184 		    "usbvc_parse_stream_if: parse groups fail");
2185 		kmem_free(strm_if, sizeof (usbvc_stream_if_t));
2186 
2187 		return (NULL);
2188 	}
2189 
2190 	/* Parse the alternate settings to find the maximum bandwidth. */
2191 	for (i = 0; i < strm_if->if_descr->if_n_alt; i++) {
2192 		if_alt_data = &strm_if->if_descr->if_alt[i];
2193 		for (j = 0; j < if_alt_data->altif_n_ep; j++) {
2194 			ep_adr =
2195 			    if_alt_data->altif_ep[j].ep_descr.bEndpointAddress;
2196 			if (strm_if->input_header != NULL &&
2197 			    ep_adr !=
2198 			    strm_if->input_header->descr->bEndpointAddress) {
2199 
2200 				continue;
2201 			}
2202 			if (strm_if->output_header != NULL &&
2203 			    ep_adr !=
2204 			    strm_if->output_header->descr->bEndpointAddress) {
2205 
2206 				continue;
2207 			}
2208 			pktsize =
2209 			    if_alt_data->altif_ep[j].ep_descr.wMaxPacketSize;
2210 			pktsize = HS_PKT_SIZE(pktsize);
2211 			if (pktsize > strm_if->max_isoc_payload) {
2212 				strm_if->max_isoc_payload = pktsize;
2213 			}
2214 		}
2215 	}
2216 
2217 	/* initialize MJPEC FID toggle */
2218 	strm_if->fid = 0xff;
2219 	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2220 	    "usbvc_parse_stream_if: return. max_isoc_payload=%x",
2221 	    strm_if->max_isoc_payload);
2222 
2223 	return (strm_if);
2224 }
2225 
2226 
2227 /*
2228  * Parse all the stream interfaces asociated with the video control interface.
2229  * This driver will attach to a video control interface on the device,
2230  * there might be multiple video stream interfaces associated with one video
2231  * control interface.
2232  */
2233 static int
2234 usbvc_parse_stream_ifs(usbvc_state_t *usbvcp)
2235 {
2236 	int			i, if_cnt, if_num;
2237 	usbvc_stream_if_t	*strm_if;
2238 
2239 	if_cnt = usbvcp->usbvc_vc_header->descr->bInCollection;
2240 	if (if_cnt == 0) {
2241 		ASSERT(list_is_empty(&usbvcp->usbvc_stream_list));
2242 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2243 		    "usbvc_parse_stream_ifs: no stream interfaces");
2244 
2245 		return (USB_SUCCESS);
2246 	}
2247 	for (i = 0; i < if_cnt; i++) {
2248 		if_num = usbvcp->usbvc_vc_header->baInterfaceNr[i];
2249 		strm_if = usbvc_parse_stream_if(usbvcp, if_num);
2250 		if (strm_if == NULL) {
2251 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
2252 			    usbvcp->usbvc_log_handle, "usbvc_parse_stream_ifs:"
2253 			    " parse stream interface %d failed.", if_num);
2254 
2255 			return (USB_FAILURE);
2256 		}
2257 		/* video data buffers */
2258 		list_create(&(strm_if->buf_map.uv_buf_free),
2259 		    sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2260 		list_create(&(strm_if->buf_map.uv_buf_done),
2261 		    sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2262 		list_create(&(strm_if->buf_read.uv_buf_free),
2263 		    sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2264 		list_create(&(strm_if->buf_read.uv_buf_done),
2265 		    sizeof (usbvc_buf_t), offsetof(usbvc_buf_t, buf_node));
2266 
2267 		list_insert_tail(&(usbvcp->usbvc_stream_list), strm_if);
2268 	}
2269 
2270 	/* Make the first stream interface as the default one. */
2271 	usbvcp->usbvc_curr_strm =
2272 	    (usbvc_stream_if_t *)list_head(&usbvcp->usbvc_stream_list);
2273 
2274 	return (USB_SUCCESS);
2275 }
2276 
2277 
2278 /*
2279  * Parse colorspace descriptor and still image descriptor of a format group.
2280  * There is only one colorspace or still image descriptor in one format group.
2281  */
2282 static void
2283 usbvc_parse_color_still(usbvc_state_t *usbvcp, usbvc_format_group_t *fmtgrp,
2284 	usb_cvs_data_t *cvs_data, uint_t cvs_num, uint_t altif_n_cvs)
2285 {
2286 	uint8_t		frame_cnt;
2287 	uint_t		last_frame, i;
2288 	uchar_t		*cvs_buf;
2289 	uint_t			cvs_buf_len;
2290 
2291 	frame_cnt = fmtgrp->format->bNumFrameDescriptors;
2292 	last_frame = frame_cnt + cvs_num;
2293 
2294 	/*
2295 	 * Find the still image descr and color format descr if there are any.
2296 	 * UVC Spec: only one still image and one color descr is allowed in
2297 	 * one format group.
2298 	 */
2299 	for (i = 1; i <= 2; i++) {
2300 		if ((last_frame + i) >= altif_n_cvs) {
2301 
2302 			break;
2303 		}
2304 		cvs_buf = cvs_data[last_frame + i].cvs_buf;
2305 		cvs_buf_len = cvs_data[last_frame + i].cvs_buf_len;
2306 
2307 		if (cvs_buf[2] == VS_STILL_IMAGE_FRAME) {
2308 			uint8_t m, n, off;
2309 			usbvc_still_image_frame_t *st;
2310 
2311 			if (usbvc_chk_descr_len(4, 4, 0, cvs_data) !=
2312 			    USB_SUCCESS) {
2313 
2314 				continue;
2315 			}
2316 
2317 			/* Number of Image Size patterns of this format */
2318 			n = cvs_buf[4];
2319 
2320 			/* offset of bNumCompressionPattern */
2321 			off = 9 + 4 * n -4;
2322 
2323 			if (off >= cvs_buf_len) {
2324 
2325 				continue;
2326 			}
2327 
2328 			/* Number of compression pattern of this format */
2329 			m = cvs_buf[off];
2330 
2331 			if (usbvc_chk_descr_len(m, 1, 0, cvs_data) !=
2332 			    USB_SUCCESS) {
2333 
2334 				continue;
2335 			}
2336 			fmtgrp->still = (usbvc_still_image_frame_t *)
2337 			    kmem_zalloc(sizeof (usbvc_still_image_frame_t),
2338 			    KM_SLEEP);
2339 			st = fmtgrp->still;
2340 			st->descr = (usbvc_still_image_frame_descr_t *)cvs_buf;
2341 			n = st->descr->bNumImageSizePatterns;
2342 			if (n > 0) {
2343 				st->width_height =
2344 				    (width_height_t *)&cvs_buf[5];
2345 			}
2346 			st->bNumCompressionPattern = cvs_buf[off];
2347 			if (cvs_buf[off] > 0) {
2348 				st->bCompression = &cvs_buf[off + 1];
2349 			}
2350 		}
2351 		if (cvs_buf[2] == VS_COLORFORMAT) {
2352 			fmtgrp->color = (usbvc_color_matching_descr_t *)cvs_buf;
2353 			fmtgrp->v4l2_color = usbvc_v4l2_colorspace(
2354 			    fmtgrp->color->bColorPrimaries);
2355 		}
2356 	}
2357 	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2358 	    "usbvc_parse_color_still: still=%p, color=%p",
2359 	    fmtgrp->still, fmtgrp->color);
2360 }
2361 
2362 
2363 /*
2364  * Parse frame descriptors of a format group. There might be multi frame
2365  * descriptors in one format group.
2366  */
2367 static void
2368 usbvc_parse_frames(usbvc_state_t *usbvcp, usbvc_format_group_t *fmtgrp,
2369 	usb_cvs_data_t *cvs_data, uint_t cvs_num, uint_t altif_n_cvs)
2370 {
2371 	uint_t		last_frame;
2372 	usbvc_frames_t	*frm;
2373 	usb_cvs_data_t		*cvs;
2374 	uchar_t		*cvs_buf;
2375 	uint_t			cvs_buf_len;
2376 	uint8_t		i;
2377 	uint8_t		frame_cnt = fmtgrp->format->bNumFrameDescriptors;
2378 
2379 	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2380 	    "usbvc_parse_format_group: frame_cnt=%d", frame_cnt);
2381 
2382 	if (frame_cnt == 0) {
2383 		fmtgrp->frames = NULL;
2384 
2385 		return;
2386 	}
2387 
2388 	/* All these mem allocated will be freed in cleanup() */
2389 	fmtgrp->frames = (usbvc_frames_t *)
2390 	    kmem_zalloc(sizeof (usbvc_frames_t) * frame_cnt, KM_SLEEP);
2391 
2392 	last_frame = frame_cnt + cvs_num;
2393 	cvs_num++;
2394 	i = 0;
2395 
2396 	/*
2397 	 * Traverse from the format decr's first frame decr to the the last
2398 	 * frame descr.
2399 	 */
2400 	for (; cvs_num <= last_frame; cvs_num++) {
2401 		USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2402 		    "usbvc_parse_frames: cvs_num=%d, i=%d", cvs_num, i);
2403 		if (cvs_num >= altif_n_cvs) {
2404 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
2405 			    usbvcp->usbvc_log_handle,
2406 			    "usbvc_parse_frames: less frames than "
2407 			    "expected, cvs_num=%d, i=%d", cvs_num, i);
2408 
2409 			break;
2410 		}
2411 		cvs = &cvs_data[cvs_num];
2412 		cvs_buf = cvs->cvs_buf;
2413 		cvs_buf_len = cvs->cvs_buf_len;
2414 		if (cvs_buf_len < USBVC_FRAME_LEN_MIN) {
2415 			i++;
2416 
2417 			continue;
2418 		}
2419 		frm = &fmtgrp->frames[i];
2420 		frm->descr = (usbvc_frame_descr_t *)cvs->cvs_buf;
2421 
2422 		/* Descriptor for discrete frame interval */
2423 		if (frm->descr->bFrameIntervalType > 0) {
2424 			if (usbvc_chk_descr_len(25, 4, 0, cvs) != USB_SUCCESS) {
2425 				frm->descr = NULL;
2426 				i++;
2427 
2428 				continue;
2429 			}
2430 
2431 			frm->dwFrameInterval = (uint32_t *)&cvs_buf[26];
2432 		} else {	/* Continuous interval */
2433 			if (cvs_buf_len < USBVC_FRAME_LEN_CON) {
2434 				frm->descr = NULL;
2435 				i++;
2436 
2437 				continue;
2438 			}
2439 
2440 			/* Continuous frame intervals */
2441 			LE_TO_UINT32(cvs_buf, 26, frm->dwMinFrameInterval);
2442 			LE_TO_UINT32(cvs_buf, 30, frm->dwMaxFrameInterval);
2443 			LE_TO_UINT32(cvs_buf, 34, frm->dwFrameIntervalStep);
2444 		}
2445 
2446 		i++;
2447 	}
2448 	fmtgrp->frame_cnt = i;
2449 	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2450 	    "usbvc_parse_frames: %d frames are actually parsed",
2451 	    fmtgrp->frame_cnt);
2452 }
2453 
2454 
2455 /* Parse one of the format groups in a stream interface */
2456 static int
2457 usbvc_parse_format_group(usbvc_state_t *usbvcp, usbvc_format_group_t *fmtgrp,
2458 	usb_cvs_data_t *cvs_data, uint_t cvs_num, uint_t altif_n_cvs)
2459 {
2460 	usbvc_format_descr_t *fmt;
2461 
2462 	fmt = fmtgrp->format;
2463 	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2464 		"usbvc_parse_format_group: frame_cnt=%d, cvs_num=%d",
2465 		fmt->bNumFrameDescriptors, cvs_num);
2466 
2467 	switch (fmt->bDescriptorSubType) {
2468 	case VS_FORMAT_UNCOMPRESSED:
2469 		usbvc_parse_color_still(usbvcp, fmtgrp, cvs_data, cvs_num,
2470 		    altif_n_cvs);
2471 		usbvc_parse_frames(usbvcp, fmtgrp, cvs_data, cvs_num,
2472 		    altif_n_cvs);
2473 		fmtgrp->v4l2_bpp = 16;
2474 		fmtgrp->v4l2_pixelformat = usbvc_v4l2_guid2fcc(
2475 		    (uint8_t *)&fmt->fmt.uncompressed.guidFormat);
2476 
2477 		break;
2478 	case VS_FORMAT_MJPEG:
2479 		usbvc_parse_color_still(usbvcp, fmtgrp, cvs_data, cvs_num,
2480 		    altif_n_cvs);
2481 		usbvc_parse_frames(usbvcp, fmtgrp, cvs_data, cvs_num,
2482 		    altif_n_cvs);
2483 		fmtgrp->v4l2_bpp = 0;
2484 		fmtgrp->v4l2_pixelformat = V4L2_PIX_FMT_MJPEG;
2485 
2486 		break;
2487 	case VS_FORMAT_MPEG2TS:
2488 	case VS_FORMAT_DV:
2489 	case VS_FORMAT_FRAME_BASED:
2490 	case VS_FORMAT_STREAM_BASED:
2491 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2492 		    "usbvc_parse_format_group: format not supported yet.");
2493 
2494 		return (USB_FAILURE);
2495 	default:
2496 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2497 		    "usbvc_parse_format_group: unknown format.");
2498 
2499 		return (USB_FAILURE);
2500 	}
2501 
2502 	return (USB_SUCCESS);
2503 }
2504 
2505 
2506 /* Parse the descriptors belong to one format */
2507 static int
2508 usbvc_parse_format_groups(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2509 {
2510 	usb_alt_if_data_t	*if_alt_data;
2511 	usb_cvs_data_t		*cvs_data;
2512 	uint8_t			fmtgrp_num, fmtgrp_cnt;
2513 	uchar_t			*cvs_buf;
2514 	uint_t			cvs_num = 0;
2515 	usbvc_format_group_t	*fmtgrp;
2516 
2517 	fmtgrp_cnt = 0;
2518 	/*
2519 	 * bNumFormats indicates the number of formats in this stream
2520 	 * interface. On some devices, we see this number is larger than
2521 	 * the truth.
2522 	 */
2523 	if (strm_if->input_header) {
2524 		fmtgrp_cnt = strm_if->input_header->descr->bNumFormats;
2525 	} else if (strm_if->output_header) {
2526 		fmtgrp_cnt = strm_if->output_header->descr->bNumFormats;
2527 	}
2528 	if (!fmtgrp_cnt) {
2529 
2530 		return (USB_FAILURE);
2531 	}
2532 	USB_DPRINTF_L3(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2533 	    "usbvc_parse_format_groups: fmtgrp_cnt=%d", fmtgrp_cnt);
2534 
2535 	fmtgrp = (usbvc_format_group_t *)
2536 	    kmem_zalloc(sizeof (usbvc_format_group_t) * fmtgrp_cnt, KM_SLEEP);
2537 
2538 	if_alt_data = strm_if->if_descr->if_alt;
2539 	cvs_data = if_alt_data->altif_cvs;
2540 	for (fmtgrp_num = 0; fmtgrp_num < fmtgrp_cnt; fmtgrp_num++) {
2541 
2542 		/* find the next format descriptor */
2543 		for (; cvs_num < if_alt_data->altif_n_cvs; cvs_num++) {
2544 			cvs_buf = cvs_data[cvs_num].cvs_buf;
2545 			switch (cvs_buf[2]) {
2546 			case VS_FORMAT_UNCOMPRESSED:
2547 			case VS_FORMAT_MJPEG:
2548 			case VS_FORMAT_MPEG2TS:
2549 			case VS_FORMAT_DV:
2550 			case VS_FORMAT_FRAME_BASED:
2551 			case VS_FORMAT_STREAM_BASED:
2552 				fmtgrp[fmtgrp_num].format =
2553 				    (usbvc_format_descr_t *)cvs_buf;
2554 
2555 				break;
2556 			default:
2557 
2558 				break;
2559 			}
2560 			if (fmtgrp[fmtgrp_num].format) {
2561 
2562 				break;
2563 			}
2564 		}
2565 
2566 		/* If can't find the next format, then break. */
2567 		if (!(fmtgrp[fmtgrp_num].format)) {
2568 			strm_if->fmtgrp_cnt = fmtgrp_num;
2569 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
2570 			    usbvcp->usbvc_log_handle,
2571 			    "usbvc_parse_format_groups: acctually %d formats"
2572 			    " parsed", fmtgrp_num);
2573 
2574 			break;
2575 		}
2576 
2577 		/*
2578 		 * Now cvs_data[cvs_num].cvs_buf is format descriptor,
2579 		 * usbvc_parse_format_group will then parse the frame
2580 		 * descriptors following this format descriptor.
2581 		 */
2582 		(void) usbvc_parse_format_group(usbvcp, &fmtgrp[fmtgrp_num],
2583 		    cvs_data, cvs_num, if_alt_data->altif_n_cvs);
2584 
2585 		/*
2586 		 * cvs_data[cvs_num].cvs_buf is the one was parsed, so plus
2587 		 * 1 to move to the next format group
2588 		 */
2589 		cvs_num++;
2590 	}
2591 
2592 	/*
2593 	 * If can't find any formats, then free all allocated
2594 	 * usbvc_format_group_t, return failure.
2595 	 */
2596 	if (!(fmtgrp[0].format)) {
2597 		kmem_free(fmtgrp, sizeof (usbvc_format_group_t) * fmtgrp_cnt);
2598 		strm_if->format_group = NULL;
2599 
2600 		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2601 		    "usbvc_parse_format_groups: can't find any formats");
2602 
2603 		return (USB_FAILURE);
2604 	}
2605 	strm_if->format_group = fmtgrp;
2606 	USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2607 	    "usbvc_parse_format_groups: %d format groups parsed", fmtgrp_num);
2608 
2609 	return (USB_SUCCESS);
2610 }
2611 
2612 
2613 /*
2614  * Parse the input/output header in one stream interface.
2615  * UVC Spec: there must be one and only one header in one stream interface.
2616  */
2617 int
2618 usbvc_parse_stream_header(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2619 {
2620 	usb_alt_if_data_t	*if_alt_data;
2621 	usb_cvs_data_t		*cvs_data;
2622 	int			cvs_num;
2623 	uchar_t			*cvs_buf;
2624 	usbvc_input_header_t	*in_hdr;
2625 	usbvc_output_header_t	*out_hdr;
2626 
2627 	if_alt_data = strm_if->if_descr->if_alt;
2628 	cvs_data = if_alt_data->altif_cvs;
2629 	for (cvs_num = 0; cvs_num < if_alt_data->altif_n_cvs; cvs_num++) {
2630 	    cvs_buf = cvs_data[cvs_num].cvs_buf;
2631 	    USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2632 		    "usbvc_parse_stream_header: cvs_num= %d", cvs_num);
2633 
2634 		/*
2635 		 * parse interface cvs descriptors here; by checking
2636 		 * bDescriptorType (cvs_buf[1])
2637 		 */
2638 		if (cvs_buf[1] != CS_INTERFACE) {
2639 
2640 			continue;
2641 		}
2642 
2643 		if (cvs_buf[2] == VS_INPUT_HEADER) {
2644 			if (usbvc_chk_descr_len(3, 0, 12, cvs_data) !=
2645 			    USB_SUCCESS) {
2646 
2647 				continue;
2648 			}
2649 
2650 			strm_if->input_header =
2651 			    (usbvc_input_header_t *)
2652 			    kmem_zalloc(sizeof (usbvc_input_header_t),
2653 			    KM_SLEEP);
2654 			in_hdr = strm_if->input_header;
2655 			in_hdr->descr = (usbvc_input_header_descr_t *)cvs_buf;
2656 			if (in_hdr->descr->bNumFormats > 0) {
2657 				in_hdr->bmaControls = &cvs_buf[13];
2658 			}
2659 
2660 			return (USB_SUCCESS);
2661 		} else if (cvs_buf[2] == VS_OUTPUT_HEADER) {
2662 			if (usbvc_chk_descr_len(3, 0, 8, cvs_data) !=
2663 			    USB_SUCCESS) {
2664 
2665 				continue;
2666 			}
2667 			strm_if->output_header =
2668 			    (usbvc_output_header_t *)
2669 			    kmem_zalloc(sizeof (usbvc_output_header_t),
2670 			    KM_SLEEP);
2671 			out_hdr = strm_if->output_header;
2672 			out_hdr->descr =
2673 			    (usbvc_output_header_descr_t *)cvs_buf;
2674 			if (out_hdr->descr->bNumFormats > 0) {
2675 				out_hdr->bmaControls = &cvs_buf[13];
2676 			}
2677 
2678 			return (USB_SUCCESS);
2679 		} else {
2680 
2681 			continue;
2682 		}
2683 	}
2684 	/* Didn't find one header descriptor. */
2685 	USB_DPRINTF_L2(PRINT_MASK_ATTA, usbvcp->usbvc_log_handle,
2686 	    "usbvc_parse_stream_header: FAIL");
2687 
2688 	return (USB_FAILURE);
2689 }
2690 
2691 /* read I/O functions */
2692 
2693 /* Allocate bufs for read I/O method */
2694 static int
2695 usbvc_alloc_read_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2696 {
2697 	usbvc_buf_t	*buf;
2698 	uchar_t		*data;
2699 	int		i;
2700 	uint32_t	len;
2701 
2702 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2703 
2704 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, len);
2705 	if (!len) {
2706 
2707 		return (USB_FAILURE);
2708 	}
2709 	for (i = 0; i < USBVC_READ_BUF_NUM; i++) {
2710 		mutex_exit(&usbvcp->usbvc_mutex);
2711 		buf = (usbvc_buf_t *)kmem_zalloc(sizeof (usbvc_buf_t),
2712 		    KM_SLEEP);
2713 		data = (uchar_t *)kmem_zalloc(len, KM_SLEEP);
2714 		mutex_enter(&usbvcp->usbvc_mutex);
2715 		buf->data = data;
2716 		buf->len = len;
2717 		list_insert_tail(&(strm_if->buf_read.uv_buf_free), buf);
2718 	}
2719 	strm_if->buf_read.buf_cnt = USBVC_READ_BUF_NUM;
2720 	USB_DPRINTF_L4(PRINT_MASK_READ, usbvcp->usbvc_log_handle,
2721 	    "read_bufs: %d bufs allocated", strm_if->buf_read.buf_cnt);
2722 
2723 	return (USB_SUCCESS);
2724 }
2725 
2726 
2727 /* Read a done buf, copy data to bp. This function is for read I/O method */
2728 static int
2729 usbvc_read_buf(usbvc_state_t *usbvcp, struct buf *bp)
2730 {
2731 	usbvc_buf_t	*buf;
2732 
2733 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2734 
2735 	/* read a buf from full list and then put it to free list */
2736 	buf = list_head(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_done);
2737 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2738 	    "usbvc_read_buf: buf=%p, buf->filled=%d, bfu->len=%d,"
2739 	    " bp->b_bcount=%d, bp->b_resid=%d",
2740 	    buf, buf->filled, buf->len, bp->b_bcount, bp->b_resid);
2741 
2742 	list_remove(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_done, buf);
2743 	bcopy(buf->data, bp->b_un.b_addr, buf->filled);
2744 	bp->b_private = NULL;
2745 	bp->b_resid = bp->b_bcount - buf->filled;
2746 	list_insert_tail(&usbvcp->usbvc_curr_strm->buf_read.uv_buf_free, buf);
2747 
2748 	return (USB_SUCCESS);
2749 }
2750 
2751 
2752 /* Free one buf which is for read/write IO style */
2753 static void
2754 usbvc_free_read_buf(usbvc_buf_t *buf)
2755 {
2756 	if (buf != NULL) {
2757 		if (buf->data) {
2758 			kmem_free(buf->data, buf->len);
2759 		}
2760 		kmem_free(buf, sizeof (usbvc_buf_t));
2761 	}
2762 }
2763 
2764 
2765 /* Free all bufs which are for read/write IO style */
2766 static void
2767 usbvc_free_read_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2768 {
2769 	usbvc_buf_t	*buf;
2770 
2771 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2772 
2773 	if (!strm_if) {
2774 
2775 		return;
2776 	}
2777 	buf = strm_if->buf_read.buf_filling;
2778 	usbvc_free_read_buf(buf);
2779 	strm_if->buf_read.buf_filling = NULL;
2780 
2781 	while (!list_is_empty(&strm_if->buf_read.uv_buf_free)) {
2782 		buf = list_head(&strm_if->buf_read.uv_buf_free);
2783 		if (buf != NULL) {
2784 			list_remove(&(strm_if->buf_read.uv_buf_free), buf);
2785 			usbvc_free_read_buf(buf);
2786 		}
2787 	}
2788 	while (!list_is_empty(&strm_if->buf_read.uv_buf_done)) {
2789 		buf = list_head(&strm_if->buf_read.uv_buf_done);
2790 		if (buf != NULL) {
2791 			list_remove(&(strm_if->buf_read.uv_buf_done), buf);
2792 			usbvc_free_read_buf(buf);
2793 		}
2794 	}
2795 	strm_if->buf_read.buf_cnt = 0;
2796 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
2797 	    "usbvc_free_read_bufs: return");
2798 }
2799 
2800 
2801 /*
2802  * Allocate bufs for mapped I/O , return the number of allocated bufs
2803  * if success, return 0 if fail.
2804  */
2805 int
2806 usbvc_alloc_map_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
2807 	int buf_cnt, int buf_len)
2808 {
2809 	int		i = 0;
2810 	usbvc_buf_t	*bufs;
2811 
2812 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2813 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2814 	    "usbvc_alloc_map_bufs: bufcnt=%d, buflen=%d", buf_cnt, buf_len);
2815 	if (buf_len <= 0 || buf_cnt <= 0) {
2816 		USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2817 		    "usbvc_alloc_map_bufs: len<=0, cnt<=0");
2818 
2819 		return (0);
2820 	}
2821 	mutex_exit(&usbvcp->usbvc_mutex);
2822 
2823 	bufs = (usbvc_buf_t *) kmem_zalloc(sizeof (usbvc_buf_t) * buf_cnt,
2824 	    KM_SLEEP);
2825 
2826 	mutex_enter(&usbvcp->usbvc_mutex);
2827 	strm_if->buf_map.buf_head = bufs;
2828 	buf_len = ptob(btopr(buf_len));
2829 
2830 	mutex_exit(&usbvcp->usbvc_mutex);
2831 	bufs[0].data = ddi_umem_alloc(buf_len * buf_cnt, DDI_UMEM_SLEEP,
2832 				    &bufs[0].umem_cookie);
2833 	mutex_enter(&usbvcp->usbvc_mutex);
2834 
2835 	for (i = 0; i < buf_cnt; i++) {
2836 		bufs[i].len = buf_len;
2837 		bufs[i].data = bufs[0].data + (buf_len * i);
2838 		bufs[i].umem_cookie = bufs[0].umem_cookie;
2839 		bufs[i].status = USBVC_BUF_INIT;
2840 
2841 		bufs[i].v4l2_buf.index = i;
2842 		bufs[i].v4l2_buf.m.offset = i * bufs[i].len;
2843 		bufs[i].v4l2_buf.length = bufs[i].len;
2844 		bufs[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2845 		bufs[i].v4l2_buf.sequence = 0;
2846 		bufs[i].v4l2_buf.field = V4L2_FIELD_NONE;
2847 		bufs[i].v4l2_buf.memory = V4L2_MEMORY_MMAP;
2848 		bufs[i].v4l2_buf.flags = V4L2_MEMORY_MMAP;
2849 
2850 		list_insert_tail(&strm_if->buf_map.uv_buf_free, &bufs[i]);
2851 		USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2852 		    "usbvc_alloc_map_bufs: prepare %d buffers of %d bytes",
2853 		    buf_cnt, bufs[i].len);
2854 	}
2855 	strm_if->buf_map.buf_cnt = buf_cnt;
2856 	strm_if->buf_map.buf_filling = NULL;
2857 
2858 	return (buf_cnt);
2859 }
2860 
2861 
2862 /* Free all bufs which are for memory map IO style */
2863 void
2864 usbvc_free_map_bufs(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2865 {
2866 	usbvc_buf_t	*buf;
2867 
2868 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2869 	if (!strm_if) {
2870 
2871 		return;
2872 	}
2873 	strm_if->buf_map.buf_filling = NULL;
2874 	while (!list_is_empty(&strm_if->buf_map.uv_buf_free)) {
2875 		buf = (usbvc_buf_t *)list_head(&strm_if->buf_map.uv_buf_free);
2876 		list_remove(&(strm_if->buf_map.uv_buf_free), buf);
2877 	}
2878 	while (!list_is_empty(&strm_if->buf_map.uv_buf_done)) {
2879 		buf = (usbvc_buf_t *)list_head(&strm_if->buf_map.uv_buf_done);
2880 		list_remove(&(strm_if->buf_map.uv_buf_done), buf);
2881 	}
2882 	buf = strm_if->buf_map.buf_head;
2883 	if (!buf) {
2884 		USB_DPRINTF_L2(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
2885 		    "usbvc_free_map_bufs: no data buf need be freed, return");
2886 
2887 		return;
2888 	}
2889 	if (buf->umem_cookie) {
2890 		ddi_umem_free(buf->umem_cookie);
2891 	}
2892 	kmem_free(buf, sizeof (usbvc_buf_t) * strm_if->buf_map.buf_cnt);
2893 	strm_if->buf_map.buf_cnt = 0;
2894 	strm_if->buf_map.buf_head = NULL;
2895 
2896 	USB_DPRINTF_L2(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
2897 	    "usbvc_free_map_bufs: return");
2898 }
2899 
2900 
2901 /*
2902  * Open the isoc pipe, this pipe is for video data transfer
2903  */
2904 int
2905 usbvc_open_isoc_pipe(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2906 {
2907 	usb_pipe_policy_t policy;
2908 	int	rval = USB_SUCCESS;
2909 
2910 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2911 
2912 	if ((rval = usbvc_set_alt(usbvcp, strm_if)) != USB_SUCCESS) {
2913 
2914 		return (rval);
2915 	}
2916 	bzero(&policy, sizeof (usb_pipe_policy_t));
2917 	policy.pp_max_async_reqs = 2;
2918 	mutex_exit(&usbvcp->usbvc_mutex);
2919 	if ((rval = usb_pipe_open(usbvcp->usbvc_dip, strm_if->curr_ep, &policy,
2920 	    USB_FLAGS_SLEEP, &strm_if->datain_ph)) != USB_SUCCESS) {
2921 		USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2922 		    "usbvc_open_isoc_pipe: open pipe fail");
2923 		mutex_enter(&usbvcp->usbvc_mutex);
2924 
2925 		return (rval);
2926 	}
2927 	mutex_enter(&usbvcp->usbvc_mutex);
2928 	strm_if->start_polling = 0;
2929 
2930 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
2931 	    "usbvc_open_isoc_pipe: success, datain_ph=%p", strm_if->datain_ph);
2932 
2933 	return (rval);
2934 }
2935 
2936 
2937 /*
2938  * Open the isoc pipe
2939  */
2940 static void
2941 usbvc_close_isoc_pipe(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
2942 {
2943 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2944 	if (!strm_if) {
2945 		USB_DPRINTF_L2(PRINT_MASK_CLOSE, usbvcp->usbvc_log_handle,
2946 		    "usbvc_close_isoc_pipe: stream interface is NULL");
2947 
2948 		return;
2949 	}
2950 	if (strm_if->datain_ph) {
2951 		mutex_exit(&usbvcp->usbvc_mutex);
2952 		usb_pipe_close(usbvcp->usbvc_dip, strm_if->datain_ph,
2953 		    USB_FLAGS_SLEEP, NULL, NULL);
2954 		mutex_enter(&usbvcp->usbvc_mutex);
2955 	}
2956 	strm_if->datain_ph = NULL;
2957 }
2958 
2959 
2960 /*
2961  * Start to get video data from isoc pipe in the stream interface,
2962  * issue isoc req.
2963  */
2964 int
2965 usbvc_start_isoc_polling(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
2966     uchar_t io_type)
2967 {
2968 	int		rval = USB_SUCCESS;
2969 	uint_t		if_num;
2970 	usb_isoc_req_t	*req;
2971 	ushort_t	pkt_size;
2972 	ushort_t	n_pkt, pkt;
2973 	uint32_t	frame_size;
2974 
2975 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
2976 	pkt_size = strm_if->curr_ep->wMaxPacketSize;
2977 	if_num = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
2978 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, frame_size);
2979 	n_pkt = (frame_size + HS_PKT_SIZE(pkt_size) -1)
2980 	    / HS_PKT_SIZE(pkt_size);
2981 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
2982 	    "usbvc_start_isoc_polling: if_num=%d, alt=%d, n_pkt=%d,"
2983 	    " pkt_size=0x%x, frame_size=0x%x",
2984 	    if_num, strm_if->curr_alt, n_pkt, pkt_size, frame_size);
2985 
2986 	if (n_pkt > USBVC_MAX_PKTS) {
2987 		n_pkt = USBVC_MAX_PKTS;
2988 	}
2989 	USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
2990 		"usbvc_start_isoc_polling: n_pkt=%d", n_pkt);
2991 
2992 	mutex_exit(&usbvcp->usbvc_mutex);
2993 	if ((req = usb_alloc_isoc_req(usbvcp->usbvc_dip, n_pkt,
2994 	    n_pkt * pkt_size, USB_FLAGS_SLEEP)) != NULL) {
2995 		mutex_enter(&usbvcp->usbvc_mutex);
2996 
2997 		/* Initialize the packet descriptor */
2998 		for (pkt = 0; pkt < n_pkt; pkt++) {
2999 			req->isoc_pkt_descr[pkt].isoc_pkt_length = pkt_size;
3000 		}
3001 
3002 		req->isoc_pkts_count = n_pkt;
3003 
3004 		/*
3005 		 * zero here indicates that HCDs will use
3006 		 * isoc_pkt_descr->isoc_pkt_length to calculate
3007 		 * isoc_pkts_length.
3008 		 */
3009 		req->isoc_pkts_length = 0;
3010 		req->isoc_attributes = USB_ATTRS_ISOC_XFER_ASAP |
3011 		    USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
3012 		req->isoc_cb = usbvc_isoc_cb;
3013 		req->isoc_exc_cb = usbvc_isoc_exc_cb;
3014 		usbvcp->usbvc_io_type = io_type;
3015 		req->isoc_client_private = (usb_opaque_t)usbvcp;
3016 		mutex_exit(&usbvcp->usbvc_mutex);
3017 		rval = usb_pipe_isoc_xfer(strm_if->datain_ph, req, 0);
3018 		mutex_enter(&usbvcp->usbvc_mutex);
3019 	} else {
3020 		mutex_enter(&usbvcp->usbvc_mutex);
3021 		USB_DPRINTF_L2(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
3022 		    "usbvc_start_isoc_polling: alloc_isoc_req fail");
3023 
3024 		return (USB_FAILURE);
3025 	}
3026 
3027 	if (rval != USB_SUCCESS) {
3028 		if (req) {
3029 			usb_free_isoc_req(req);
3030 			req = NULL;
3031 		}
3032 	}
3033 	USB_DPRINTF_L4(PRINT_MASK_IOCTL, usbvcp->usbvc_log_handle,
3034 		"usbvc_start_isoc_polling: return, rval=%d", rval);
3035 
3036 	return (rval);
3037 }
3038 
3039 /* callbacks for receiving video data (isco in transfer) */
3040 
3041 /*ARGSUSED*/
3042 /* Isoc transfer callback, get video data */
3043 static void
3044 usbvc_isoc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
3045 {
3046 	usbvc_state_t	*usbvcp =
3047 			    (usbvc_state_t *)isoc_req->isoc_client_private;
3048 	int		i;
3049 	mblk_t		*data = isoc_req->isoc_data;
3050 	usbvc_buf_grp_t	*bufgrp;
3051 
3052 	mutex_enter(&usbvcp->usbvc_mutex);
3053 
3054 	USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3055 	    "usbvc_isoc_cb: rq=0x%p, fno=%" PRId64 ", n_pkts=%u, flag=0x%x,"
3056 	    " data=0x%p, cnt=%d",
3057 	    isoc_req, isoc_req->isoc_frame_no, isoc_req->isoc_pkts_count,
3058 	    isoc_req->isoc_attributes, isoc_req->isoc_data,
3059 	    isoc_req->isoc_error_count);
3060 
3061 	ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) != 0);
3062 	for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
3063 
3064 		USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3065 		    "\tpkt%d: "
3066 		    "pktsize=%d status=%d resid=%d",
3067 		    i,
3068 		    isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
3069 		    isoc_req->isoc_pkt_descr[i].isoc_pkt_status,
3070 		    isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length);
3071 
3072 		if (isoc_req->isoc_pkt_descr[i].isoc_pkt_status !=
3073 		    USB_CR_OK) {
3074 			USB_DPRINTF_L3(PRINT_MASK_CB,
3075 			    usbvcp->usbvc_log_handle,
3076 			    "record: pkt=%d status=%s", i, usb_str_cr(
3077 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_status));
3078 		}
3079 
3080 		if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
3081 			bufgrp = &usbvcp->usbvc_curr_strm->buf_map;
3082 		} else {
3083 			bufgrp = &usbvcp->usbvc_curr_strm->buf_read;
3084 		}
3085 
3086 		if (isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length) {
3087 			if (usbvc_decode_stream_header(usbvcp, bufgrp, data,
3088 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length)
3089 			    != USB_SUCCESS) {
3090 				USB_DPRINTF_L3(PRINT_MASK_CB,
3091 				    usbvcp->usbvc_log_handle, "decode error");
3092 			}
3093 			if (bufgrp->buf_filling &&
3094 			    (bufgrp->buf_filling->status == USBVC_BUF_ERR ||
3095 			    bufgrp->buf_filling->status == USBVC_BUF_DONE)) {
3096 
3097 				/* Move the buf to the full list */
3098 				list_insert_tail(&bufgrp->uv_buf_done,
3099 				    bufgrp->buf_filling);
3100 
3101 				bufgrp->buf_filling = NULL;
3102 
3103 				if (usbvcp->usbvc_io_type == V4L2_MEMORY_MMAP) {
3104 					cv_broadcast(&usbvcp->usbvc_mapio_cv);
3105 				} else {
3106 					cv_broadcast(&usbvcp->usbvc_read_cv);
3107 				}
3108 			}
3109 		}
3110 		data->b_rptr +=
3111 		    HS_PKT_SIZE(isoc_req->isoc_pkt_descr[i].isoc_pkt_length);
3112 	}
3113 	mutex_exit(&usbvcp->usbvc_mutex);
3114 	usb_free_isoc_req(isoc_req);
3115 }
3116 
3117 
3118 /*ARGSUSED*/
3119 static void
3120 usbvc_isoc_exc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
3121 {
3122 	usbvc_state_t	*usbvcp =
3123 			    (usbvc_state_t *)isoc_req->isoc_client_private;
3124 	usb_cr_t	completion_reason;
3125 	int		rval;
3126 	usbvc_stream_if_t	*strm_if;
3127 
3128 	ASSERT(!list_is_empty(&usbvcp->usbvc_stream_list));
3129 
3130 	mutex_enter(&usbvcp->usbvc_mutex);
3131 
3132 	/* get the first stream interface */
3133 	strm_if = usbvcp->usbvc_curr_strm;
3134 
3135 	completion_reason = isoc_req->isoc_completion_reason;
3136 
3137 	USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3138 	    "usbvc_isoc_exc_cb: ph=0x%p, isoc_req=0x%p, cr=%d",
3139 	    (void *)ph, (void *)isoc_req, completion_reason);
3140 
3141 	ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) == 0);
3142 
3143 	switch (completion_reason) {
3144 	case USB_CR_STOPPED_POLLING:
3145 	case USB_CR_PIPE_CLOSING:
3146 	case USB_CR_PIPE_RESET:
3147 
3148 		break;
3149 	case USB_CR_NO_RESOURCES:
3150 		/*
3151 		 * keep the show going: Since we have the original
3152 		 * request, we just resubmit it
3153 		 */
3154 		rval = usb_pipe_isoc_xfer(strm_if->datain_ph, isoc_req,
3155 		    USB_FLAGS_NOSLEEP);
3156 		USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3157 		    "usbvc_isoc_exc_cb: restart capture rval=%d", rval);
3158 		mutex_exit(&usbvcp->usbvc_mutex);
3159 
3160 		return;
3161 	default:
3162 		mutex_exit(&usbvcp->usbvc_mutex);
3163 		usb_pipe_stop_isoc_polling(ph, USB_FLAGS_NOSLEEP);
3164 		USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3165 		    "usbvc_isoc_exc_cb: stop polling");
3166 		mutex_enter(&usbvcp->usbvc_mutex);
3167 	}
3168 	usb_free_isoc_req(isoc_req);
3169 	strm_if->start_polling = 0;
3170 	USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3171 	    "usbvc_isoc_exc_cb: start_polling=%d cr=%d",
3172 	    strm_if->start_polling, completion_reason);
3173 	mutex_exit(&usbvcp->usbvc_mutex);
3174 }
3175 
3176 /*
3177  * Other utility functions
3178  */
3179 
3180 /*
3181  * Find a proper alternate according to the bandwidth that the current video
3182  * format need;
3183  * Set alternate by calling usb_set_alt_if;
3184  * Called before open pipes in stream interface.
3185  */
3186 static int
3187 usbvc_set_alt(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if)
3188 {
3189 	usb_alt_if_data_t	*alt;
3190 	uint_t			i, j, if_num;
3191 	uint16_t		pktsize, curr_pktsize;
3192 	uint32_t		bandwidth;
3193 	int			rval = USB_SUCCESS;
3194 	usbvc_input_header_t	*ihd;
3195 	usbvc_output_header_t	*ohd;
3196 
3197 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3198 
3199 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxPayloadTransferSize, 0, bandwidth);
3200 	if (!bandwidth) {
3201 		USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3202 		    "usbvc_set_alt: bandwidth is not set yet");
3203 
3204 		return (USB_FAILURE);
3205 	}
3206 	USB_DPRINTF_L3(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3207 		"usbvc_set_alt: bandwidth=%x", bandwidth);
3208 
3209 	strm_if->curr_ep = NULL;
3210 	curr_pktsize = 0xffff;
3211 	ohd = strm_if->output_header;
3212 	ihd = strm_if->input_header;
3213 	/*
3214 	 * Find one alternate setting whose isoc ep's max pktsize is just
3215 	 * enough for the bandwidth.
3216 	 */
3217 	for (i = 0; i < strm_if->if_descr->if_n_alt; i++) {
3218 		alt = &strm_if->if_descr->if_alt[i];
3219 
3220 		for (j = 0; j < alt->altif_n_ep; j++) {
3221 
3222 			/* if this stream interface is for input */
3223 			if (ihd != NULL &&
3224 			    alt->altif_ep[j].ep_descr.bEndpointAddress !=
3225 			    ihd->descr->bEndpointAddress) {
3226 
3227 				continue;
3228 			}
3229 			/*  if this stream interface is for output */
3230 			if (ohd != NULL &&
3231 			    alt->altif_ep[j].ep_descr.bEndpointAddress !=
3232 			    ohd->descr->bEndpointAddress) {
3233 
3234 				continue;
3235 			}
3236 			pktsize =
3237 			    alt->altif_ep[j].ep_descr.wMaxPacketSize;
3238 			pktsize = HS_PKT_SIZE(pktsize);
3239 			if (pktsize >= bandwidth && pktsize < curr_pktsize) {
3240 				curr_pktsize = pktsize;
3241 				strm_if->curr_alt = i;
3242 				strm_if->curr_ep = &alt->altif_ep[j].ep_descr;
3243 			}
3244 		}
3245 	}
3246 	if (!strm_if->curr_ep) {
3247 		USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3248 		    "usbvc_set_alt: can't find a proper ep to satisfy"
3249 		    " the given bandwidth");
3250 
3251 		return (USB_FAILURE);
3252 	}
3253 	USB_DPRINTF_L3(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3254 	    "usbvc_set_alt: strm_if->curr_alt=%d", strm_if->curr_alt);
3255 	if_num = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3256 	mutex_exit(&usbvcp->usbvc_mutex);
3257 	if ((rval = usb_set_alt_if(usbvcp->usbvc_dip, if_num, strm_if->curr_alt,
3258 		USB_FLAGS_SLEEP, NULL, NULL)) != USB_SUCCESS) {
3259 		mutex_enter(&usbvcp->usbvc_mutex);
3260 		USB_DPRINTF_L2(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3261 		    "usbvc_set_alt: usb_set_alt_if fail, if.alt=%d.%d, rval=%d",
3262 		    if_num, strm_if->curr_alt, rval);
3263 
3264 		return (rval);
3265 	}
3266 	mutex_enter(&usbvcp->usbvc_mutex);
3267 
3268 	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbvcp->usbvc_log_handle,
3269 	    "usbvc_set_alt: return, if_num=%d, alt=%d",
3270 	    if_num, strm_if->curr_alt);
3271 
3272 	return (rval);
3273 }
3274 
3275 
3276 /*
3277  * Decode stream header for mjpeg and uncompressed format video data.
3278  * mjpeg and uncompressed format have the same stream header. See their
3279  * payload spec, 2.2 and 2.4
3280  */
3281 static int
3282 usbvc_decode_stream_header(usbvc_state_t *usbvcp, usbvc_buf_grp_t *bufgrp,
3283 	mblk_t *data, int actual_len)
3284 {
3285 	uint32_t len, buf_left, data_len;
3286 	usbvc_stream_if_t *strm_if;
3287 	uchar_t head_flag, head_len;
3288 	usbvc_buf_t *buf_filling;
3289 
3290 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3291 	USB_DPRINTF_L4(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3292 	    "usbvc_decode_stream_header: enter. actual_len=%x", actual_len);
3293 
3294 	/* header length check. */
3295 	if (actual_len < 2) {
3296 		USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3297 		    "usbvc_decode_stream_header: header is not completed");
3298 
3299 		return (USB_FAILURE);
3300 	}
3301 	head_len = data->b_rptr[0];
3302 	head_flag = data->b_rptr[1];
3303 
3304 	USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3305 	    "usbvc_decode_stream_header: headlen=%x", head_len);
3306 
3307 	/* header length check. */
3308 	if (actual_len < head_len) {
3309 		USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3310 		    "usbvc_decode_stream_header: actual_len < head_len");
3311 
3312 		return (USB_FAILURE);
3313 	}
3314 
3315 	/*
3316 	 * If there is no stream data in this packet and this packet is not
3317 	 * used to indicate the end of a frame, then just skip it.
3318 	 */
3319 	if ((actual_len == head_len) && !(head_flag & USBVC_STREAM_EOF)) {
3320 	    USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3321 		    "usbvc_decode_stream_header: only header, no data");
3322 
3323 		return (USB_FAILURE);
3324 	}
3325 
3326 	/* Get the first stream interface */
3327 	strm_if = usbvcp->usbvc_curr_strm;
3328 
3329 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxVideoFrameSize, 0, len);
3330 	USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3331 	    "usbvc_decode_stream_header: dwMaxVideoFrameSize=%x, head_flag=%x",
3332 	    len, head_flag);
3333 
3334 	/*
3335 	 * if no buf is filling, pick one buf from free list and alloc data
3336 	 * mem for the buf.
3337 	 */
3338 	if (!bufgrp->buf_filling) {
3339 		if (list_is_empty(&bufgrp->uv_buf_free)) {
3340 			strm_if->fid = head_flag & USBVC_STREAM_FID;
3341 			USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3342 			    "usbvc_decode_stream_header: free list are empty");
3343 
3344 			return (USB_FAILURE);
3345 
3346 		} else {
3347 			bufgrp->buf_filling =
3348 			    (usbvc_buf_t *)list_head(&bufgrp->uv_buf_free);
3349 
3350 			/* unlink from buf free list */
3351 			list_remove(&bufgrp->uv_buf_free, bufgrp->buf_filling);
3352 		}
3353 		bufgrp->buf_filling->filled = 0;
3354 		USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3355 		    "usbvc_decode_stream_header: status=%d",
3356 		    bufgrp->buf_filling->status);
3357 		bufgrp->buf_filling->status = USBVC_BUF_EMPTY;
3358 	}
3359 	buf_filling = bufgrp->buf_filling;
3360 	ASSERT(buf_filling->len >= buf_filling->filled);
3361 	buf_left = buf_filling->len - buf_filling->filled;
3362 
3363 	/* if no buf room left, then return with a err status */
3364 	if (buf_left == 0) {
3365 		buf_filling->status = USBVC_BUF_ERR;
3366 
3367 		return (USB_FAILURE);
3368 	}
3369 
3370 	/* get this sample's data length except header */
3371 	data_len = actual_len - head_len;
3372 	USB_DPRINTF_L3(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3373 	    "usbvc_decode_stream_header: fid=%x, len=%x, filled=%x",
3374 	    strm_if->fid, buf_filling->len, buf_filling->filled);
3375 
3376 	/* if the first sample for a frame */
3377 	if (buf_filling->filled == 0) {
3378 		/*
3379 		 * Only if it is the frist packet of a frame,
3380 		 * we will begin filling a frame.
3381 		 */
3382 		if (strm_if->fid != 0xff && strm_if->fid ==
3383 		    (head_flag & USBVC_STREAM_FID)) {
3384 			USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3385 			    "usbvc_decode_stream_header: 1st sample of a frame,"
3386 			    " fid is incorrect.");
3387 
3388 			return (USB_FAILURE);
3389 		}
3390 		strm_if->fid = head_flag & USBVC_STREAM_FID;
3391 
3392 	/* If in the middle of a frame, fid should be consistent. */
3393 	} else if (strm_if->fid != (head_flag & USBVC_STREAM_FID)) {
3394 		USB_DPRINTF_L2(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3395 		    "usbvc_decode_stream_header: fid is incorrect.");
3396 		strm_if->fid = head_flag & USBVC_STREAM_FID;
3397 		buf_filling->status = USBVC_BUF_ERR;
3398 
3399 		return (USB_FAILURE);
3400 	}
3401 	if (data_len) {
3402 		bcopy((void *)(data->b_rptr + head_len),
3403 		    (void *)(buf_filling->data + buf_filling->filled),
3404 		    min(data_len, buf_left));
3405 
3406 		buf_filling->filled += min(data_len, buf_left);
3407 	}
3408 
3409 	/* If the last packet for this frame */
3410 	if (head_flag & USBVC_STREAM_EOF) {
3411 		buf_filling->status = USBVC_BUF_DONE;
3412 	}
3413 	if (data_len > buf_left) {
3414 		buf_filling->status = USBVC_BUF_ERR;
3415 	}
3416 	USB_DPRINTF_L4(PRINT_MASK_CB, usbvcp->usbvc_log_handle,
3417 	    "usbvc_decode_stream_header: buf_status=%d", buf_filling->status);
3418 
3419 	return (USB_SUCCESS);
3420 }
3421 
3422 
3423 /*
3424  * usbvc_serialize_access:
3425  *    Get the serial synchronization object before returning.
3426  *
3427  * Arguments:
3428  *    usbvcp - Pointer to usbvc state structure
3429  *    waitsig - Set to:
3430  *	USBVC_SER_SIG - to wait such that a signal can interrupt
3431  *	USBVC_SER_NOSIG - to wait such that a signal cannot interrupt
3432  */
3433 static int
3434 usbvc_serialize_access(usbvc_state_t *usbvcp, boolean_t waitsig)
3435 {
3436 	int rval = 1;
3437 
3438 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3439 
3440 	while (usbvcp->usbvc_serial_inuse) {
3441 		if (waitsig == USBVC_SER_SIG) {
3442 			rval = cv_wait_sig(&usbvcp->usbvc_serial_cv,
3443 			    &usbvcp->usbvc_mutex);
3444 		} else {
3445 			cv_wait(&usbvcp->usbvc_serial_cv,
3446 			    &usbvcp->usbvc_mutex);
3447 		}
3448 	}
3449 	usbvcp->usbvc_serial_inuse = B_TRUE;
3450 
3451 	return (rval);
3452 }
3453 
3454 
3455 /*
3456  * usbvc_release_access:
3457  *    Release the serial synchronization object.
3458  */
3459 static void
3460 usbvc_release_access(usbvc_state_t *usbvcp)
3461 {
3462 	ASSERT(mutex_owned(&usbvcp->usbvc_mutex));
3463 	usbvcp->usbvc_serial_inuse = B_FALSE;
3464 	cv_broadcast(&usbvcp->usbvc_serial_cv);
3465 }
3466 
3467 
3468 /* Send req to video control interface to get ctrl */
3469 int
3470 usbvc_vc_get_ctrl(usbvc_state_t *usbvcp, uint8_t req_code, uint8_t entity_id,
3471     uint16_t cs, uint16_t wlength, mblk_t *data)
3472 {
3473 	usb_cb_flags_t	cb_flags;
3474 	usb_cr_t	cr;
3475 	usb_ctrl_setup_t setup;
3476 
3477 	setup.bmRequestType = USBVC_GET_IF;	/* bmRequestType */
3478 	setup.bRequest = req_code;		/* bRequest */
3479 	setup.wValue = cs<<8;
3480 	setup.wIndex = entity_id<<8;
3481 	setup.wLength = wlength;
3482 	setup.attrs = 0;
3483 
3484 	if (usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup, &data,
3485 	    &cr, &cb_flags, 0) != USB_SUCCESS) {
3486 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3487 		    "usbvc_vc_get_ctrl: cmd failed, cr=%d, cb_flags=%x",
3488 		    cr, cb_flags);
3489 
3490 		return (USB_FAILURE);
3491 	}
3492 
3493 	return (USB_SUCCESS);
3494 }
3495 
3496 
3497 /* Send req to video control interface to get ctrl */
3498 int
3499 usbvc_vc_set_ctrl(usbvc_state_t *usbvcp, uint8_t req_code,  uint8_t entity_id,
3500 	uint16_t cs, uint16_t wlength, mblk_t *data)
3501 {
3502 	usb_cb_flags_t	cb_flags;
3503 	usb_cr_t	cr;
3504 	usb_ctrl_setup_t setup;
3505 
3506 	setup.bmRequestType = USBVC_SET_IF;	/* bmRequestType */
3507 	setup.bRequest = req_code;		/* bRequest */
3508 	setup.wValue = cs<<8;
3509 	setup.wIndex = entity_id<<8;
3510 	setup.wLength = wlength;
3511 	setup.attrs = 0;
3512 
3513 	if (usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup, &data,
3514 	    &cr, &cb_flags, 0) != USB_SUCCESS) {
3515 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3516 		    "usbvc_vc_set_ctrl: cmd failed, cr=%d, cb_flags=%x",
3517 		    cr, cb_flags);
3518 
3519 		return (USB_FAILURE);
3520 	}
3521 
3522 	return (USB_SUCCESS);
3523 }
3524 
3525 
3526 /* Set probe or commit ctrl for video stream interface */
3527 int
3528 usbvc_vs_set_probe_commit(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
3529 	usbvc_vs_probe_commit_t *ctrl_pc, uchar_t cs)
3530 {
3531 	mblk_t *data;
3532 	usb_cb_flags_t	cb_flags;
3533 	usb_cr_t	cr;
3534 	usb_ctrl_setup_t setup;
3535 	int rval;
3536 
3537 	setup.bmRequestType = USBVC_SET_IF;	/* bmRequestType */
3538 	setup.bRequest = SET_CUR;		/* bRequest */
3539 
3540 	/* wValue, VS_PROBE_CONTROL or VS_COMMIT_CONTROL */
3541 	setup.wValue = cs;
3542 
3543 	/* UVC Spec: this value must be put to the high byte */
3544 	setup.wValue = setup.wValue << 8;
3545 
3546 	setup.wIndex = strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3547 	setup.wLength = usbvcp->usbvc_vc_header->descr->bcdUVC[0] ? 34 : 26;
3548 	setup.attrs = 0;
3549 
3550 	USB_DPRINTF_L3(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3551 	    "usbvc_vs_set_probe_commit: wLength=%d", setup.wLength);
3552 
3553 	/* Data block */
3554 	if ((data = allocb(setup.wLength, BPRI_HI)) == NULL) {
3555 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3556 		    "usbvc_vs_set_probe_commit: allocb failed");
3557 
3558 		return (USB_FAILURE);
3559 	}
3560 
3561 	bcopy(ctrl_pc, data->b_rptr, setup.wLength);
3562 	data->b_wptr += setup.wLength;
3563 
3564 	if ((rval = usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup,
3565 	    &data, &cr, &cb_flags, 0)) != USB_SUCCESS) {
3566 		if (data) {
3567 			freemsg(data);
3568 		}
3569 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3570 		    "usbvc_vs_set_probe_commit: fail, rval=%d, cr=%d, "
3571 		    "cb_flags=%x", rval, cr, cb_flags);
3572 
3573 		return (rval);
3574 	}
3575 	if (data) {
3576 		freemsg(data);
3577 	}
3578 
3579 	return (USB_SUCCESS);
3580 }
3581 
3582 
3583 /* Get probe ctrl for vodeo stream interface */
3584 int
3585 usbvc_vs_get_probe(usbvc_state_t *usbvcp, usbvc_stream_if_t *strm_if,
3586 	usbvc_vs_probe_commit_t *ctrl_pc, uchar_t bRequest)
3587 {
3588 	mblk_t *data = NULL;
3589 	usb_cb_flags_t	cb_flags;
3590 	usb_cr_t	cr;
3591 	usb_ctrl_setup_t setup;
3592 
3593 	setup.bmRequestType = USBVC_GET_IF;	/* bmRequestType */
3594 	setup.bRequest = bRequest;		/* bRequest */
3595 	setup.wValue = VS_PROBE_CONTROL;	/* wValue, PROBE or COMMIT */
3596 	setup.wValue = setup.wValue << 8;
3597 	setup.wIndex =
3598 	    (uint16_t)strm_if->if_descr->if_alt->altif_descr.bInterfaceNumber;
3599 	setup.wLength = usbvcp->usbvc_vc_header->descr->bcdUVC[0] ? 34 : 26;
3600 
3601 	setup.attrs = 0;
3602 
3603 	if (usb_pipe_ctrl_xfer_wait(usbvcp->usbvc_default_ph, &setup, &data,
3604 	    &cr, &cb_flags, 0) != USB_SUCCESS) {
3605 		if (data) {
3606 			freemsg(data);
3607 		}
3608 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3609 		    "usbvc_vs_get_probe: cmd failed, cr=%d, cb_flags=%x",
3610 		    cr, cb_flags);
3611 
3612 		return (USB_FAILURE);
3613 	}
3614 	bcopy(data->b_rptr, ctrl_pc, setup.wLength);
3615 	if (data) {
3616 		freemsg(data);
3617 	}
3618 
3619 	return (USB_SUCCESS);
3620 }
3621 
3622 
3623 /* Set a default format when open the device */
3624 static int
3625 usbvc_set_default_stream_fmt(usbvc_state_t *usbvcp)
3626 {
3627 	usbvc_vs_probe_commit_t ctrl, ctrl_get;
3628 	usbvc_stream_if_t *strm_if;
3629 	usbvc_format_group_t *curr_fmtgrp;
3630 	uint32_t bandwidth;
3631 	uint8_t  index, i;
3632 
3633 	USB_DPRINTF_L4(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3634 	    "usbvc_set_default_stream_fmt: enter");
3635 
3636 	mutex_enter(&usbvcp->usbvc_mutex);
3637 	if (list_is_empty(&usbvcp->usbvc_stream_list)) {
3638 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3639 		    "usbvc_set_default_stream_fmt: no stream interface, fail");
3640 		mutex_exit(&usbvcp->usbvc_mutex);
3641 
3642 		return (USB_FAILURE);
3643 	}
3644 	bzero((void *)&ctrl, sizeof (usbvc_vs_probe_commit_t));
3645 
3646 	/* Get the current stream interface */
3647 	strm_if = usbvcp->usbvc_curr_strm;
3648 
3649 	/* Fill the probe commit req data */
3650 	ctrl.bmHint[0] = 0;
3651 
3652 	for (i = 0; i < strm_if->fmtgrp_cnt; i++) {
3653 		curr_fmtgrp = &strm_if->format_group[i];
3654 
3655 		/*
3656 		 * If v4l2_pixelformat is NULL, then that means there is not
3657 		 * a parsed format in format_group[i].
3658 		 */
3659 		if (!curr_fmtgrp || !curr_fmtgrp->v4l2_pixelformat ||
3660 		    curr_fmtgrp->frame_cnt == 0) {
3661 			USB_DPRINTF_L2(PRINT_MASK_DEVCTRL,
3662 			    usbvcp->usbvc_log_handle,
3663 			    "usbvc_set_default_stream_fmt: no frame, fail");
3664 
3665 			continue;
3666 		} else {
3667 
3668 			break;
3669 		}
3670 	}
3671 	if (!curr_fmtgrp || curr_fmtgrp->frame_cnt == 0) {
3672 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3673 		    "usbvc_set_default_stream_fmt: can't find a fmtgrp"
3674 		    "which has a frame, fail");
3675 		mutex_exit(&usbvcp->usbvc_mutex);
3676 
3677 		return (USB_FAILURE);
3678 	}
3679 
3680 	ctrl.bFormatIndex = curr_fmtgrp->format->bFormatIndex;
3681 
3682 	/* use the first frame descr as default */
3683 	ctrl.bFrameIndex = curr_fmtgrp->frames[0].descr->bFrameIndex;
3684 
3685 	/* use bcopy to keep the byte sequence as 32 bit little endian */
3686 	bcopy(&(curr_fmtgrp->frames[0].descr->dwDefaultFrameInterval[0]),
3687 	    &(ctrl.dwFrameInterval[0]), 4);
3688 
3689 	mutex_exit(&usbvcp->usbvc_mutex);
3690 	if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl, VS_PROBE_CONTROL)
3691 	    != USB_SUCCESS) {
3692 
3693 		return (USB_FAILURE);
3694 	}
3695 	if (usbvc_vs_get_probe(usbvcp, strm_if, &ctrl_get, GET_CUR)
3696 	    != USB_SUCCESS) {
3697 
3698 		return (USB_FAILURE);
3699 	}
3700 
3701 	mutex_enter(&usbvcp->usbvc_mutex);
3702 	LE_TO_UINT32(strm_if->ctrl_pc.dwMaxPayloadTransferSize, 0, bandwidth);
3703 	USB_DPRINTF_L3(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3704 	    "usbvc_set_default_stream_fmt: get bandwidth=%x", bandwidth);
3705 
3706 	mutex_exit(&usbvcp->usbvc_mutex);
3707 	if (usbvc_vs_set_probe_commit(usbvcp, strm_if, &ctrl_get,
3708 	    VS_COMMIT_CONTROL) != USB_SUCCESS) {
3709 
3710 		return (USB_FAILURE);
3711 	}
3712 
3713 	mutex_enter(&usbvcp->usbvc_mutex);
3714 
3715 	/*  it's good to check index here before use it */
3716 	index = ctrl_get.bFormatIndex - curr_fmtgrp->format->bFormatIndex;
3717 	if (index < strm_if->fmtgrp_cnt) {
3718 		strm_if->cur_format_group = &strm_if->format_group[index];
3719 	} else {
3720 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3721 		    "usbvc_set_default_stream_fmt: format index out of range");
3722 		mutex_exit(&usbvcp->usbvc_mutex);
3723 
3724 		return (USB_FAILURE);
3725 	}
3726 
3727 	index = ctrl_get.bFrameIndex -
3728 	    strm_if->cur_format_group->frames[0].descr->bFrameIndex;
3729 	if (index < strm_if->cur_format_group->frame_cnt) {
3730 		strm_if->cur_format_group->cur_frame =
3731 		    &strm_if->cur_format_group->frames[index];
3732 	} else {
3733 		USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, usbvcp->usbvc_log_handle,
3734 		    "usbvc_set_default_stream: frame index out of range");
3735 		mutex_exit(&usbvcp->usbvc_mutex);
3736 
3737 		return (USB_FAILURE);
3738 	}
3739 
3740 	/*
3741 	 * by now, the video format is set successfully. record the current
3742 	 * setting to strm_if->ctrl_pc
3743 	 */
3744 	bcopy(&ctrl_get, &strm_if->ctrl_pc, sizeof (usbvc_vs_probe_commit_t));
3745 
3746 	mutex_exit(&usbvcp->usbvc_mutex);
3747 
3748 	return (USB_SUCCESS);
3749 }
3750