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