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