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