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