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