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