1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * AUDIO CONTROL Driver: usb_ac is a streams multiplexor that sits
29  * on top of usb_as and hid and is responsible for
30  * (1) providing the entry points to audio mixer framework, (2) passing
31  * streams messages to and from usb_as and hid and (3) processing
32  * control messages that it can handle.
33  *
34  * 1. Mixer entry points are: usb_ac_setup(), usb_ac_teardown(),
35  *	usb_ac_set_config(), usb_ac_set_format(), usb_ac_start_play(),
36  *	usb_ac_pause_play(), usb_ac_stop_play, usb_ac_start_record(),
37  *	usb_ac_stop_record().
38  * 2. usb_ac is a streams driver that passes streams messages down to
39  *	usb_as that selects the correct alternate with passed format
40  *	parameters, sets sample frequency, starts play/record, stops
41  *	play/record, pause play/record, open/close isoc pipe.
42  * 3. usb_ac handles the set_config command through the default pipe
43  *	of sound control interface of the audio device in a synchronous
44  *	manner.
45  *
46  * Serialization: usb_ac being a streams driver and having the requirement
47  * of making non-blockings calls (USBA or streams or mixer) needs to drop
48  * mutexes over such calls. But at the same time, a competing thread
49  * can't be allowed to interfere with (1) pipe, (2) streams state.
50  * So we need some kind of serialization among the asynchronous
51  * threads that can run in the driver. The serialization is mostly
52  * needed to avoid races among open/close/events/power entry points
53  * etc. Once a routine takes control, it checks if the resource (pipe or
54  * stream or dev state) is still accessible. If so, it proceeds with
55  * its job and until it completes, no other thread requiring the same
56  * resource can run.
57  *
58  * PM model in usb_ac: Raise power during attach. If a device is not at full
59  * power, raise power in the entry points. After the command is over,
60  * pm_idle_component() is called. The power is lowered in detach().
61  *
62  * locking: Warlock is not aware of the automatic locking mechanisms for
63  * streams drivers.
64  */
65 #include <sys/usb/usba/usbai_version.h>
66 #include <sys/usb/usba.h>
67 #include <sys/stropts.h>
68 #include <sys/sunndi.h>
69 #include <sys/ndi_impldefs.h>
70 #include <sys/strsubr.h>
71 
72 #include <sys/audio.h>
73 #include <sys/audiovar.h>
74 #include <sys/audio/audio_support.h>
75 #include <sys/audio/audio_src.h>
76 #include <sys/mixer.h>
77 #include <sys/audio/audio_mixer.h>
78 
79 #include <sys/usb/clients/audio/usb_audio.h>
80 #include <sys/usb/clients/audio/usb_mixer.h>
81 #include <sys/usb/clients/audio/usb_ac/usb_ac.h>
82 
83 /* debug support */
84 uint_t	usb_ac_errlevel 	= USB_LOG_L4;
85 uint_t	usb_ac_errmask		= (uint_t)-1;
86 uint_t	usb_ac_instance_debug	= (uint_t)-1;
87 
88 #ifdef DEBUG
89 /*
90  * tunable timeout for usb_as response, allow at least 10 secs for control
91  * cmd to timeout
92  */
93 int	usb_ac_wait_timeout = 10000000;
94 #endif
95 
96 /*
97  * table for converting term types of input and output terminals
98  * to SADA port types (pretty rough mapping)
99  */
100 static struct {
101 	ushort_t	term_type;
102 	ushort_t	port_type;
103 } usb_ac_term_type_map[] = {
104 { USB_AUDIO_TERM_TYPE_STREAMING,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
105 { USB_AUDIO_TERM_TYPE_MICROPHONE,		AUDIO_MICROPHONE },
106 { USB_AUDIO_TERM_TYPE_DT_MICROPHONE,		AUDIO_MICROPHONE },
107 { USB_AUDIO_TERM_TYPE_PERS_MICROPHONE,		AUDIO_MICROPHONE },
108 { USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE,	AUDIO_MICROPHONE },
109 { USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY,		AUDIO_MICROPHONE },
110 { USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY,	AUDIO_MICROPHONE },
111 { USB_AUDIO_TERM_TYPE_SPEAKER,			AUDIO_SPEAKER },
112 { USB_AUDIO_TERM_TYPE_HEADPHONES,		AUDIO_HEADPHONE },
113 { USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO,		AUDIO_LINE_OUT },
114 { USB_AUDIO_TERM_TYPE_DT_SPEAKER,		AUDIO_SPEAKER },
115 { USB_AUDIO_TERM_TYPE_ROOM_SPEAKER,		AUDIO_SPEAKER },
116 { USB_AUDIO_TERM_TYPE_COMM_SPEAKER,		AUDIO_SPEAKER },
117 { USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER,	AUDIO_SPEAKER },
118 { USB_AUDIO_TERM_TYPE_HANDSET,		AUDIO_LINE_IN|AUDIO_LINE_OUT },
119 { USB_AUDIO_TERM_TYPE_HEADSET,		AUDIO_LINE_IN|AUDIO_LINE_OUT },
120 { USB_AUDIO_TERM_TYPE_SPEAKERPHONE,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
121 { USB_AUDIO_TERM_TYPE_ECHO_SUPP_SPEAKERPHONE,
122 					AUDIO_LINE_IN|AUDIO_LINE_OUT },
123 { USB_AUDIO_TERM_TYPE_ECHO_CANCEL_SPEAKERPHONE,
124 					AUDIO_LINE_IN|AUDIO_LINE_OUT },
125 { USB_AUDIO_TERM_TYPE_PHONE_LINE,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
126 { USB_AUDIO_TERM_TYPE_TELEPHONE,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
127 { USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
128 { USB_AUDIO_TERM_TYPE_ANALOG_CONNECTOR,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
129 { USB_AUDIO_TERM_TYPE_DIGITAL_AUDIO_IF,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
130 { USB_AUDIO_TERM_TYPE_LINE_CONNECTOR,	AUDIO_LINE_IN|AUDIO_LINE_OUT },
131 { USB_AUDIO_TERM_TYPE_LEGACY_AUDIO_CONNECTOR,
132 					AUDIO_LINE_IN|AUDIO_LINE_OUT },
133 { USB_AUDIO_TERM_TYPE_SPDIF_IF,		AUDIO_SPDIF_IN },
134 { USB_AUDIO_TERM_TYPE_1394_DA_STREAM,
135 					AUDIO_LINE_IN|AUDIO_LINE_OUT },
136 { USB_AUDIO_TERM_TYPE_1394_DV_STREAM_SNDTRCK,
137 					AUDIO_LINE_IN|AUDIO_LINE_OUT },
138 { 0, 0 }
139 };
140 
141 
142 /*
143  * Module linkage routines for the kernel
144  */
145 static int	usb_ac_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
146 static int	usb_ac_attach(dev_info_t *, ddi_attach_cmd_t);
147 static int	usb_ac_detach(dev_info_t *, ddi_detach_cmd_t);
148 static int	usb_ac_power(dev_info_t *, int, int);
149 
150 /*
151  * STREAMS module entry points
152  */
153 static int	usb_ac_open(queue_t *, dev_t *, int, int, cred_t *);
154 static int	usb_ac_close(queue_t *, int, cred_t *);
155 static int	usb_ac_uwput(queue_t *, mblk_t *);
156 static int	usb_ac_lrput(queue_t *, mblk_t *);
157 
158 /* plumbing */
159 static usb_ac_plumbed_t *usb_ac_get_plumb_info(usb_ac_state_t *, char *,
160 				uchar_t);
161 static usb_ac_plumbed_t *usb_ac_get_plumb_info_from_lrq(usb_ac_state_t *,
162 				queue_t *);
163 static uint_t	usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
164 				uint_t);
165 static void	usb_ac_plumb_ioctl(queue_t *, mblk_t *);
166 
167 
168 /* registration */
169 static int	usb_ac_get_curr_n_channels(usb_ac_state_t *, int);
170 static usb_audio_formats_t *usb_ac_get_curr_format(usb_ac_state_t *, int);
171 
172 /* descriptor handling */
173 static int	usb_ac_handle_descriptors(usb_ac_state_t *);
174 static void	usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t);
175 static void	usb_ac_alloc_unit(usb_ac_state_t *, uint_t);
176 static void	usb_ac_free_all_units(usb_ac_state_t *);
177 static void	usb_ac_setup_connections(usb_ac_state_t *);
178 static void	usb_ac_map_termtype_to_port(usb_ac_state_t *, uint_t);
179 
180 /* power management */
181 static int	usb_ac_pwrlvl0(usb_ac_state_t *);
182 static int	usb_ac_pwrlvl1(usb_ac_state_t *);
183 static int	usb_ac_pwrlvl2(usb_ac_state_t *);
184 static int	usb_ac_pwrlvl3(usb_ac_state_t *);
185 static void	usb_ac_create_pm_components(dev_info_t *, usb_ac_state_t *);
186 static void	usb_ac_pm_busy_component(usb_ac_state_t *);
187 static void	usb_ac_pm_idle_component(usb_ac_state_t *);
188 
189 /* event handling */
190 static int	usb_ac_disconnect_event_cb(dev_info_t *);
191 static int	usb_ac_reconnect_event_cb(dev_info_t *);
192 static int	usb_ac_cpr_suspend(dev_info_t *);
193 static void	usb_ac_cpr_resume(dev_info_t *);
194 
195 static usb_event_t usb_ac_events = {
196 	usb_ac_disconnect_event_cb,
197 	usb_ac_reconnect_event_cb,
198 	NULL, NULL
199 };
200 
201 /* misc. support */
202 static void	usb_ac_restore_device_state(dev_info_t *, usb_ac_state_t *);
203 static int	usb_ac_cleanup(dev_info_t *, usb_ac_state_t *);
204 static void	usb_ac_serialize_access(usb_ac_state_t *);
205 static void	usb_ac_release_access(usb_ac_state_t *);
206 
207 static void	usb_ac_push_unit_id(usb_ac_state_t *, uint_t);
208 static void	usb_ac_pop_unit_id(usb_ac_state_t *, uint_t);
209 static void	usb_ac_show_traverse_path(usb_ac_state_t *);
210 static int	usb_ac_check_path(usb_ac_state_t *, uint_t);
211 
212 static uint_t	usb_ac_traverse_connections(usb_ac_state_t *, uint_t, uint_t,
213 				uint_t, uint_t, uint_t, uint_t,
214 				uint_t *, uint_t, uint_t *,
215 				int (*func)(usb_ac_state_t *, uint_t, uint_t,
216 				uint_t, uint_t, uint_t, uint_t *));
217 static uint_t	usb_ac_set_port(usb_ac_state_t *, uint_t, uint_t);
218 static uint_t	usb_ac_set_control(usb_ac_state_t *, uint_t, uint_t,
219 				uint_t, uint_t, uint_t,
220 				uint_t *, uint_t,
221 				int (*func)(usb_ac_state_t *, uint_t, uint_t,
222 				uint_t, uint_t, uint_t, uint_t *));
223 static uint_t	usb_ac_set_monitor_gain_control(usb_ac_state_t *, uint_t,
224 				uint_t, uint_t, uint_t, uint_t,
225 				uint_t *, uint_t,
226 				int (*func)(usb_ac_state_t *, uint_t, uint_t,
227 				uint_t, uint_t, uint_t, uint_t *));
228 static uint_t	usb_ac_traverse_all_units(usb_ac_state_t *, uint_t, uint_t,
229 				uint_t, uint_t, uint_t, uint_t *,
230 				uint_t, uint_t *,
231 				int (*func)(usb_ac_state_t *, uint_t, uint_t,
232 				uint_t, uint_t, uint_t, uint_t *));
233 static int	usb_ac_update_port(usb_ac_state_t *, uint_t,
234 				uint_t, uint_t, uint_t, uint_t, uint_t *);
235 static int	usb_ac_set_selector(usb_ac_state_t *, uint_t,
236 				uint_t, uint_t, uint_t, uint_t, uint_t *);
237 static int	usb_ac_feature_unit_check(usb_ac_state_t *, uint_t,
238 				uint_t, uint_t, uint_t, uint_t, uint_t *);
239 static int	usb_ac_set_gain(usb_ac_state_t *, uint_t,
240 				uint_t, uint_t, uint_t, uint_t, uint_t *);
241 static int	usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t,
242 				uint_t, uint_t, uint_t, uint_t, uint_t *);
243 static int	usb_ac_set_mute(usb_ac_state_t *, uint_t, uint_t,
244 				uint_t, uint_t, uint_t, uint_t *);
245 static int	usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir,
246 				int);
247 static int	usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int,
248 				int);
249 static void	usb_ac_free_mblk(mblk_t *);
250 static mblk_t	*usb_ac_allocate_req_mblk(usb_ac_state_t *, int,
251 				void *, uint_t);
252 static int	usb_ac_send_as_cmd(usb_ac_state_t *, usb_ac_plumbed_t *,
253 				int, void *);
254 static int	usb_ac_send_format_cmd(audiohdl_t, int, int, int,
255 				int, int, int);
256 static int	usb_ac_do_setup(audiohdl_t, int, int);
257 static void	usb_ac_do_teardown(audiohdl_t, int, int);
258 static void	usb_ac_do_pause_play(audiohdl_t, int);
259 static void	usb_ac_do_stop_record(audiohdl_t, int);
260 
261 /*  Mixer entry points */
262 static int	usb_ac_setup(audiohdl_t, int, int);
263 static void	usb_ac_teardown(audiohdl_t, int, int);
264 static int	usb_ac_set_config(audiohdl_t, int, int, int, int, int);
265 static int	usb_ac_set_format(audiohdl_t, int, int, int, int, int, int);
266 static int	usb_ac_start_play(audiohdl_t, int);
267 static void	usb_ac_pause_play(audiohdl_t, int);
268 static void	usb_ac_stop_play(audiohdl_t, int);
269 static int	usb_ac_start_record(audiohdl_t, int);
270 static void	usb_ac_stop_record(audiohdl_t, int);
271 static int	usb_ac_restore_audio_state(usb_ac_state_t *, int);
272 
273 /*
274  * External functions
275  */
276 extern int	space_store(char *key, uintptr_t ptr);
277 extern void	space_free(char *);
278 
279 
280 /*
281  * mixer registration data
282  */
283 static am_ad_entry_t usb_ac_entry = {
284 	usb_ac_setup,		/* ad_setup() */
285 	usb_ac_teardown,	/* ad_teardown() */
286 	usb_ac_set_config,	/* ad_set_config() */
287 	usb_ac_set_format,	/* ad_set_format() */
288 	usb_ac_start_play,	/* ad_start_play() */
289 	usb_ac_pause_play,	/* ad_pause_play() */
290 	usb_ac_stop_play,	/* ad_stop_play() */
291 	usb_ac_start_record,	/* ad_start_record() */
292 	usb_ac_stop_record,	/* ad_stop_record() */
293 	NULL,			/* ad_ioctl() */
294 	NULL			/* ad_iocdata() */
295 };
296 
297 /* anchor for soft state structures */
298 static void	*usb_ac_statep;
299 
300 /* for passing soft state etc. to usb_ac_dacf module */
301 static usb_ac_state_space_t ssp;
302 
303 /* STREAMS driver id and limit value structure */
304 static struct module_info usb_ac_modinfo = {
305 	0xffff,				/* module ID number */
306 	"usb_ac",			/* module name */
307 	USB_AUDIO_MIN_PKTSZ,		/* minimum packet size */
308 	USB_AUDIO_MAX_PKTSZ,		/* maximum packet size */
309 	USB_AC_HIWATER,			/* high water mark */
310 	USB_AC_LOWATER			/* low water mark */
311 };
312 
313 /* STREAMS queue processing procedures structures */
314 /* upper read queue */
315 static struct qinit usb_ac_urqueue = {
316 	NULL,			/* put procedure */
317 	NULL,			/* service procedure */
318 	usb_ac_open,		/* open procedure */
319 	usb_ac_close,		/* close procedure */
320 	NULL,			/* unused */
321 	&usb_ac_modinfo,	/* module parameters */
322 	NULL			/* module statistics */
323 };
324 
325 /* upper write queue */
326 static struct qinit usb_ac_uwqueue = {
327 	usb_ac_uwput,		/* put procedure */
328 	audio_sup_wsvc,		/* service procedure */
329 	NULL,			/* open procedure */
330 	NULL,			/* close procedure */
331 	NULL,			/* unused */
332 	&usb_ac_modinfo,	/* module parameters */
333 	NULL			/* module statistics */
334 };
335 
336 /* lower read queue */
337 static struct qinit usb_ac_lrqueue = {
338 	usb_ac_lrput,
339 	NULL,
340 	NULL,
341 	NULL,
342 	NULL,
343 	&usb_ac_modinfo,	/* module parameters */
344 	NULL
345 };
346 
347 /* lower write queue */
348 static struct qinit usb_ac_lwqueue = {
349 	NULL,
350 	NULL,
351 	NULL,
352 	NULL,
353 	NULL,
354 	&usb_ac_modinfo,	/* module parameters */
355 	NULL
356 };
357 
358 /* STREAMS entity declaration structure */
359 static struct streamtab usb_ac_str_info = {
360 	&usb_ac_urqueue,		/* upper read queue */
361 	&usb_ac_uwqueue,		/* upper write queue */
362 	&usb_ac_lrqueue,		/* lower read queue */
363 	&usb_ac_lwqueue,		/* lower write queue */
364 };
365 
366 /*
367  * DDI Structures
368  *
369  * Entry points structure
370  */
371 static struct cb_ops usb_ac_cb_ops = {
372 	nulldev,		/* cb_open */
373 	nulldev,		/* cb_close */
374 	nodev,			/* cb_strategy */
375 	nodev,			/* cb_print */
376 	nodev,			/* cb_dump */
377 	nodev,			/* cb_read */
378 	nodev,			/* cb_write */
379 	nodev,			/* cb_ioctl */
380 	nodev,			/* cb_devmap */
381 	nodev,			/* cb_mmap */
382 	nodev,			/* cb_segmap */
383 	nochpoll,		/* cb_chpoll */
384 	ddi_prop_op,		/* cb_prop_op */
385 	&usb_ac_str_info,	/* cb_str */
386 	D_MP | D_MTPERQ,	/* cb_flag */
387 	CB_REV,			/* cb_rev */
388 	nodev,			/* cb_aread */
389 	nodev,			/* cb_arwite */
390 };
391 
392 /* Device operations structure */
393 static struct dev_ops usb_ac_dev_ops = {
394 	DEVO_REV,		/* devo_rev */
395 	0,			/* devo_refcnt */
396 	usb_ac_getinfo,		/* devo_getinfo */
397 	nulldev,		/* devo_identify - obsolete */
398 	nulldev,		/* devo_probe - not needed */
399 	usb_ac_attach,		/* devo_attach */
400 	usb_ac_detach,		/* devo_detach */
401 	nodev,			/* devo_reset */
402 	&usb_ac_cb_ops,		/* devi_cb_ops */
403 	NULL,			/* devo_busb_ac_ops */
404 	usb_ac_power		/* devo_power */
405 };
406 
407 /* Linkage structure for loadable drivers */
408 static struct modldrv usb_ac_modldrv = {
409 	&mod_driverops,				/* drv_modops */
410 	"USB Audio Control Driver",		/* drv_linkinfo */
411 	&usb_ac_dev_ops				/* drv_dev_ops */
412 };
413 
414 /* Module linkage structure */
415 static struct modlinkage usb_ac_modlinkage = {
416 	MODREV_1,			/* ml_rev */
417 	(void *)&usb_ac_modldrv,	/* ml_linkage */
418 	NULL				/* NULL terminates the list */
419 };
420 
421 /* warlock directives */
422 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk))
423 _NOTE(SCHEME_PROTECTS_DATA("unique per call", datab))
424 _NOTE(SCHEME_PROTECTS_DATA("unique per call", msgb))
425 _NOTE(SCHEME_PROTECTS_DATA("unique per call", queue))
426 _NOTE(SCHEME_PROTECTS_DATA("stable data", usb_pipe_policy_t))
427 
428 /* standard entry points */
429 int
430 _init(void)
431 {
432 	int rval;
433 
434 	/* initialize the soft state */
435 	if ((rval = ddi_soft_state_init(&usb_ac_statep,
436 	    sizeof (usb_ac_state_t), 1)) != DDI_SUCCESS) {
437 		return (rval);
438 	}
439 
440 	if ((rval = mod_install(&usb_ac_modlinkage)) != 0) {
441 		ddi_soft_state_fini(&usb_ac_statep);
442 	}
443 
444 	if (!rval) {
445 		ssp.sp = usb_ac_statep;
446 		ssp.restore_func = usb_ac_restore_audio_state;
447 		ssp.get_featureID_func = usb_ac_get_featureID;
448 		ssp.ac_entryp = &usb_ac_entry;
449 		ssp.pm_busy_component = usb_ac_pm_busy_component;
450 		ssp.pm_idle_component = usb_ac_pm_idle_component;
451 
452 		rval = space_store("usb_ac", (uintptr_t)&ssp);
453 	}
454 
455 	return (rval);
456 }
457 
458 
459 int
460 _fini(void)
461 {
462 	int rval;
463 
464 	if ((rval = mod_remove(&usb_ac_modlinkage)) == 0) {
465 		/* Free the soft state internal structures */
466 		ddi_soft_state_fini(&usb_ac_statep);
467 		space_free("usb_ac");
468 	}
469 
470 	return (rval);
471 }
472 
473 
474 int
475 _info(struct modinfo *modinfop)
476 {
477 	return (mod_info(&usb_ac_modlinkage, modinfop));
478 }
479 
480 /*ARGSUSED*/
481 static int
482 usb_ac_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
483 			void *arg, void **result)
484 {
485 	usb_ac_state_t	   *uacp = NULL;
486 	int error = DDI_FAILURE;
487 	int instance;
488 
489 	switch (infocmd) {
490 	case DDI_INFO_DEVT2DEVINFO:
491 		instance = audio_sup_devt_to_instance((dev_t)arg);
492 		if ((uacp = ddi_get_soft_state(usb_ac_statep,
493 		    instance)) != NULL) {
494 			*result = uacp->usb_ac_dip;
495 			if (*result != NULL) {
496 				error = DDI_SUCCESS;
497 			}
498 		} else {
499 			*result = NULL;
500 		}
501 		break;
502 	case DDI_INFO_DEVT2INSTANCE:
503 		*result = (void *)(uintptr_t)
504 		    audio_sup_devt_to_instance((dev_t)arg);
505 		error = DDI_SUCCESS;
506 		break;
507 	default:
508 		break;
509 	}
510 
511 	return (error);
512 }
513 
514 extern	uint_t		nproc;
515 #define	INIT_PROCESS_CNT 3
516 
517 static int
518 usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
519 {
520 	usb_ac_state_t		*uacp = NULL;
521 	audio_sup_reg_data_t	reg_data;
522 	int			instance = ddi_get_instance(dip);
523 	int			minor;
524 	char			*key;
525 	size_t			key_len, len;
526 
527 	switch (cmd) {
528 		case DDI_ATTACH:
529 			break;
530 		case DDI_RESUME:
531 			usb_ac_cpr_resume(dip);
532 
533 			return (DDI_SUCCESS);
534 		default:
535 			return (DDI_FAILURE);
536 	}
537 
538 	/*
539 	 * wait  until all processes are started from main.
540 	 * USB enumerates early in boot (ie. consconfig time).
541 	 * If the plumbing takes place early, the file descriptors
542 	 * are owned by the init process and can never be closed anymore
543 	 * Consequently, hot removal is not possible and the dips
544 	 * never go away. By waiting some time, e.g. INIT_PROCESS_CNT,
545 	 * the problem is avoided.
546 	 */
547 	if (nproc < INIT_PROCESS_CNT) {
548 		USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL,
549 		    "usb_ac%d attach too early", instance);
550 
551 		return (DDI_FAILURE);
552 	}
553 
554 	/*
555 	 * Allocate soft state information.
556 	 */
557 	if (ddi_soft_state_zalloc(usb_ac_statep, instance) != DDI_SUCCESS) {
558 
559 		goto fail;
560 	}
561 
562 	/*
563 	 * get soft state space and initialize
564 	 */
565 	uacp = (usb_ac_state_t *)ddi_get_soft_state(usb_ac_statep, instance);
566 	if (uacp == NULL) {
567 
568 		goto fail;
569 	}
570 
571 
572 	/* get log handle */
573 	uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac",
574 	    &usb_ac_errlevel,
575 	    &usb_ac_errmask, &usb_ac_instance_debug,
576 	    0);
577 
578 	uacp->usb_ac_instance = instance;
579 	uacp->usb_ac_dip = dip;
580 
581 	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
582 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
583 		    "usb_client_attach failed");
584 
585 		usb_free_log_hdl(uacp->usb_ac_log_handle);
586 		ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
587 
588 		return (DDI_FAILURE);
589 	}
590 
591 	if (usb_get_dev_data(dip, &uacp->usb_ac_dev_data,
592 	    USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
593 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
594 		    "usb_get_dev_data failed");
595 
596 		usb_client_detach(dip, NULL);
597 		usb_free_log_hdl(uacp->usb_ac_log_handle);
598 		ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
599 
600 		return (DDI_FAILURE);
601 	}
602 
603 	/* initialize mutex & cv */
604 	mutex_init(&uacp->usb_ac_mutex, NULL, MUTEX_DRIVER,
605 	    uacp->usb_ac_dev_data->dev_iblock_cookie);
606 
607 	uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph;
608 
609 	/* register with audiosup */
610 	reg_data.asrd_version	= AUDIOSUP_VERSION;
611 
612 	/*
613 	 * we register with pathname, the mgf, product, and serial number
614 	 * strings, vid.pid, and driver name which should be pretty unique
615 	 */
616 	key_len = 2 * MAXNAMELEN;
617 	if (uacp->usb_ac_dev_data->dev_mfg) {
618 		key_len += strlen(uacp->usb_ac_dev_data->dev_mfg);
619 	}
620 	if (uacp->usb_ac_dev_data->dev_product) {
621 		key_len += strlen(uacp->usb_ac_dev_data->dev_product);
622 	}
623 	if (uacp->usb_ac_dev_data->dev_serial) {
624 		key_len += strlen(uacp->usb_ac_dev_data->dev_serial);
625 	}
626 
627 	key = kmem_alloc(key_len, KM_SLEEP);
628 	(void) ddi_pathname(dip, key);
629 
630 	len = strlen(key);
631 	(void) snprintf(&key[len], key_len - len, ",%s,%s,%s,%x.%x,%s",
632 	    (uacp->usb_ac_dev_data->dev_mfg ?
633 	    uacp->usb_ac_dev_data->dev_mfg : "-"),
634 	    (uacp->usb_ac_dev_data->dev_product ?
635 	    uacp->usb_ac_dev_data->dev_product : "-"),
636 	    (uacp->usb_ac_dev_data->dev_serial ?
637 	    uacp->usb_ac_dev_data->dev_serial : "-"),
638 	    uacp->usb_ac_dev_data->dev_descr->idVendor,
639 	    uacp->usb_ac_dev_data->dev_descr->idProduct,
640 	    ddi_driver_name(dip));
641 
642 	reg_data.asrd_key = key;
643 
644 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
645 	    "registering with key: %s", key);
646 
647 	uacp->usb_ac_audiohdl = audio_sup_register(dip, &reg_data);
648 	kmem_free(key, key_len);
649 
650 	if (uacp->usb_ac_audiohdl == NULL) {
651 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
652 		    "audio_sup_register failed");
653 
654 		goto fail;
655 	}
656 
657 	/* save softstate pointer in audio handle */
658 	audio_sup_set_private(uacp->usb_ac_audiohdl, (void *)uacp);
659 
660 	/* parse all class specific descriptors */
661 	if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) {
662 
663 		goto fail;
664 	}
665 
666 	/* we no longer need the descr tree */
667 	usb_free_descr_tree(dip, uacp->usb_ac_dev_data);
668 
669 	/* read .conf file properties */
670 	uacp->usb_ac_mixer_mode_enable = ddi_prop_get_int(DDI_DEV_T_ANY,
671 	    dip, DDI_PROP_DONTPASS, "mixer-enabled", 1);
672 
673 	uacp->usb_ac_ser_acc = usb_init_serialization(dip,
674 	    USB_INIT_SER_CHECK_SAME_THREAD);
675 
676 	/* create minor node */
677 	minor = audio_sup_construct_minor(uacp->usb_ac_audiohdl, USER1);
678 
679 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
680 	    "minor=%d", minor);
681 
682 	if ((ddi_create_minor_node(dip, "mux", S_IFCHR,
683 	    minor, NULL, 0)) != DDI_SUCCESS) {
684 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
685 		    "usb_ac_attach: couldn't create minor node mux");
686 
687 		goto fail;
688 	}
689 	uacp->usb_ac_mux_minor = minor;
690 
691 	mutex_enter(&uacp->usb_ac_mutex);
692 
693 	/* we are online */
694 	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
695 
696 	/*
697 	 * safe guard the postattach to be executed
698 	 * only two states arepossible: plumbed / unplumbed
699 	 */
700 	uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
701 	uacp->usb_ac_current_plumbed_index = -1;
702 
703 	mutex_exit(&uacp->usb_ac_mutex);
704 
705 	/* create components to power manage this device */
706 	usb_ac_create_pm_components(dip, uacp);
707 
708 	/* Register for events */
709 	if (usb_register_event_cbs(dip, &usb_ac_events, 0) != USB_SUCCESS) {
710 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
711 		    "usb_ac_attach: couldn't register for events");
712 
713 		goto fail;
714 	}
715 
716 	/* report device */
717 	ddi_report_dev(dip);
718 
719 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
720 	    "usb_ac_attach: End");
721 
722 	return (DDI_SUCCESS);
723 fail:
724 	if (uacp) {
725 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
726 		    "attach failed");
727 		(void) usb_ac_cleanup(dip, uacp);
728 	}
729 
730 	return (DDI_FAILURE);
731 }
732 
733 
734 static int
735 usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
736 {
737 	int instance = ddi_get_instance(dip);
738 	usb_ac_state_t	*uacp;
739 	int rval;
740 
741 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
742 
743 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
744 	    "usb_ac_detach:");
745 
746 	switch (cmd) {
747 	case DDI_DETACH:
748 		rval = usb_ac_cleanup(dip, uacp);
749 
750 		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
751 	case DDI_SUSPEND:
752 		rval = usb_ac_cpr_suspend(dip);
753 
754 		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
755 	default:
756 
757 		return (DDI_FAILURE);
758 	}
759 }
760 
761 
762 /*
763  * usb_ac_cleanup:
764  *	cleanup on attach failure and detach
765  */
766 static int
767 usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
768 {
769 	usb_ac_power_t	*uacpm;
770 	int	rval = USB_FAILURE;
771 
772 	ASSERT(uacp);
773 
774 	mutex_enter(&uacp->usb_ac_mutex);
775 	uacpm = uacp->usb_ac_pm;
776 
777 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
778 	    "usb_ac_cleanup: uacpm=0x%p", (void *)uacpm);
779 
780 	ASSERT(uacp->usb_ac_busy_count == 0);
781 
782 	ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED);
783 
784 	/*
785 	 * deregister with audio framework, if it fails we are hosed
786 	 * and we probably don't want to plumb again
787 	 */
788 	if (uacp->usb_ac_audiohdl) {
789 		if (uacp->usb_ac_registered_with_mixer) {
790 			mutex_exit(&uacp->usb_ac_mutex);
791 			if (am_detach(uacp->usb_ac_audiohdl, DDI_DETACH) !=
792 			    AUDIO_SUCCESS) {
793 
794 				return (rval);
795 			}
796 		} else {
797 			mutex_exit(&uacp->usb_ac_mutex);
798 		}
799 		if (audio_sup_unregister(uacp->usb_ac_audiohdl) !=
800 		    AUDIO_SUCCESS) {
801 
802 			return (rval);
803 		}
804 	} else {
805 		mutex_exit(&uacp->usb_ac_mutex);
806 	}
807 
808 	/*
809 	 * Disable the event callbacks, after this point, event
810 	 * callbacks will never get called. Note we shouldn't hold
811 	 * the mutex while unregistering events because there may be a
812 	 * competing event callback thread. Event callbacks are done
813 	 * with ndi mutex held and this can cause a potential deadlock.
814 	 */
815 	usb_unregister_event_cbs(dip, &usb_ac_events);
816 
817 	mutex_enter(&uacp->usb_ac_mutex);
818 
819 	if (uacpm && (uacp->usb_ac_dev_state != USB_DEV_DISCONNECTED)) {
820 		if (uacpm->acpm_wakeup_enabled) {
821 			mutex_exit(&uacp->usb_ac_mutex);
822 			usb_ac_pm_busy_component(uacp);
823 			(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
824 
825 			rval = usb_handle_remote_wakeup(dip,
826 			    USB_REMOTE_WAKEUP_DISABLE);
827 			if (rval != USB_SUCCESS) {
828 				USB_DPRINTF_L2(PRINT_MASK_PM,
829 				    uacp->usb_ac_log_handle,
830 				    "usb_ac_cleanup: disable remote "
831 				    "wakeup failed, rval=%d", rval);
832 			}
833 			usb_ac_pm_idle_component(uacp);
834 		} else {
835 			mutex_exit(&uacp->usb_ac_mutex);
836 		}
837 
838 		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
839 
840 		mutex_enter(&uacp->usb_ac_mutex);
841 	}
842 
843 	if (uacpm) {
844 		kmem_free(uacpm,  sizeof (usb_ac_power_t));
845 		uacp->usb_ac_pm = NULL;
846 	}
847 
848 	usb_client_detach(dip, uacp->usb_ac_dev_data);
849 
850 	/* free descriptors */
851 	usb_ac_free_all_units(uacp);
852 
853 	mutex_exit(&uacp->usb_ac_mutex);
854 
855 	mutex_destroy(&uacp->usb_ac_mutex);
856 
857 	usb_fini_serialization(uacp->usb_ac_ser_acc);
858 
859 	ddi_remove_minor_node(dip, NULL);
860 
861 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
862 	    "usb_ac_cleanup: Ending");
863 
864 	usb_free_log_hdl(uacp->usb_ac_log_handle);
865 	kmem_free(uacp->usb_ac_connections, uacp->usb_ac_connections_len);
866 	kmem_free(uacp->usb_ac_connections_a, uacp->usb_ac_connections_a_len);
867 	kmem_free(uacp->usb_ac_unit_type, uacp->usb_ac_max_unit);
868 	kmem_free(uacp->usb_ac_traverse_path, uacp->usb_ac_max_unit);
869 
870 	ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
871 
872 	ddi_prop_remove_all(dip);
873 
874 	return (USB_SUCCESS);
875 }
876 
877 
878 /*
879  * usb_ac_open:
880  *	Open entry point. Called on the plumbing minor node or
881  *	audio or audioctl minor nodes which we pass to audio_sup_open()
882  *	We do not raise power here and wait for the setup callback
883  */
884 /*ARGSUSED*/
885 static int
886 usb_ac_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
887 {
888 	int minor = getminor(*devp);
889 	int instance;
890 	int rval;
891 	usb_ac_state_t	*uacp;
892 
893 	instance = audio_sup_devt_to_instance(*devp);
894 
895 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
896 	if (uacp == NULL) {
897 
898 		return (ENXIO);
899 	}
900 
901 	mutex_enter(&uacp->usb_ac_mutex);
902 	uacp->usb_ac_busy_count++; /* This will prevent unplumbing */
903 
904 	USB_DPRINTF_L4(PRINT_MASK_OPEN, uacp->usb_ac_log_handle,
905 	    "usb_ac_open: Begin q=0x%p, minor=0x%x instance=%d "
906 	    "open cnt=%d", (void *)q, minor, instance, uacp->usb_ac_busy_count);
907 
908 	if (sflag) {
909 		USB_DPRINTF_L2(PRINT_MASK_OPEN, uacp->usb_ac_log_handle,
910 		    "usb_ac_open: clone open not supported");
911 
912 		uacp->usb_ac_busy_count--;
913 		mutex_exit(&uacp->usb_ac_mutex);
914 
915 		return (ENXIO);
916 	}
917 
918 	if (minor == uacp->usb_ac_mux_minor) {
919 
920 		USB_DPRINTF_L4(PRINT_MASK_OPEN, uacp->usb_ac_log_handle,
921 		    "usb_ac_open: opening mux");
922 		/*
923 		 * This is the plumbing open, initiated during attach/
924 		 * connect_event_callback/cpr_resume/first user open.
925 		 */
926 		uacp->usb_ac_busy_count--;
927 
928 		/* Save the dev_t value of pluming q to use for lower q's */
929 		uacp->usb_ac_dev = *devp;
930 		audio_sup_set_qptr(q, *devp, (void *)uacp);
931 
932 		/* Initialize the queue pointers */
933 		uacp->usb_ac_rq = q;
934 		uacp->usb_ac_wq = WR(q);
935 
936 		/* release mutex while making streams framework call */
937 		mutex_exit(&uacp->usb_ac_mutex);
938 		qprocson(q);
939 		mutex_enter(&uacp->usb_ac_mutex);
940 
941 	} else if (uacp->usb_ac_plumbing_state != USB_AC_STATE_PLUMBED) {
942 		uacp->usb_ac_busy_count--;
943 		mutex_exit(&uacp->usb_ac_mutex);
944 
945 		return (EIO);
946 	} else {
947 		/* pass the open to audio_sup_open so SADA can do its work */
948 		USB_DPRINTF_L4(PRINT_MASK_OPEN, uacp->usb_ac_log_handle,
949 		    "usb_ac_open: calling audio_sup_open, q=0x%p, open_cnt=%d",
950 		    (void *)q, uacp->usb_ac_busy_count);
951 
952 		mutex_exit(&uacp->usb_ac_mutex);
953 
954 		/*
955 		 * go to full power
956 		 */
957 		usb_ac_pm_busy_component(uacp);
958 		(void) pm_raise_power(uacp->usb_ac_dip, 0, USB_DEV_OS_FULL_PWR);
959 
960 		rval = audio_sup_open(q, devp, flag, sflag, credp);
961 
962 		mutex_enter(&uacp->usb_ac_mutex);
963 
964 		if (rval != 0) {
965 			USB_DPRINTF_L4(PRINT_MASK_OPEN,
966 			    uacp->usb_ac_log_handle,
967 			    "audio_sup_open rval=%d", rval);
968 
969 			uacp->usb_ac_busy_count--;
970 
971 			mutex_exit(&uacp->usb_ac_mutex);
972 
973 			usb_ac_pm_idle_component(uacp);
974 
975 			return (rval);
976 		}
977 	}
978 
979 	USB_DPRINTF_L4(PRINT_MASK_OPEN, uacp->usb_ac_log_handle,
980 	    "usb_ac_open: End q=0x%p, open cnt=%d",
981 	    (void *)q, uacp->usb_ac_busy_count);
982 
983 	mutex_exit(&uacp->usb_ac_mutex);
984 
985 	return (0);
986 }
987 
988 
989 /*
990  * usb_ac_close :
991  *	Close entry point
992  */
993 /*ARGSUSED*/
994 static int
995 usb_ac_close(queue_t *q, int flag, cred_t *credp)
996 {
997 	dev_t dev = audio_sup_get_qptr_dev(q);
998 	int minor = getminor(dev);
999 	int instance = audio_sup_get_qptr_instance(q);
1000 	usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance);
1001 	int rval;
1002 
1003 	mutex_enter(&uacp->usb_ac_mutex);
1004 
1005 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1006 	    "usb_ac_close: Begin q=0x%p, opencount=%d",
1007 	    (void *)q, uacp->usb_ac_busy_count);
1008 
1009 	/* closing the mux? */
1010 	if (minor == uacp->usb_ac_mux_minor) {
1011 		USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1012 		    "usb_ac_close: closing mux plumbing stream");
1013 		mutex_exit(&uacp->usb_ac_mutex);
1014 
1015 		/* Wait till all activity in the default pipe has drained */
1016 		usb_ac_serialize_access(uacp);
1017 		usb_ac_release_access(uacp);
1018 
1019 		audio_sup_free_qptr(q);
1020 		qprocsoff(q);
1021 
1022 		return (0);
1023 	}
1024 
1025 	mutex_exit(&uacp->usb_ac_mutex);
1026 
1027 	rval = audio_sup_close(q, flag, credp);
1028 
1029 	if (rval != 0) {
1030 		USB_DPRINTF_L2(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1031 		    "audio_sup_close fails %d", rval);
1032 
1033 		return (rval);
1034 	}
1035 
1036 	mutex_enter(&uacp->usb_ac_mutex);
1037 
1038 	/* normal streams closing */
1039 	ASSERT(uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED);
1040 
1041 	uacp->usb_ac_busy_count --;
1042 
1043 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1044 	    "usb_ac_close: End rval=%d q=0x%p, opencount=%d",
1045 	    rval, (void *)q, uacp->usb_ac_busy_count);
1046 
1047 	mutex_exit(&uacp->usb_ac_mutex);
1048 
1049 	usb_ac_pm_idle_component(uacp);
1050 
1051 	return (0);
1052 }
1053 
1054 
1055 /*
1056  * usb_ac_uwput:
1057  *	write put entry point for the upper mux. Only PLUMB/UNPLUMB ioctls
1058  *	are processed here. All other ioctls are passed to audio_sup routines
1059  *	for further processing.
1060  */
1061 static int
1062 usb_ac_uwput(queue_t *q, mblk_t *mp)
1063 {
1064 	int instance = audio_sup_get_qptr_instance(q);
1065 	usb_ac_state_t	*uacp = ddi_get_soft_state(usb_ac_statep, instance);
1066 	int error = DDI_SUCCESS;
1067 
1068 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1069 	    "usb_ac_uwput: q=0x%p, mp=0x%p", (void *)q, (void *)mp);
1070 
1071 	ASSERT(mp != NULL);
1072 	ASSERT(mp->b_datap != NULL);
1073 
1074 	mutex_enter(&uacp->usb_ac_mutex);
1075 	if (uacp->usb_ac_wq == q) {
1076 		ASSERT(mp->b_datap->db_type == M_IOCTL);
1077 
1078 		mutex_exit(&uacp->usb_ac_mutex);
1079 
1080 		/* ioctl from plumbing thread (namely P_LINK) */
1081 		usb_ac_plumb_ioctl(q, mp);
1082 
1083 		return (error);
1084 	}
1085 	mutex_exit(&uacp->usb_ac_mutex);
1086 
1087 	/* Pass to audio_sup routine */
1088 	(void) audio_sup_wput(q, mp);
1089 
1090 	return (error);
1091 }
1092 
1093 
1094 /*
1095  * usb_ac_lrput:
1096  *	read put entry point for the lower mux. Get the response from the
1097  *	lower module, signal usb_ac_send_as_cmd(), the thread that is waiting
1098  *	for a response to a message sent earlier anbd pass the response
1099  *	message	block.
1100  */
1101 static int
1102 usb_ac_lrput(queue_t *q, mblk_t *mp)
1103 {
1104 	int instance = audio_sup_get_qptr_instance(q);
1105 	usb_ac_state_t	*uacp;
1106 	int error = DDI_SUCCESS;
1107 	usb_ac_plumbed_t *plumb_infop;
1108 	usb_ac_streams_info_t *streams_infop = NULL;
1109 	int	val;
1110 	char	val1;
1111 	struct iocblk *iocp;
1112 
1113 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
1114 
1115 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1116 	    "usb_ac_lrput: q=0x%p, mp=0x%p, instance=%d",
1117 	    (void *)q, (void *)mp, instance);
1118 	ASSERT(mp != NULL);
1119 
1120 	mutex_enter(&uacp->usb_ac_mutex);
1121 	plumb_infop = usb_ac_get_plumb_info_from_lrq(uacp, q);
1122 	ASSERT(plumb_infop != NULL);
1123 
1124 	switch (mp->b_datap->db_type) {
1125 	case M_CTL:
1126 	case M_ERROR:
1127 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1128 		    "M_CTL/M_ERROR");
1129 
1130 		switch (plumb_infop->acp_driver) {
1131 		case USB_AS_PLUMBED:
1132 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1133 			    "reply from usb_as, lrq=0x%p", (void *)q);
1134 			streams_infop = (usb_ac_streams_info_t *)
1135 			    plumb_infop->acp_data;
1136 			ASSERT(streams_infop != NULL);
1137 			streams_infop->acs_ac_to_as_req.acr_reply_mp = mp;
1138 			streams_infop->acs_ac_to_as_req.acr_wait_flag = 0;
1139 			cv_signal(&streams_infop->acs_ac_to_as_req.acr_cv);
1140 
1141 			break;
1142 		case USB_AH_PLUMBED:
1143 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1144 			    "M_CTL from hid, lrq=0x%p", (void *)q);
1145 
1146 			iocp = (struct iocblk *)mp->b_rptr;
1147 			ASSERT(mp->b_cont != NULL);
1148 
1149 			if (uacp->usb_ac_registered_with_mixer) {
1150 
1151 				val1 = *((char *)mp->b_cont->b_rptr);
1152 				val = (int)val1;
1153 
1154 				USB_DPRINTF_L4(PRINT_MASK_ALL,
1155 				    uacp->usb_ac_log_handle, "val1=0x%x(%d),"
1156 				    "val=0x%x(%d)", val1, val1, val, val);
1157 
1158 				switch (iocp->ioc_cmd) {
1159 				/* Handle relative volume change */
1160 				case USB_AUDIO_VOL_CHANGE:
1161 					/* prevent unplumbing */
1162 					uacp->usb_ac_busy_count++;
1163 					if (uacp->usb_ac_plumbing_state ==
1164 					    USB_AC_STATE_PLUMBED) {
1165 						mutex_exit(&uacp->usb_ac_mutex);
1166 						(void) am_hw_state_change(
1167 						    uacp->usb_ac_audiohdl,
1168 						    AM_HWSC_SET_GAIN_DELTA,
1169 						    AUDIO_PLAY, val,
1170 						    AUDIO_NO_SLEEP);
1171 						mutex_enter(&uacp->
1172 						    usb_ac_mutex);
1173 					}
1174 					uacp->usb_ac_busy_count--;
1175 					/* FALLTHRU */
1176 				case USB_AUDIO_MUTE:
1177 				default:
1178 					freemsg(mp);
1179 					break;
1180 				}
1181 			} else {
1182 				freemsg(mp);
1183 			}
1184 
1185 			break;
1186 		default:
1187 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1188 			    "M_CTL from unknown module(%s)",
1189 			    ddi_driver_name(plumb_infop->acp_dip));
1190 			freemsg(mp);
1191 		}
1192 
1193 		break;
1194 	default:
1195 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1196 		    "Unknown type=%d", mp->b_datap->db_type);
1197 		usb_ac_free_mblk(mp);
1198 	}
1199 	mutex_exit(&uacp->usb_ac_mutex);
1200 
1201 	/*
1202 	 * Nobody is waiting; nothing to send up.
1203 	 */
1204 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1205 	    "usb_ac_lrput: done");
1206 
1207 	return (error);
1208 }
1209 
1210 
1211 /*
1212  * Power Management
1213  * usb_ac_power:
1214  *	power entry point
1215  */
1216 static int
1217 usb_ac_power(dev_info_t *dip, int comp, int level)
1218 {
1219 	int		instance = ddi_get_instance(dip);
1220 	usb_ac_state_t	*uacp;
1221 	usb_ac_power_t	*uacpm;
1222 	int		rval = DDI_FAILURE;
1223 
1224 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
1225 
1226 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1227 	    "usb_ac_power: comp=%d level=%d", comp, level);
1228 
1229 	mutex_enter(&uacp->usb_ac_mutex);
1230 	uacpm = uacp->usb_ac_pm;
1231 
1232 	if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) {
1233 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1234 		    "usb_ac_power: illegal level=%d pwr_states=%d",
1235 		    level, uacpm->acpm_pwr_states);
1236 
1237 		goto done;
1238 	}
1239 
1240 	switch (level) {
1241 	case USB_DEV_OS_PWR_OFF:
1242 		rval = usb_ac_pwrlvl0(uacp);
1243 		break;
1244 	case USB_DEV_OS_PWR_1:
1245 		rval = usb_ac_pwrlvl1(uacp);
1246 		break;
1247 	case USB_DEV_OS_PWR_2:
1248 		rval = usb_ac_pwrlvl2(uacp);
1249 		break;
1250 	case USB_DEV_OS_FULL_PWR:
1251 		rval = usb_ac_pwrlvl3(uacp);
1252 		break;
1253 	}
1254 
1255 done:
1256 	mutex_exit(&uacp->usb_ac_mutex);
1257 
1258 	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1259 }
1260 
1261 
1262 /*
1263  * functions to handle power transition for various levels
1264  * These functions act as place holders to issue USB commands
1265  * to the devices to change their power levels
1266  * Level 0 = Device is powered off
1267  * Level 3 = Device if full powered
1268  * Level 1,2 = Intermediate power level of the device as implemented
1269  *	by the hardware.
1270  * Note that Level 0 is OS power-off and Level 3 is OS full-power.
1271  */
1272 static int
1273 usb_ac_pwrlvl0(usb_ac_state_t *uacp)
1274 {
1275 	usb_ac_power_t	*uacpm;
1276 	int		rval;
1277 
1278 	uacpm = uacp->usb_ac_pm;
1279 
1280 	switch (uacp->usb_ac_dev_state) {
1281 	case USB_DEV_ONLINE:
1282 		/* Deny the powerdown request if the device is busy */
1283 		if (uacpm->acpm_pm_busy != 0) {
1284 
1285 			return (USB_FAILURE);
1286 		}
1287 
1288 		/* Issue USB D3 command to the device here */
1289 		rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip);
1290 		ASSERT(rval == USB_SUCCESS);
1291 
1292 		uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN;
1293 		uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF;
1294 
1295 		/* FALLTHRU */
1296 	case USB_DEV_DISCONNECTED:
1297 	case USB_DEV_SUSPENDED:
1298 	case USB_DEV_PWRED_DOWN:
1299 	default:
1300 		return (USB_SUCCESS);
1301 	}
1302 }
1303 
1304 
1305 /* ARGSUSED */
1306 static int
1307 usb_ac_pwrlvl1(usb_ac_state_t *uacp)
1308 {
1309 	int		rval;
1310 
1311 	/* Issue USB D2 command to the device here */
1312 	rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip);
1313 	ASSERT(rval == USB_SUCCESS);
1314 
1315 	return (USB_FAILURE);
1316 }
1317 
1318 
1319 /* ARGSUSED */
1320 static int
1321 usb_ac_pwrlvl2(usb_ac_state_t *uacp)
1322 {
1323 	int		rval;
1324 
1325 	rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip);
1326 	ASSERT(rval == USB_SUCCESS);
1327 
1328 	return (USB_FAILURE);
1329 }
1330 
1331 
1332 static int
1333 usb_ac_pwrlvl3(usb_ac_state_t *uacp)
1334 {
1335 	usb_ac_power_t	*uacpm;
1336 	int		rval;
1337 
1338 	uacpm = uacp->usb_ac_pm;
1339 
1340 	switch (uacp->usb_ac_dev_state) {
1341 	case USB_DEV_PWRED_DOWN:
1342 		/* Issue USB D0 command to the device here */
1343 		rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip);
1344 		ASSERT(rval == USB_SUCCESS);
1345 
1346 		uacp->usb_ac_dev_state = USB_DEV_ONLINE;
1347 		uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1348 		/* FALLTHRU */
1349 	case USB_DEV_ONLINE:
1350 		/* we are already in full power */
1351 
1352 		/* FALLTHRU */
1353 	case USB_DEV_DISCONNECTED:
1354 	case USB_DEV_SUSPENDED:
1355 
1356 		return (USB_SUCCESS);
1357 	default:
1358 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1359 		    "usb_ac_pwerlvl3: Illegal dev_state");
1360 
1361 		return (USB_FAILURE);
1362 	}
1363 }
1364 
1365 
1366 static void
1367 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
1368 {
1369 	usb_ac_power_t	*uacpm;
1370 	uint_t		pwr_states;
1371 
1372 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1373 	    "usb_ac_create_pm_components: begin");
1374 
1375 	/* Allocate the state structure */
1376 	uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP);
1377 	uacp->usb_ac_pm = uacpm;
1378 	uacpm->acpm_state = uacp;
1379 	uacpm->acpm_capabilities = 0;
1380 	uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1381 
1382 	if (usb_create_pm_components(dip, &pwr_states) ==
1383 	    USB_SUCCESS) {
1384 		if (usb_handle_remote_wakeup(dip,
1385 		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1386 			uacpm->acpm_wakeup_enabled = 1;
1387 
1388 			USB_DPRINTF_L4(PRINT_MASK_PM,
1389 			    uacp->usb_ac_log_handle,
1390 			    "remote Wakeup enabled");
1391 		}
1392 		uacpm->acpm_pwr_states = (uint8_t)pwr_states;
1393 		(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1394 	} else {
1395 		if (uacpm) {
1396 			kmem_free(uacpm,  sizeof (usb_ac_power_t));
1397 			uacp->usb_ac_pm = NULL;
1398 		}
1399 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1400 		    "pm not enabled");
1401 	}
1402 
1403 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1404 	    "usb_ac_create_pm_components: end");
1405 }
1406 
1407 
1408 /*
1409  * usb_ac_plumb_ioctl:
1410  *	IOCTL issued from plumbing thread (only P_LINK_LH/P_UNLINK for now
1411  *	caused by ldi_ioctl). Maybe we will need to use this function
1412  *	to issue other IOCTLS to children in future from plumbing thread
1413  */
1414 static void
1415 usb_ac_plumb_ioctl(queue_t *q, mblk_t *mp)
1416 {
1417 	int		instance = audio_sup_get_qptr_instance(q);
1418 	usb_ac_state_t	*uacp = ddi_get_soft_state(usb_ac_statep, instance);
1419 	struct iocblk	*iocp;
1420 	struct linkblk	*linkp;
1421 	int		n;
1422 	usb_ac_streams_info_t *streams_infop;
1423 
1424 	ASSERT(uacp != NULL);
1425 	ASSERT(mp != NULL);
1426 	ASSERT(mp->b_cont != NULL);
1427 
1428 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1429 	    "usb_ac_plumb_ioctl, q=0x%p mp=0x%p instance=%d",
1430 	    (void *)q, (void *)mp, instance);
1431 
1432 	iocp = (struct iocblk *)mp->b_rptr;
1433 	mutex_enter(&uacp->usb_ac_mutex);
1434 	n = uacp->usb_ac_current_plumbed_index;
1435 
1436 	switch (iocp->ioc_cmd) {
1437 	case I_PLINK:
1438 		linkp = (struct linkblk *)mp->b_cont->b_rptr;
1439 
1440 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1441 		    "LINK ioctl, index=%d linkblk ptr=0x%p", n, (void *)linkp);
1442 
1443 		/*
1444 		 * We keep track of the module that is being
1445 		 * currently plumbed through usb_ac_current_plumbed_index
1446 		 * to the plumb structure array. We set the lwq field
1447 		 * of the plumb structure here.
1448 		 */
1449 		ASSERT(uacp->usb_ac_plumbed[n].acp_lwq == NULL);
1450 		uacp->usb_ac_plumbed[n].acp_lwq = linkp->l_qbot;
1451 		uacp->usb_ac_plumbed[n].acp_lrq = RD(linkp->l_qbot);
1452 
1453 		audio_sup_set_qptr(uacp->usb_ac_plumbed[n].acp_lrq,
1454 		    uacp->usb_ac_dev, (void *)uacp);
1455 
1456 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1457 		    "index=%d lwq=0x%p lrq=0x%p", n, (void *)linkp->l_qbot,
1458 		    (void *)RD(linkp->l_qbot));
1459 		break;
1460 	case I_UNLINK:
1461 	case I_PUNLINK:
1462 		linkp = (struct linkblk *)mp->b_cont->b_rptr;
1463 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1464 		    "UNLINK ioctl, linkblk ptr=0x%p", (void *)linkp);
1465 
1466 		audio_sup_free_qptr(RD(linkp->l_qbot));
1467 		uacp->usb_ac_dev = 0;
1468 
1469 		if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) {
1470 
1471 			/*
1472 			 * we bzero the streams info and plumbed structure
1473 			 * since there is no guarantee that the next plumbing
1474 			 * will be identical
1475 			 */
1476 			streams_infop = (usb_ac_streams_info_t *)
1477 			    uacp->usb_ac_plumbed[n].acp_data;
1478 			cv_destroy(&(streams_infop->acs_ac_to_as_req.acr_cv));
1479 
1480 			/* bzero the relevant plumbing structure */
1481 			bzero(streams_infop, sizeof (usb_ac_streams_info_t));
1482 		}
1483 		bzero(&uacp->usb_ac_plumbed[n], sizeof (usb_ac_plumbed_t));
1484 
1485 		iocp->ioc_count = 0;
1486 		break;
1487 	default:
1488 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1489 		    "Unknown ioctl, cmd=%d", iocp->ioc_cmd);
1490 		iocp->ioc_error = EINVAL;
1491 		mutex_exit(&uacp->usb_ac_mutex);
1492 
1493 		goto iocnak;
1494 	}
1495 
1496 	mutex_exit(&uacp->usb_ac_mutex);
1497 
1498 	/*
1499 	 * Common exit path for calls that return a positive
1500 	 * acknowledgment with a return value of 0.
1501 	 */
1502 	iocp->ioc_rval = 0;
1503 	iocp->ioc_error = 0;
1504 	mp->b_datap->db_type = M_IOCACK;
1505 	qreply(q, mp);
1506 
1507 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1508 	    "usb_ac_plumb_ioctl: End (ACK)");
1509 
1510 	return;
1511 
1512 iocnak:
1513 
1514 	iocp->ioc_rval = 0;
1515 	mp->b_datap->db_type = M_IOCNAK;
1516 	qreply(q, mp);
1517 
1518 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1519 	    "usb_ac_plumb_ioctl: End: (NAK)");
1520 }
1521 
1522 
1523 /*
1524  * usb_ac_get_plumb_info:
1525  *	Get plumb_info pointer that matches module "name"
1526  *	If name = "usb_as", match the direction also (record or play)
1527  */
1528 static usb_ac_plumbed_t *
1529 usb_ac_get_plumb_info(usb_ac_state_t *uacp, char *name, uchar_t reg_play_type)
1530 {
1531 	int			n;
1532 	usb_ac_plumbed_t	*plumb_infop = NULL;
1533 	usb_as_registration_t	*asreg;
1534 	usb_ac_streams_info_t	*asinfo;
1535 
1536 	for (n = 0; n < USB_AC_MAX_PLUMBED; n++) {
1537 		if (uacp->usb_ac_plumbed[n].acp_dip == NULL) {
1538 			continue;
1539 		}
1540 		if (strcmp(ddi_driver_name(uacp->
1541 		    usb_ac_plumbed[n].acp_dip), name) != 0) {
1542 			continue;
1543 		}
1544 		if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) {
1545 			asinfo = uacp->usb_ac_plumbed[n].acp_data;
1546 			asreg = asinfo->acs_streams_reg;
1547 			/* Match direction */
1548 			if (asreg->reg_mode & reg_play_type) {
1549 				break;
1550 			}
1551 		} else if (uacp->usb_ac_plumbed[n].acp_driver ==
1552 		    USB_AH_PLUMBED) {
1553 			break;
1554 		}
1555 	}
1556 
1557 	if (n < USB_AC_MAX_PLUMBED) {
1558 		plumb_infop = &uacp->usb_ac_plumbed[n];
1559 	}
1560 
1561 	return (plumb_infop);
1562 }
1563 
1564 
1565 /*
1566  * usb_ac_get_pinfo_from_lrq:
1567  *	Get plumb_info pointer that matches the lrq passed
1568  */
1569 static usb_ac_plumbed_t *
1570 usb_ac_get_plumb_info_from_lrq(usb_ac_state_t *uacp, queue_t *lrq)
1571 {
1572 	int	n;
1573 
1574 	for (n = 0; n < USB_AC_MAX_PLUMBED; n++) {
1575 		if (uacp->usb_ac_plumbed[n].acp_lrq == lrq) {
1576 
1577 			return (&uacp->usb_ac_plumbed[n]);
1578 		}
1579 	}
1580 
1581 	return (NULL);
1582 }
1583 
1584 
1585 /*
1586  * usb_ac_get_featureID:
1587  *	find out if there is at least one feature unit that supports
1588  *	the request controls.
1589  *	Return featureID or USB_AC_ID_NONE.
1590  */
1591 static uint_t
1592 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir,
1593     uint_t channel, uint_t control)
1594 {
1595 	uint_t count = 0;
1596 
1597 	return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT,
1598 	    channel, control, USB_AC_FIND_ONE, &count, 0,
1599 	    usb_ac_feature_unit_check));
1600 }
1601 
1602 
1603 /*
1604  * usb_ac_feature_unit_check:
1605  *	check if a feature unit can support the required channel
1606  *	and control combination. Return USB_SUCCESS or USB_FAILURE.
1607  *	Called for each matching unit from usb_ac_traverse_connections.
1608  */
1609 /*ARGSUSED*/
1610 static int
1611 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
1612     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1613 {
1614 	usb_audio_feature_unit_descr1_t *feature_descrp;
1615 	int				n_channel_controls;
1616 
1617 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1618 	    "usb_ac_feature_unit_check: ID=%d ch=%d cntrl=%d",
1619 	    featureID, channel, control);
1620 
1621 	ASSERT((featureID >= 0) && (featureID < uacp->usb_ac_max_unit));
1622 
1623 	/*
1624 	 * check if this control is supported on this channel
1625 	 */
1626 	feature_descrp = (usb_audio_feature_unit_descr1_t *)
1627 	    uacp->usb_ac_units[featureID].acu_descriptor;
1628 	ASSERT(feature_descrp->bUnitID == featureID);
1629 
1630 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1631 	    "bControlSize=%d", feature_descrp->bControlSize);
1632 
1633 	if (feature_descrp->bControlSize == 0) {
1634 		featureID = USB_AC_ID_NONE;
1635 	} else {
1636 		uint_t index;
1637 
1638 		n_channel_controls = (feature_descrp->bLength -
1639 		    offsetof(usb_audio_feature_unit_descr1_t,
1640 		    bmaControls))/feature_descrp->bControlSize;
1641 
1642 		USB_DPRINTF_L3(PRINT_MASK_ALL,
1643 		    uacp->usb_ac_log_handle,
1644 		    "#controls: %d index=%d", n_channel_controls,
1645 		    feature_descrp->bControlSize * channel);
1646 
1647 		if (channel > n_channel_controls) {
1648 			featureID = USB_AC_ID_NONE;
1649 		} else {
1650 			/*
1651 			 * we only support MUTE and VOLUME
1652 			 * which are in the first byte
1653 			 */
1654 			index = feature_descrp->bControlSize *
1655 			    channel;
1656 
1657 			USB_DPRINTF_L3(PRINT_MASK_ALL,
1658 			    uacp->usb_ac_log_handle,
1659 			    "control: 0x%x",
1660 			    feature_descrp->bmaControls[index]);
1661 
1662 			if ((feature_descrp->bmaControls[index] &
1663 			    control) == 0) {
1664 				featureID = USB_AC_ID_NONE;
1665 			}
1666 		}
1667 	}
1668 
1669 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1670 	    "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
1671 	    dir, featureID);
1672 
1673 	return ((featureID != USB_AC_ID_NONE) ?
1674 	    USB_SUCCESS : USB_FAILURE);
1675 }
1676 
1677 
1678 /*
1679  * Descriptor Management
1680  *
1681  * usb_ac_handle_descriptors:
1682  *	extract interesting descriptors from the config cloud
1683  */
1684 static int
1685 usb_ac_handle_descriptors(usb_ac_state_t *uacp)
1686 {
1687 	int			rest, len, index;
1688 	int			rval = USB_FAILURE;
1689 	usb_audio_cs_if_descr_t descr;
1690 	usb_client_dev_data_t	*dev_data = uacp->usb_ac_dev_data;
1691 	usb_alt_if_data_t	*altif_data;
1692 	usb_cvs_data_t		*cvs;
1693 
1694 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1695 	    "config=%ld, interface=%d",
1696 	    (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]),
1697 	    dev_data->dev_curr_if);
1698 
1699 	altif_data = &dev_data->dev_curr_cfg->
1700 	    cfg_if[dev_data->dev_curr_if].if_alt[0];
1701 
1702 	uacp->usb_ac_ifno	= dev_data->dev_curr_if;
1703 	uacp->usb_ac_if_descr	= altif_data->altif_descr;
1704 
1705 	/* find USB_AUDIO_CS_INTERFACE type descriptor */
1706 	for (index = 0; index < altif_data->altif_n_cvs; index++) {
1707 		cvs = &altif_data->altif_cvs[index];
1708 		if (cvs->cvs_buf == NULL) {
1709 			continue;
1710 		}
1711 		if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) {
1712 			break;
1713 		}
1714 	}
1715 
1716 	if (index == altif_data->altif_n_cvs) {
1717 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1718 		    "cannot find descriptor type %d", USB_AUDIO_CS_INTERFACE);
1719 
1720 		return (rval);
1721 	}
1722 
1723 	len = usb_parse_data(
1724 	    CS_AC_IF_HEADER_FORMAT,
1725 	    cvs->cvs_buf, cvs->cvs_buf_len,
1726 	    (void *)&descr, sizeof (usb_audio_cs_if_descr_t));
1727 
1728 	/* is this a sane header descriptor */
1729 	if (!((len >= CS_AC_IF_HEADER_SIZE) &&
1730 	    (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
1731 	    (descr.bDescriptorSubType == USB_AUDIO_HEADER))) {
1732 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1733 		    "invalid header");
1734 
1735 		return (rval);
1736 	}
1737 
1738 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1739 	    "header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
1740 	    "total=0x%x InCol=0x%x",
1741 	    descr.bDescriptorType,
1742 	    descr.bDescriptorSubType,
1743 	    descr.bcdADC,
1744 	    descr.wTotalLength,
1745 	    descr.blnCollection);
1746 
1747 	/*
1748 	 * we read descriptors by index and store them in ID array.
1749 	 * the actual parsing is done in usb_ac_add_unit_descriptor()
1750 	 */
1751 	rest = descr.wTotalLength - descr.bLength;
1752 	for (index++; rest > 0; index++) {
1753 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1754 		    "index=%d rest=%d", index, rest);
1755 
1756 		cvs = &altif_data->altif_cvs[index];
1757 		if (cvs->cvs_buf == NULL) {
1758 			continue;
1759 		}
1760 
1761 		/* add to ID array */
1762 		usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf,
1763 		    cvs->cvs_buf_len);
1764 		rest -= cvs->cvs_buf[0];
1765 	}
1766 	rval = USB_SUCCESS;
1767 
1768 	usb_ac_setup_connections(uacp);
1769 
1770 	/* determine port types */
1771 	usb_ac_map_termtype_to_port(uacp, AUDIO_PLAY);
1772 	usb_ac_map_termtype_to_port(uacp, AUDIO_RECORD);
1773 
1774 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1775 	    "input port types=0x%x output port types =0x%x",
1776 	    uacp->usb_ac_input_ports, uacp->usb_ac_output_ports);
1777 
1778 
1779 	return (rval);
1780 }
1781 
1782 
1783 /*
1784  * usb_ac_setup_connections:
1785  *	build a matrix reflecting all connections
1786  */
1787 static void
1788 usb_ac_setup_connections(usb_ac_state_t *uacp)
1789 {
1790 	usb_ac_unit_list_t	*units = uacp->usb_ac_units;
1791 	uchar_t			*a, **p, i, unit;
1792 	size_t			a_len, p_len;
1793 
1794 	/* allocate array for unit types for quick reference */
1795 	uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit,
1796 	    KM_SLEEP);
1797 	/* allocate array for traversal path */
1798 	uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit,
1799 	    KM_SLEEP);
1800 
1801 
1802 	/* allocate the connection matrix and set it up */
1803 	a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit;
1804 	p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *);
1805 
1806 	/* trick to create a 2 dimensional array */
1807 	a = kmem_zalloc(a_len, KM_SLEEP);
1808 	p = kmem_zalloc(p_len, KM_SLEEP);
1809 	for (i = 0; i < uacp->usb_ac_max_unit; i++) {
1810 		p[i] = a + i * uacp->usb_ac_max_unit;
1811 	}
1812 	uacp->usb_ac_connections = p;
1813 	uacp->usb_ac_connections_len = p_len;
1814 	uacp->usb_ac_connections_a = a;
1815 	uacp->usb_ac_connections_a_len = a_len;
1816 
1817 	/* traverse all units and set connections */
1818 	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1819 
1820 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1821 		    "traversing unit=0x%x type=0x%x",
1822 		    unit, units[unit].acu_type);
1823 
1824 		/* store type in the first unused column */
1825 		uacp->usb_ac_unit_type[unit] = units[unit].acu_type;
1826 
1827 		/* save the Unit ID in the unit it points to */
1828 		switch (units[unit].acu_type) {
1829 		case USB_AUDIO_FEATURE_UNIT:
1830 		{
1831 			usb_audio_feature_unit_descr1_t *d =
1832 			    units[unit].acu_descriptor;
1833 
1834 			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1835 			    "sourceID=0x%x type=0x%x", d->bSourceID,
1836 			    units[d->bSourceID].acu_type);
1837 
1838 			if (d->bSourceID != 0) {
1839 				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1840 				p[unit][d->bSourceID] = B_TRUE;
1841 			}
1842 
1843 			break;
1844 		}
1845 		case USB_AUDIO_OUTPUT_TERMINAL:
1846 		{
1847 			usb_audio_output_term_descr_t *d =
1848 			    units[unit].acu_descriptor;
1849 
1850 			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1851 			    "sourceID=0x%x type=0x%x", d->bSourceID,
1852 			    units[d->bSourceID].acu_type);
1853 
1854 			if (d->bSourceID != 0) {
1855 				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1856 				p[unit][d->bSourceID] = B_TRUE;
1857 			}
1858 
1859 			break;
1860 		}
1861 		case USB_AUDIO_MIXER_UNIT:
1862 		{
1863 			usb_audio_mixer_unit_descr1_t *d =
1864 			    units[unit].acu_descriptor;
1865 			int n_sourceID = d->bNrInPins;
1866 			int id;
1867 
1868 			for (id = 0; id < n_sourceID; id++) {
1869 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1870 				    uacp->usb_ac_log_handle,
1871 				    "sourceID=0x%x type=0x%x c=%d",
1872 				    d->baSourceID[id],
1873 				    units[d->baSourceID[id]].acu_type,
1874 				    p[unit][d->baSourceID[id]]);
1875 
1876 				if (d->baSourceID[id] != 0) {
1877 					ASSERT(p[unit][d->baSourceID[id]] ==
1878 					    B_FALSE);
1879 					p[unit][d->baSourceID[id]] = B_TRUE;
1880 				}
1881 			}
1882 
1883 			break;
1884 		}
1885 		case USB_AUDIO_SELECTOR_UNIT:
1886 		{
1887 			usb_audio_selector_unit_descr1_t *d =
1888 			    units[unit].acu_descriptor;
1889 			int n_sourceID = d->bNrInPins;
1890 			int id;
1891 
1892 			for (id = 0; id < n_sourceID; id++) {
1893 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1894 				    uacp->usb_ac_log_handle,
1895 				    "sourceID=0x%x type=0x%x",
1896 				    d->baSourceID[id],
1897 				    units[d->baSourceID[id]].acu_type);
1898 
1899 				if (d->baSourceID[id] != 0) {
1900 					ASSERT(p[unit][d->baSourceID[id]] ==
1901 					    B_FALSE);
1902 					p[unit][d->baSourceID[id]] = B_TRUE;
1903 				}
1904 			}
1905 
1906 			break;
1907 		}
1908 		case USB_AUDIO_PROCESSING_UNIT:
1909 		{
1910 			usb_audio_mixer_unit_descr1_t *d =
1911 			    units[unit].acu_descriptor;
1912 			int n_sourceID = d->bNrInPins;
1913 			int id;
1914 
1915 			for (id = 0; id < n_sourceID; id++) {
1916 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1917 				    uacp->usb_ac_log_handle,
1918 				    "sourceID=0x%x type=0x%x",
1919 				    d->baSourceID[id],
1920 				    units[d->baSourceID[id]].acu_type);
1921 
1922 				if (d->baSourceID[id] != 0) {
1923 					ASSERT(p[unit][d->baSourceID[id]] ==
1924 					    B_FALSE);
1925 					p[unit][d->baSourceID[id]] = B_TRUE;
1926 				}
1927 			}
1928 
1929 			break;
1930 		}
1931 		case USB_AUDIO_EXTENSION_UNIT:
1932 		{
1933 			usb_audio_extension_unit_descr1_t *d =
1934 			    units[unit].acu_descriptor;
1935 			int n_sourceID = d->bNrInPins;
1936 			int id;
1937 
1938 			for (id = 0; id < n_sourceID; id++) {
1939 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1940 				    uacp->usb_ac_log_handle,
1941 				    "sourceID=0x%x type=0x%x",
1942 				    d->baSourceID[id],
1943 				    units[d->baSourceID[id]].acu_type);
1944 
1945 				if (d->baSourceID[id] != 0) {
1946 					ASSERT(p[unit][d->baSourceID[id]] ==
1947 					    B_TRUE);
1948 					p[unit][d->baSourceID[id]] = B_FALSE;
1949 				}
1950 			}
1951 
1952 			break;
1953 		}
1954 		case USB_AUDIO_INPUT_TERMINAL:
1955 
1956 			break;
1957 		default:
1958 			/*
1959 			 * Ignore the rest because they are not support yet
1960 			 */
1961 			break;
1962 		}
1963 	}
1964 
1965 #ifdef DEBUG
1966 	/* display topology in log buffer */
1967 {
1968 	uint_t i, j, l;
1969 	char *buf;
1970 
1971 	l = uacp->usb_ac_max_unit * 5;
1972 
1973 	buf = kmem_alloc(l, KM_SLEEP);
1974 
1975 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1976 	    "unit types:");
1977 
1978 	/* two	strings so they won't be replaced accidentily by tab */
1979 	(void) sprintf(&buf[0], "    ""    ");
1980 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1981 		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1982 	}
1983 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1984 
1985 	(void) sprintf(&buf[0], "  +-------");
1986 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1987 		(void) sprintf(&buf[5+((i-1)*3)], "---");
1988 	}
1989 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1990 
1991 	(void) sprintf(&buf[0], "    ""    ");
1992 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1993 		(void) sprintf(&buf[2 + (i*3)], "%02d ",
1994 		    uacp->usb_ac_unit_type[i]);
1995 	}
1996 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1997 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " ");
1998 
1999 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2000 	    "adjacency matrix:");
2001 	(void) sprintf(&buf[0], "    ""    ");
2002 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
2003 		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
2004 	}
2005 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
2006 
2007 	(void) sprintf(&buf[0], "  +-------");
2008 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
2009 		(void) sprintf(&buf[5+((i-1)*3)], "---");
2010 	}
2011 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
2012 
2013 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
2014 		(void) sprintf(&buf[0], "%02d| "" ", i);
2015 		for (j = 1; j < uacp->usb_ac_max_unit; j++) {
2016 			(void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]);
2017 		}
2018 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
2019 	}
2020 	kmem_free(buf, l);
2021 }
2022 #endif
2023 }
2024 
2025 
2026 /*
2027  * usb_ac_add_unit_descriptor:
2028  *	take the parsed descriptor in the buffer and store it in the ID unit
2029  *	array. we grow the unit array if the ID exceeds the current max
2030  */
2031 static void
2032 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
2033 	size_t buflen)
2034 {
2035 	void	*descr;
2036 	int	len;
2037 	char	*format;
2038 	size_t	size;
2039 
2040 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2041 	    "usb_ac_add_unit_descriptor: 0x%x 0x%x 0x%x",
2042 	    buffer[0], buffer[1], buffer[2]);
2043 
2044 	/* doubling the length should allow for padding */
2045 	len = 2 * buffer[0];
2046 	descr = kmem_zalloc(len, KM_SLEEP);
2047 
2048 	switch (buffer[2]) {
2049 	case USB_AUDIO_INPUT_TERMINAL:
2050 		format = CS_AC_INPUT_TERM_FORMAT;
2051 		size = CS_AC_INPUT_TERM_SIZE;
2052 
2053 		break;
2054 	case USB_AUDIO_OUTPUT_TERMINAL:
2055 		format = CS_AC_OUTPUT_TERM_FORMAT;
2056 		size = CS_AC_OUTPUT_TERM_SIZE;
2057 
2058 		break;
2059 	case USB_AUDIO_MIXER_UNIT:
2060 		format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c";
2061 		size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1;
2062 
2063 		break;
2064 	case USB_AUDIO_SELECTOR_UNIT:
2065 		format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c";
2066 		size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1;
2067 
2068 		break;
2069 	case USB_AUDIO_FEATURE_UNIT:
2070 		format = CS_AC_FEATURE_UNIT_FORMAT "255c";
2071 		size = CS_AC_FEATURE_UNIT_SIZE;
2072 
2073 		break;
2074 	case USB_AUDIO_PROCESSING_UNIT:
2075 		format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c";
2076 		size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1;
2077 
2078 		break;
2079 	case USB_AUDIO_EXTENSION_UNIT:
2080 		format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c";
2081 		size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1;
2082 
2083 		break;
2084 	default:
2085 		USB_DPRINTF_L2(PRINT_MASK_ATTA,
2086 		    uacp->usb_ac_log_handle,
2087 		    "unsupported descriptor %d", buffer[2]);
2088 
2089 		/* ignore this descriptor */
2090 		kmem_free(descr, len);
2091 
2092 		return;
2093 	}
2094 
2095 	if (usb_parse_data(format, buffer, buflen, descr, len) < size) {
2096 		/* ignore this descriptor */
2097 		kmem_free(descr, len);
2098 
2099 		return;
2100 	}
2101 
2102 	switch (buffer[2]) {
2103 	case USB_AUDIO_INPUT_TERMINAL:
2104 	{
2105 		usb_audio_input_term_descr_t *d =
2106 		    (usb_audio_input_term_descr_t *)descr;
2107 
2108 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2109 		    uacp->usb_ac_log_handle,
2110 		    "input term: type=0x%x sub=0x%x termid=0x%x\n\t"
2111 		    "termtype=0x%x assoc=0x%x #ch=%d "
2112 		    "chconf=0x%x ich=0x%x iterm=0x%x",
2113 		    d->bDescriptorType, d->bDescriptorSubType,
2114 		    d->bTerminalID, d->wTerminalType,
2115 		    d->bAssocTerminal, d->bNrChannels,
2116 		    d->wChannelConfig, d->iChannelNames,
2117 		    d->iTerminal);
2118 
2119 		usb_ac_alloc_unit(uacp, d->bTerminalID);
2120 		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
2121 		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
2122 		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
2123 
2124 		break;
2125 	}
2126 	case USB_AUDIO_OUTPUT_TERMINAL:
2127 	{
2128 		usb_audio_output_term_descr_t *d =
2129 		    (usb_audio_output_term_descr_t *)descr;
2130 
2131 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2132 		    uacp->usb_ac_log_handle,
2133 		    "output term: type=0x%x sub=0x%x termid=0x%x\n\t"
2134 		    "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
2135 		    d->bDescriptorType, d->bDescriptorSubType,
2136 		    d->bTerminalID, d->wTerminalType,
2137 		    d->bAssocTerminal, d->bSourceID,
2138 		    d->iTerminal);
2139 
2140 		usb_ac_alloc_unit(uacp, d->bTerminalID);
2141 		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
2142 		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
2143 		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
2144 
2145 		break;
2146 	}
2147 	case USB_AUDIO_MIXER_UNIT:
2148 	{
2149 		usb_audio_mixer_unit_descr1_t *d =
2150 		    (usb_audio_mixer_unit_descr1_t *)descr;
2151 
2152 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2153 		    uacp->usb_ac_log_handle,
2154 		    "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2155 		    "#pins=0x%x sourceid[0]=0x%x",
2156 		    d->bDescriptorType, d->bDescriptorSubType,
2157 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2158 		usb_ac_alloc_unit(uacp, d->bUnitID);
2159 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2160 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2161 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2162 
2163 		break;
2164 	}
2165 	case USB_AUDIO_SELECTOR_UNIT:
2166 	{
2167 		usb_audio_selector_unit_descr1_t *d =
2168 		    (usb_audio_selector_unit_descr1_t *)descr;
2169 
2170 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2171 		    uacp->usb_ac_log_handle,
2172 		    "selector unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2173 		    "#pins=0x%x sourceid[0]=0x%x",
2174 		    d->bDescriptorType, d->bDescriptorSubType,
2175 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2176 		usb_ac_alloc_unit(uacp, d->bUnitID);
2177 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2178 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2179 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2180 
2181 		break;
2182 	}
2183 	case USB_AUDIO_FEATURE_UNIT:
2184 	{
2185 		usb_audio_feature_unit_descr1_t *d =
2186 		    (usb_audio_feature_unit_descr1_t *)descr;
2187 
2188 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2189 		    uacp->usb_ac_log_handle,
2190 		    "feature unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2191 		    "sourceid=0x%x size=0x%x",
2192 		    d->bDescriptorType, d->bDescriptorSubType,
2193 		    d->bUnitID, d->bSourceID, d->bControlSize);
2194 
2195 		usb_ac_alloc_unit(uacp, d->bUnitID);
2196 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2197 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2198 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2199 
2200 		break;
2201 	}
2202 	case USB_AUDIO_PROCESSING_UNIT:
2203 	{
2204 		usb_audio_processing_unit_descr1_t *d =
2205 		    (usb_audio_processing_unit_descr1_t *)descr;
2206 
2207 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2208 		    uacp->usb_ac_log_handle,
2209 		    "processing unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2210 		    "#pins=0x%x sourceid[0]=0x%x",
2211 		    d->bDescriptorType, d->bDescriptorSubType,
2212 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2213 		usb_ac_alloc_unit(uacp, d->bUnitID);
2214 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2215 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2216 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2217 
2218 		break;
2219 	}
2220 	case USB_AUDIO_EXTENSION_UNIT:
2221 	{
2222 		usb_audio_extension_unit_descr1_t *d =
2223 		    (usb_audio_extension_unit_descr1_t *)descr;
2224 
2225 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2226 		    uacp->usb_ac_log_handle,
2227 		    "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2228 		    "#pins=0x%x sourceid[0]=0x%x",
2229 		    d->bDescriptorType, d->bDescriptorSubType,
2230 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2231 		usb_ac_alloc_unit(uacp, d->bUnitID);
2232 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2233 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2234 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2235 
2236 		break;
2237 	}
2238 	default:
2239 		break;
2240 	}
2241 }
2242 
2243 
2244 /*
2245  * usb_ac_alloc_unit:
2246  *	check if the unit ID is less than max_unit in which case no
2247  *	extra entries are needed. If more entries are needed, copy over
2248  *	the existing array into a new larger array
2249  */
2250 static void
2251 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
2252 {
2253 	usb_ac_unit_list_t *old = NULL;
2254 	uint_t	max_unit;
2255 
2256 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2257 	    "usb_ac_alloc_unit: unit=%d", unit);
2258 
2259 	if (uacp->usb_ac_units) {
2260 		if (unit < uacp->usb_ac_max_unit) {
2261 			/* existing array is big enough */
2262 
2263 			return;
2264 		}
2265 		old = uacp->usb_ac_units;
2266 		max_unit = uacp->usb_ac_max_unit;
2267 	}
2268 
2269 	/* allocate two extra ones */
2270 	unit += 2;
2271 	uacp->usb_ac_max_unit = unit;
2272 	uacp->usb_ac_units = kmem_zalloc(unit *
2273 	    sizeof (usb_ac_unit_list_t), KM_SLEEP);
2274 
2275 	if (old) {
2276 		size_t len = max_unit * sizeof (usb_ac_unit_list_t);
2277 		bcopy(old, uacp->usb_ac_units, len);
2278 
2279 		kmem_free(old, len);
2280 	}
2281 }
2282 
2283 
2284 /*
2285  * usb_ac_free_all_units:
2286  *	free the entire unit list
2287  */
2288 static void
2289 usb_ac_free_all_units(usb_ac_state_t *uacp)
2290 {
2291 	uint_t	unit;
2292 	usb_ac_unit_list_t *unitp;
2293 
2294 	if (uacp->usb_ac_units == NULL) {
2295 
2296 		return;
2297 	}
2298 
2299 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2300 	    "usb_ac_alloc_unit: max_unit=%d", uacp->usb_ac_max_unit);
2301 
2302 	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
2303 		unitp = &uacp->usb_ac_units[unit];
2304 		if (unitp) {
2305 			if (unitp->acu_descriptor) {
2306 				kmem_free(unitp->acu_descriptor,
2307 				    unitp->acu_descr_length);
2308 			}
2309 		}
2310 	}
2311 
2312 	kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit *
2313 	    sizeof (usb_ac_unit_list_t));
2314 }
2315 
2316 
2317 /*
2318  * usb_ac_lookup_port_type:
2319  *	map term type to port type
2320  *	default just return LINE_IN + LINE_OUT
2321  */
2322 static int
2323 usb_ac_lookup_port_type(ushort_t termtype)
2324 {
2325 	uint_t i;
2326 
2327 	for (i = 0; ; i++) {
2328 		if (usb_ac_term_type_map[i].term_type == 0) {
2329 
2330 			break;
2331 		}
2332 
2333 		if (usb_ac_term_type_map[i].term_type == termtype) {
2334 
2335 			return (usb_ac_term_type_map[i].port_type);
2336 		}
2337 	}
2338 
2339 	return (AUDIO_LINE_IN|AUDIO_LINE_OUT);
2340 }
2341 
2342 
2343 /*
2344  * usb_ac_update_port:
2345  *	called for each terminal
2346  */
2347 /*ARGSUSED*/
2348 static int
2349 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
2350     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
2351 {
2352 	if (dir & AUDIO_PLAY) {
2353 		usb_audio_output_term_descr_t *d =
2354 		    (usb_audio_output_term_descr_t *)
2355 		    uacp->usb_ac_units[id].acu_descriptor;
2356 		uint_t port_type =
2357 		    usb_ac_lookup_port_type(d->wTerminalType);
2358 
2359 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2360 		    "usb_ac_update_port: dir=%d type=0x%x port type=%d",
2361 		    dir, d->wTerminalType, port_type);
2362 
2363 		uacp->usb_ac_output_ports |= port_type;
2364 		uacp->usb_ac_output_ports &= ~AUDIO_LINE_IN;
2365 	} else {
2366 		usb_audio_output_term_descr_t *d =
2367 		    (usb_audio_output_term_descr_t *)
2368 		    uacp->usb_ac_units[id].acu_descriptor;
2369 		uint_t port_type =
2370 		    usb_ac_lookup_port_type(d->wTerminalType);
2371 
2372 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2373 		    "usb_ac_update_port: dir=%d type=0x%x port type=%d",
2374 		    dir, d->wTerminalType, port_type);
2375 
2376 		uacp->usb_ac_input_ports |=
2377 		    usb_ac_lookup_port_type(d->wTerminalType);
2378 		uacp->usb_ac_input_ports &= ~AUDIO_LINE_OUT;
2379 	}
2380 
2381 	return (USB_SUCCESS);
2382 }
2383 
2384 
2385 /*
2386  * usb_ac_map_termtype_to_port:
2387  *	starting from a streaming termtype find all
2388  *	input or output terminals and OR into uacp->usb_ac_input_ports
2389  *	or uacp->usb_ac_output_ports;
2390  */
2391 static void
2392 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
2393 {
2394 	uint_t count = 0;
2395 	uint_t depth = 0;
2396 	uint_t search_type = (dir & AUDIO_PLAY) ?
2397 	    USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
2398 
2399 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2400 	    "usb_ac_map_term_to_port: dir=%d", dir);
2401 
2402 	(void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
2403 	    0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
2404 
2405 	ASSERT(depth == 0);
2406 }
2407 
2408 
2409 /*
2410  * usb_ac_set_port:
2411  *	find a selector port (record side only) and set the
2412  *	input to the matching pin
2413  */
2414 static uint_t
2415 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
2416 {
2417 	uint_t count = 0;
2418 	uint_t id;
2419 	uint_t depth = 0;
2420 
2421 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2422 	    "usb_ac_set_port: dir=%d port=%d", dir, port);
2423 
2424 	/* we only support the selector for the record side */
2425 	if (dir & AUDIO_RECORD) {
2426 		id = usb_ac_traverse_all_units(uacp, dir,
2427 		    USB_AUDIO_SELECTOR_UNIT, 0,
2428 		    0, USB_AC_FIND_ONE, &count, port, &depth,
2429 		    usb_ac_set_selector);
2430 
2431 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2432 		    "usb_ac_set_port: id=%d count=%d port=%d",
2433 		    id, count, port);
2434 
2435 		ASSERT(depth == 0);
2436 	}
2437 
2438 	return (USB_SUCCESS);
2439 }
2440 
2441 
2442 /*
2443  * usb_ac_match_port:
2444  *	given the requested port type, find a correspondig term type
2445  *	Called from usb_ac_traverse_all_units()
2446  */
2447 /*ARGSUSED*/
2448 static int
2449 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
2450     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
2451 {
2452 	uint_t port_type;
2453 
2454 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2455 	    "usb_ac_match_port: id=%d dir=%d port=%d",
2456 	    id, dir, arg1);
2457 
2458 	if (dir & AUDIO_PLAY) {
2459 		usb_audio_output_term_descr_t *d =
2460 		    (usb_audio_output_term_descr_t *)
2461 		    uacp->usb_ac_units[id].acu_descriptor;
2462 		port_type = usb_ac_lookup_port_type(d->wTerminalType);
2463 
2464 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2465 		    "usb_ac_match_port: "
2466 		    "dir=%d type=0x%x port_type=%d port=%d",
2467 		    dir, d->wTerminalType, port_type, arg1);
2468 	} else {
2469 		usb_audio_output_term_descr_t *d =
2470 		    (usb_audio_output_term_descr_t *)
2471 		    uacp->usb_ac_units[id].acu_descriptor;
2472 		port_type = usb_ac_lookup_port_type(d->wTerminalType);
2473 
2474 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2475 		    "usb_ac_match_port: "
2476 		    "dir=%d type=0x%x port_type=%d port=%d",
2477 		    dir, d->wTerminalType, port_type, arg1);
2478 	}
2479 
2480 	return ((port_type & arg1) ? USB_SUCCESS : USB_FAILURE);
2481 }
2482 
2483 
2484 /*
2485  * usb_ac_set_selector:
2486  *	Called from usb_ac_traverse_all_units()
2487  *	Find the correct pin and set selector to this pin
2488  */
2489 /*ARGSUSED*/
2490 static int
2491 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
2492     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
2493 {
2494 	uint_t count = 0;
2495 	uint_t unit = USB_AC_ID_NONE;
2496 	uint_t pin;
2497 	uint_t search_target =
2498 	    (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2499 	    USB_AUDIO_INPUT_TERMINAL;
2500 	usb_audio_selector_unit_descr1_t *d =
2501 	    (usb_audio_selector_unit_descr1_t *)
2502 	    uacp->usb_ac_units[id].acu_descriptor;
2503 	int n_sourceID = d->bNrInPins;
2504 	int rval = USB_FAILURE;
2505 
2506 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2507 	    "usb_ac_set_selector: id=%d dir=%d port=%d",
2508 	    id, dir, arg1);
2509 
2510 	/*
2511 	 * for each pin, find a term type that matches the
2512 	 * requested port type
2513 	 */
2514 	for (pin = 0; pin < n_sourceID; pin++) {
2515 		if (d->baSourceID[pin] == 0) {
2516 
2517 			break;
2518 		}
2519 		unit = d->baSourceID[pin];
2520 
2521 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2522 		    "usb_ac_set_selector: pin=%d unit=%d", pin, unit);
2523 
2524 		if (uacp->usb_ac_unit_type[unit] == search_target) {
2525 			if (usb_ac_match_port(uacp, unit, dir, channel,
2526 			    control, arg1, depth) == USB_SUCCESS) {
2527 
2528 				break;
2529 			} else {
2530 				unit = USB_AC_ID_NONE;
2531 
2532 				continue;
2533 			}
2534 		}
2535 
2536 		/* find units connected to this unit */
2537 		unit = usb_ac_traverse_connections(uacp, unit,
2538 		    dir, search_target, channel, control,
2539 		    USB_AC_FIND_ONE, &count, arg1, depth,
2540 		    usb_ac_match_port);
2541 
2542 		if (unit != USB_AC_ID_NONE) {
2543 
2544 			break;
2545 		}
2546 	}
2547 
2548 
2549 	if (unit != USB_AC_ID_NONE) {
2550 		mblk_t		*data;
2551 		usb_cr_t	cr;
2552 		usb_cb_flags_t	cb_flags;
2553 
2554 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2555 		    "usb_ac_set_selector: found id=%d at pin %d", unit, pin);
2556 
2557 		mutex_exit(&uacp->usb_ac_mutex);
2558 
2559 		data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
2560 
2561 		/* pins are 1-based */
2562 		*(data->b_rptr) = (char)++pin;
2563 
2564 		if (usb_pipe_sync_ctrl_xfer(
2565 		    uacp->usb_ac_dip,
2566 		    uacp->usb_ac_default_ph,
2567 		    USB_DEV_REQ_HOST_TO_DEV |
2568 		    USB_DEV_REQ_TYPE_CLASS |
2569 		    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
2570 		    USB_AUDIO_SET_CUR,		/* bRequest */
2571 		    0,				/* wValue */
2572 						/* feature unit and id */
2573 		    (id << 8)| uacp->usb_ac_ifno, /* wIndex */
2574 		    1,				/* wLength */
2575 		    &data,
2576 		    USB_ATTRS_NONE,
2577 		    &cr, &cb_flags,
2578 		    USB_FLAGS_SLEEP) == USB_SUCCESS) {
2579 			USB_DPRINTF_L3(PRINT_MASK_ALL,
2580 			    uacp->usb_ac_log_handle,
2581 			    "set current selection: %d", *data->b_rptr);
2582 
2583 			rval = USB_SUCCESS;
2584 		} else {
2585 			USB_DPRINTF_L2(PRINT_MASK_ALL,
2586 			    uacp->usb_ac_log_handle,
2587 			    "set current pin selection failed");
2588 		}
2589 		freemsg(data);
2590 
2591 		mutex_enter(&uacp->usb_ac_mutex);
2592 	} else {
2593 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2594 		    "usb_ac_set_selector: nothing found");
2595 	}
2596 
2597 	return (rval);
2598 }
2599 
2600 
2601 /*
2602  * usb_ac_set_control:
2603  *	apply func to all units of search_target type for both the
2604  *	requested channel and master channel
2605  */
2606 static uint_t
2607 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
2608 	uint_t channel, uint_t control, uint_t all_or_one,
2609 	uint_t *count, uint_t arg1,
2610 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2611 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2612 {
2613 	uint_t id;
2614 	uint_t depth = 0;
2615 
2616 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2617 	    "usb_ac_set_control: dir=%d type=%d ch=%d cntl=%d",
2618 	    dir, search_target, channel, control);
2619 
2620 
2621 	id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
2622 	    control, all_or_one, count, arg1, &depth, func);
2623 
2624 	if ((channel != 0) &&
2625 	    (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) ||
2626 	    (all_or_one == USB_AC_FIND_ALL)))  {
2627 		/* try master channel */
2628 		channel = 0;
2629 		id = usb_ac_traverse_all_units(uacp, dir, search_target,
2630 		    channel, control, all_or_one, count, arg1,
2631 		    &depth, func);
2632 	}
2633 
2634 	ASSERT(depth == 0);
2635 
2636 	return (id);
2637 }
2638 
2639 
2640 /*
2641  * usb_ac_traverse_all_units:
2642  *	traverse all units starting with all IT or OT depending on direction.
2643  *	If no unit is found for the particular channel, try master channel
2644  *	If a matching unit is found, apply the function passed by
2645  *	the caller
2646  */
2647 static uint_t
2648 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
2649 	uint_t search_target, uint_t channel, uint_t control,
2650 	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2651 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2652 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2653 {
2654 	uint_t unit, start_type, id;
2655 
2656 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2657 	    "usb_ac_traverse_all_units: "
2658 	    "dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
2659 	    dir, search_target, channel, control, all_or_one, *depth);
2660 
2661 	start_type = (dir & AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
2662 	    USB_AUDIO_OUTPUT_TERMINAL;
2663 
2664 	/* keep track of recursion */
2665 	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2666 		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2667 		    "Unit topology too complex, giving up");
2668 
2669 		return (USB_AC_ID_NONE);
2670 	}
2671 
2672 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2673 		/* is this an IT or OT? */
2674 		if (uacp->usb_ac_unit_type[unit] != start_type) {
2675 
2676 			continue;
2677 		}
2678 
2679 		/* start at streaming term types */
2680 		if (dir & AUDIO_PLAY) {
2681 			usb_audio_input_term_descr_t *d =
2682 			    uacp->usb_ac_units[unit].acu_descriptor;
2683 			if (d->wTerminalType !=
2684 			    USB_AUDIO_TERM_TYPE_STREAMING) {
2685 
2686 				continue;
2687 			}
2688 		} else {
2689 			usb_audio_output_term_descr_t *d =
2690 			    uacp->usb_ac_units[unit].acu_descriptor;
2691 			if (d->wTerminalType !=
2692 			    USB_AUDIO_TERM_TYPE_STREAMING) {
2693 
2694 				continue;
2695 			}
2696 		}
2697 
2698 		/* find units connected to this unit */
2699 		id = usb_ac_traverse_connections(uacp, unit, dir,
2700 		    search_target, channel, control, all_or_one, count,
2701 		    arg1, depth, func);
2702 
2703 		if ((all_or_one == USB_AC_FIND_ONE) &&
2704 		    (id != USB_AC_ID_NONE)) {
2705 			unit = id;
2706 
2707 			break;
2708 		}
2709 	}
2710 
2711 	(*depth)--;
2712 
2713 	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2714 }
2715 
2716 
2717 /*
2718  * usb_ac_set_monitor_gain_control:
2719  *	search for a feature unit between output terminal (OT) and
2720  *	input terminal. We are looking for a path between
2721  *	for example a microphone and a speaker through a feature unit
2722  *	and mixer
2723  */
2724 static uint_t
2725 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
2726 	uint_t search_target, uint_t channel, uint_t control,
2727 	uint_t all_or_one, uint_t *count, uint_t arg1,
2728 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2729 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2730 {
2731 	uint_t unit, id;
2732 	uint_t depth = 0;
2733 
2734 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2735 	    "usb_ac_set_monitor_gain_control: dir=%d type=%d ch=%d cntl=%d",
2736 	    dir, search_target, channel, control);
2737 
2738 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2739 		usb_audio_output_term_descr_t *d =
2740 		    uacp->usb_ac_units[unit].acu_descriptor;
2741 
2742 		/* is this an OT and not stream type? */
2743 		if ((uacp->usb_ac_unit_type[unit] ==
2744 		    USB_AUDIO_OUTPUT_TERMINAL) &&
2745 		    (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) {
2746 
2747 			/* find units connected to this unit */
2748 			id = usb_ac_traverse_connections(uacp, unit, dir,
2749 			    search_target, channel, control, all_or_one, count,
2750 			    arg1, &depth, func);
2751 
2752 			if ((all_or_one == USB_AC_FIND_ONE) &&
2753 			    (id != USB_AC_ID_NONE)) {
2754 
2755 				break;
2756 			}
2757 		}
2758 	}
2759 
2760 	ASSERT(depth == 0);
2761 
2762 	return (id);
2763 }
2764 
2765 
2766 /*
2767  * usb_ac_push/pop_unit
2768  *	add/remove unit ID to the traverse path
2769  */
2770 static void
2771 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
2772 {
2773 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2774 	    "usb_ac_push_unit_id: pushing %d at %d", unit,
2775 	    uacp->usb_ac_traverse_path_index);
2776 
2777 	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] = unit;
2778 	ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
2779 }
2780 
2781 
2782 static void
2783 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
2784 {
2785 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2786 	    "usb_ac_push_unit_id: popping %d at %d", unit,
2787 	    uacp->usb_ac_traverse_path_index);
2788 
2789 	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
2790 }
2791 
2792 
2793 /*
2794  * usb_ac_show_traverse_path:
2795  *	display entire path, just for debugging
2796  */
2797 static void
2798 usb_ac_show_traverse_path(usb_ac_state_t *uacp)
2799 {
2800 	int i;
2801 
2802 	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2803 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2804 		    "traverse path %d: unit=%d type=%d",
2805 		    i, uacp->usb_ac_traverse_path[i],
2806 		    uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]);
2807 	}
2808 }
2809 
2810 
2811 /*
2812  * usb_ac_check_path:
2813  *	check for a specified type in the traverse path
2814  */
2815 static int
2816 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type)
2817 {
2818 	int i;
2819 
2820 	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2821 		uint_t unit = uacp->usb_ac_traverse_path[i];
2822 
2823 		if (uacp->usb_ac_unit_type[unit] == type) {
2824 
2825 			return (USB_SUCCESS);
2826 		}
2827 	}
2828 
2829 	return (USB_FAILURE);
2830 }
2831 
2832 
2833 /*
2834  * usb_ac_traverse_connections:
2835  *	traverse all units and for each unit with the right type, call
2836  *	func. If the func returns a success and search == USB_AC_FIND_ONE,
2837  *	we are done. If all is set then we continue until we terminate
2838  *	and input or output terminal.
2839  *	For audio play, we traverse columns starting from an input terminal
2840  *	to an output terminal while for record we traverse rows from output
2841  *	terminal to input terminal.
2842  */
2843 static uint_t
2844 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
2845 	uint_t search_target, uint_t channel, uint_t control,
2846 	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2847 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2848 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2849 {
2850 	uint_t unit, id;
2851 	uint_t done = (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2852 	    USB_AUDIO_INPUT_TERMINAL;
2853 
2854 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2855 	    "usb_ac_traverse_connections: "
2856 	    "start=%d dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
2857 	    start_unit, dir, search_target, channel, control,
2858 	    all_or_one, *depth);
2859 
2860 	/* keep track of recursion depth */
2861 	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2862 		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2863 		    "Unit topology too complex, giving up");
2864 
2865 		return (USB_AC_ID_NONE);
2866 	}
2867 
2868 	usb_ac_push_unit_id(uacp, start_unit);
2869 
2870 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2871 		uint_t entry = (dir & AUDIO_PLAY) ?
2872 		    uacp->usb_ac_connections[unit][start_unit] :
2873 		    uacp->usb_ac_connections[start_unit][unit];
2874 
2875 		if (entry) {
2876 			USB_DPRINTF_L3(PRINT_MASK_ALL,
2877 			    uacp->usb_ac_log_handle,
2878 			    "start=%d unit=%d entry=%d type=%d "
2879 			    "done=%d found=%d",
2880 			    start_unit, unit, entry, search_target, done,
2881 			    uacp->usb_ac_unit_type[unit]);
2882 
2883 			/* did we find a matching type? */
2884 			if (uacp->usb_ac_unit_type[unit] == search_target) {
2885 				USB_DPRINTF_L3(PRINT_MASK_ALL,
2886 				    uacp->usb_ac_log_handle,
2887 				    "match: dir=%d unit=%d type=%d",
2888 				    dir, unit, search_target);
2889 
2890 				/* yes, no apply function to this unit */
2891 				if (func(uacp, unit, dir, channel,
2892 				    control, arg1, depth) == USB_SUCCESS) {
2893 					(*count)++;
2894 
2895 					USB_DPRINTF_L3(PRINT_MASK_ALL,
2896 					    uacp->usb_ac_log_handle,
2897 					    "func returned success, "
2898 					    "unit=%d all=%d", unit,
2899 					    all_or_one);
2900 
2901 					/* are we done? */
2902 					if (all_or_one == USB_AC_FIND_ONE) {
2903 
2904 						break;
2905 					}
2906 				}
2907 			}
2908 
2909 			/* did we find the terminating unit */
2910 			if (uacp->usb_ac_unit_type[unit] == done) {
2911 
2912 				continue;
2913 			}
2914 			id = usb_ac_traverse_connections(uacp, unit, dir,
2915 			    search_target, channel, control,
2916 			    all_or_one, count, arg1, depth, func);
2917 			if ((id != USB_AC_ID_NONE) &&
2918 			    (all_or_one == USB_AC_FIND_ONE)) {
2919 				unit = id;
2920 
2921 				break;
2922 			}
2923 		}
2924 	}
2925 
2926 	(*depth)--;
2927 	usb_ac_pop_unit_id(uacp, start_unit);
2928 
2929 	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2930 }
2931 
2932 
2933 /*
2934  * Event Management
2935  *
2936  * usb_ac_disconnect_event_cb:
2937  *	The device has been disconnected. we either wait for
2938  *	detach or a reconnect event.
2939  */
2940 static int
2941 usb_ac_disconnect_event_cb(dev_info_t *dip)
2942 {
2943 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2944 	    usb_ac_statep, ddi_get_instance(dip));
2945 
2946 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2947 	    "usb_ac_disconnect_event_cb: dip=0x%p", (void *)dip);
2948 
2949 	usb_ac_serialize_access(uacp);
2950 
2951 	/* setting to disconnect state will prevent replumbing */
2952 	mutex_enter(&uacp->usb_ac_mutex);
2953 	uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2954 
2955 	if (uacp->usb_ac_busy_count) {
2956 		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2957 		    "device was disconnected while busy. "
2958 		    "Data may have been lost");
2959 	}
2960 	mutex_exit(&uacp->usb_ac_mutex);
2961 
2962 	USB_DPRINTF_L3(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2963 	    "usb_ac_disconnect_event_cb: done");
2964 
2965 	usb_ac_release_access(uacp);
2966 
2967 	return (USB_SUCCESS);
2968 }
2969 
2970 
2971 /*
2972  * usb_ac_cpr_suspend:
2973  */
2974 static int
2975 usb_ac_cpr_suspend(dev_info_t *dip)
2976 {
2977 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2978 	    usb_ac_statep, ddi_get_instance(dip));
2979 
2980 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2981 	    "usb_ac_cpr_suspend: Begin");
2982 
2983 	mutex_enter(&uacp->usb_ac_mutex);
2984 	uacp->usb_ac_dev_state = USB_DEV_SUSPENDED;
2985 	mutex_exit(&uacp->usb_ac_mutex);
2986 
2987 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2988 	    "usb_ac_cpr_suspend: End");
2989 
2990 	return (USB_SUCCESS);
2991 }
2992 
2993 
2994 
2995 /*
2996  * usb_ac_reconnect_event_cb:
2997  *	The device was disconnected but this instance not detached, probably
2998  *	because the device was busy.
2999  *	if the same device, continue with restoring state
3000  *	We should either be in the unplumbed state or the plumbed open
3001  *	state.
3002  */
3003 static int
3004 usb_ac_reconnect_event_cb(dev_info_t *dip)
3005 {
3006 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
3007 	    usb_ac_statep, ddi_get_instance(dip));
3008 
3009 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
3010 	    "usb_ac_reconnect_event_cb: dip=0x%p", (void *)dip);
3011 
3012 	mutex_enter(&uacp->usb_ac_mutex);
3013 	mutex_exit(&uacp->usb_ac_mutex);
3014 
3015 	usb_ac_serialize_access(uacp);
3016 
3017 	/* check the plumbing state */
3018 	mutex_enter(&uacp->usb_ac_mutex);
3019 	uacp->usb_ac_busy_count++;
3020 	if (uacp->usb_ac_plumbing_state ==
3021 	    USB_AC_STATE_PLUMBED) {
3022 		mutex_exit(&uacp->usb_ac_mutex);
3023 		usb_ac_restore_device_state(dip, uacp);
3024 		mutex_enter(&uacp->usb_ac_mutex);
3025 	}
3026 	uacp->usb_ac_busy_count--;
3027 
3028 	if (uacp->usb_ac_busy_count) {
3029 		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
3030 		    "busy device has been reconnected");
3031 	}
3032 	mutex_exit(&uacp->usb_ac_mutex);
3033 
3034 	usb_ac_release_access(uacp);
3035 
3036 	return (USB_SUCCESS);
3037 }
3038 
3039 
3040 /*
3041  * usb_ac_cpr_resume:
3042  *	Restore device state
3043  */
3044 static void
3045 usb_ac_cpr_resume(dev_info_t *dip)
3046 {
3047 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
3048 	    usb_ac_statep, ddi_get_instance(dip));
3049 
3050 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
3051 	    "usb_ac_cpr_resume");
3052 
3053 	usb_ac_serialize_access(uacp);
3054 
3055 	usb_ac_restore_device_state(dip, uacp);
3056 
3057 	usb_ac_release_access(uacp);
3058 }
3059 
3060 
3061 /*
3062  * usb_ac_restore_device_state:
3063  *	Set original configuration of the device
3064  *	enable wrq - this starts new transactions on the control pipe
3065  */
3066 static void
3067 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp)
3068 {
3069 	usb_ac_power_t	*uacpm;
3070 	int	rval;
3071 
3072 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
3073 	    "usb_ac_restore_device_state:");
3074 
3075 	usb_ac_pm_busy_component(uacp);
3076 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3077 
3078 	/* Check if we are talking to the same device */
3079 	if (usb_check_same_device(dip, uacp->usb_ac_log_handle,
3080 	    USB_LOG_L0, PRINT_MASK_ALL,
3081 	    USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
3082 		usb_ac_pm_idle_component(uacp);
3083 
3084 		/* change the device state from suspended to disconnected */
3085 		mutex_enter(&uacp->usb_ac_mutex);
3086 		uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
3087 		mutex_exit(&uacp->usb_ac_mutex);
3088 
3089 		return;
3090 	}
3091 
3092 	mutex_enter(&uacp->usb_ac_mutex);
3093 	uacpm = uacp->usb_ac_pm;
3094 	if (uacpm) {
3095 		if (uacpm->acpm_wakeup_enabled) {
3096 			mutex_exit(&uacp->usb_ac_mutex);
3097 
3098 			if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip,
3099 			    USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
3100 
3101 				USB_DPRINTF_L4(PRINT_MASK_ATTA,
3102 				    uacp->usb_ac_log_handle,
3103 				    "usb_ac_restore_device_state: "
3104 				    "remote wakeup "
3105 				    "enable failed, rval=%d", rval);
3106 			}
3107 
3108 			mutex_enter(&uacp->usb_ac_mutex);
3109 		}
3110 	}
3111 
3112 	/* prevent unplumbing */
3113 	uacp->usb_ac_busy_count++;
3114 	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
3115 	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) {
3116 		(void) usb_ac_restore_audio_state(uacp, 0);
3117 	}
3118 	uacp->usb_ac_busy_count--;
3119 	mutex_exit(&uacp->usb_ac_mutex);
3120 	usb_ac_pm_idle_component(uacp);
3121 }
3122 
3123 
3124 /*
3125  * usb_ac_am_restore_state
3126  */
3127 static void
3128 usb_ac_am_restore_state(void *arg)
3129 {
3130 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3131 
3132 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3133 	    "usb_ac_am_restore_state: Begin");
3134 
3135 	usb_ac_serialize_access(uacp);
3136 
3137 	mutex_enter(&uacp->usb_ac_mutex);
3138 
3139 	if (uacp->usb_ac_plumbing_state ==
3140 	    USB_AC_STATE_PLUMBED_RESTORING) {
3141 		mutex_exit(&uacp->usb_ac_mutex);
3142 
3143 		/*
3144 		 * allow hid and usb_as to restore themselves
3145 		 * (some handshake would have been preferable though)
3146 		 */
3147 		delay(USB_AC_RESTORE_DELAY);
3148 
3149 		(void) audio_sup_restore_state(uacp->usb_ac_audiohdl,
3150 		    AUDIO_ALL_DEVICES, AUDIO_BOTH);
3151 
3152 		mutex_enter(&uacp->usb_ac_mutex);
3153 		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3154 	}
3155 
3156 	/* allow unplumbing */
3157 	uacp->usb_ac_busy_count--;
3158 	mutex_exit(&uacp->usb_ac_mutex);
3159 
3160 	usb_ac_release_access(uacp);
3161 
3162 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3163 	    "usb_ac_am_restore_state: End");
3164 }
3165 
3166 
3167 /*
3168  * usb_ac_restore_audio_state:
3169  */
3170 static int
3171 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
3172 {
3173 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3174 
3175 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3176 	    "usb_ac_restore_audio_state: flag=%d", flag);
3177 
3178 	switch (uacp->usb_ac_plumbing_state) {
3179 	case USB_AC_STATE_PLUMBED:
3180 		uacp->usb_ac_plumbing_state =
3181 		    USB_AC_STATE_PLUMBED_RESTORING;
3182 
3183 		break;
3184 	case USB_AC_STATE_UNPLUMBED:
3185 
3186 		return (USB_SUCCESS);
3187 	case USB_AC_STATE_PLUMBED_RESTORING:
3188 	default:
3189 
3190 		return (USB_FAILURE);
3191 	}
3192 
3193 	/*
3194 	 * increment busy_count again, it will be decremented
3195 	 * in usb_ac_am_restore_state
3196 	 */
3197 	uacp->usb_ac_busy_count++;
3198 
3199 	if (flag & USB_FLAGS_SLEEP) {
3200 		mutex_exit(&uacp->usb_ac_mutex);
3201 		usb_ac_am_restore_state((void *)uacp);
3202 		mutex_enter(&uacp->usb_ac_mutex);
3203 	} else {
3204 		mutex_exit(&uacp->usb_ac_mutex);
3205 		if (usb_async_req(uacp->usb_ac_dip,
3206 		    usb_ac_am_restore_state,
3207 		    (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) {
3208 
3209 			mutex_enter(&uacp->usb_ac_mutex);
3210 			uacp->usb_ac_busy_count--;
3211 
3212 			return (USB_FAILURE);
3213 		}
3214 		mutex_enter(&uacp->usb_ac_mutex);
3215 	}
3216 
3217 	return (USB_SUCCESS);
3218 }
3219 
3220 
3221 /*
3222  * Mixer Callback Management
3223  * NOTE: all mixer callbacks are serialized. we cannot be closed while
3224  *	we are in the middle of a callback. There needs to be a
3225  *	teardown first. We cannot be unplumbed as long as we are
3226  *	still open.
3227  *
3228  * usb_ac_setup:
3229  *	Send setup to usb_as if the first setup
3230  *	Check power is done in usb_ac_send_as_cmd()
3231  */
3232 static int
3233 usb_ac_setup(audiohdl_t ahdl, int stream, int flag)
3234 {
3235 	int	rval = AUDIO_SUCCESS;
3236 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
3237 
3238 	ASSERT(uacp != NULL);
3239 
3240 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3241 	    "usb_ac_setup: Begin ahdl=0x%p, stream=%d, flag=%d",
3242 	    (void *)ahdl, stream, flag);
3243 
3244 	mutex_enter(&uacp->usb_ac_mutex);
3245 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3246 		mutex_exit(&uacp->usb_ac_mutex);
3247 
3248 		return (AUDIO_FAILURE);
3249 	}
3250 	mutex_exit(&uacp->usb_ac_mutex);
3251 
3252 	usb_ac_serialize_access(uacp);
3253 
3254 	if (flag & AUDIO_PLAY) {
3255 		rval = usb_ac_do_setup(ahdl, stream, AUDIO_PLAY);
3256 	}
3257 
3258 	if ((rval == USB_SUCCESS) && (flag & AUDIO_RECORD)) {
3259 		rval = usb_ac_do_setup(ahdl, stream, AUDIO_RECORD);
3260 	}
3261 
3262 	usb_ac_release_access(uacp);
3263 
3264 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3265 	    "usb_ac_setup: rval=%d", rval);
3266 
3267 	return ((rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE);
3268 }
3269 
3270 
3271 /*
3272  * usb_ac_do_setup:
3273  *	Wrapper function for usb_ac_setup which can be called
3274  *	either from audio framework for usb_ac_set_format
3275  */
3276 static int
3277 usb_ac_do_setup(audiohdl_t ahdl, int stream, int flag)
3278 {
3279 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
3280 	usb_ac_plumbed_t	*plumb_infop = NULL;
3281 	usb_ac_streams_info_t	*streams_infop = NULL;
3282 	int	dir;
3283 
3284 	ASSERT(uacp != NULL);
3285 
3286 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3287 	    "usb_ac_do_setup: Begin ahdl=0x%p, stream=%d, flag=%d",
3288 	    (void *)ahdl, stream, flag);
3289 
3290 	mutex_enter(&uacp->usb_ac_mutex);
3291 
3292 	dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3293 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3294 	ASSERT(plumb_infop != NULL);
3295 
3296 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3297 	ASSERT(streams_infop != NULL);
3298 
3299 	/*
3300 	 * Handle multiple setup calls. Pass the setup call to usb_as only
3301 	 * the first time so isoc pipe will be opened only once
3302 	 */
3303 	if (streams_infop->acs_setup_teardown_count++) {
3304 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3305 		    "usb_ac_do_setup: more than one setup, cnt=%d",
3306 		    streams_infop->acs_setup_teardown_count);
3307 
3308 		mutex_exit(&uacp->usb_ac_mutex);
3309 
3310 		return (USB_SUCCESS);
3311 	}
3312 
3313 	/* Send setup command to usb_as */
3314 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SETUP, 0) !=
3315 	    USB_SUCCESS) {
3316 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3317 		    "usb_ac_do_setup: failure");
3318 
3319 		streams_infop->acs_setup_teardown_count--;
3320 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3321 
3322 		mutex_exit(&uacp->usb_ac_mutex);
3323 
3324 		return (USB_FAILURE);
3325 	}
3326 
3327 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3328 
3329 	mutex_exit(&uacp->usb_ac_mutex);
3330 
3331 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3332 	    "usb_ac_do_setup: End");
3333 
3334 	return (USB_SUCCESS);
3335 }
3336 
3337 
3338 /*
3339  * usb_ac_teardown:
3340  *	Send teardown to usb_as if the last teardown
3341  *	Check power is done in usb_ac_send_as_cmd()
3342  *	NOTE: allow teardown when disconnected
3343  */
3344 static void
3345 usb_ac_teardown(audiohdl_t ahdl, int stream, int flag)
3346 {
3347 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
3348 
3349 	ASSERT(uacp != NULL);
3350 
3351 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3352 	    "usb_ac_teardown: Begin ahdl=0x%p, stream=%d",
3353 	    (void *)ahdl, stream);
3354 
3355 	usb_ac_serialize_access(uacp);
3356 
3357 	if (flag & AUDIO_PLAY) {
3358 		usb_ac_do_teardown(ahdl, stream, AUDIO_PLAY);
3359 	}
3360 
3361 	if (flag & AUDIO_RECORD) {
3362 		usb_ac_do_teardown(ahdl, stream, AUDIO_RECORD);
3363 	}
3364 
3365 	usb_ac_release_access(uacp);
3366 
3367 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3368 	    "usb_ac_teardown: End");
3369 }
3370 
3371 
3372 /*
3373  * usb_ac_do_teardown()
3374  *	Check power is done in usb_ac_send_as_cmd()
3375  */
3376 static void
3377 usb_ac_do_teardown(audiohdl_t ahdl, int stream, int flag)
3378 {
3379 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
3380 	usb_ac_plumbed_t	*plumb_infop = NULL;
3381 	usb_ac_streams_info_t	*streams_infop = NULL;
3382 	int			dir;
3383 
3384 	ASSERT(uacp != NULL);
3385 
3386 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3387 	    "usb_ac_do_teardown: Begin ahdl=0x%p, stream=%d",
3388 	    (void *)ahdl, stream);
3389 
3390 	mutex_enter(&uacp->usb_ac_mutex);
3391 
3392 	dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3393 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3394 	ASSERT(plumb_infop != NULL);
3395 
3396 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3397 	ASSERT(streams_infop != NULL);
3398 
3399 	/* There should be at least one matching setup call */
3400 	ASSERT(streams_infop->acs_setup_teardown_count);
3401 
3402 	/*
3403 	 * Handle multiple setup/teardown calls. Pass the call to usb_as
3404 	 * only this is the last teardown so that isoc pipe is closed
3405 	 * only once
3406 	 */
3407 	if (--(streams_infop->acs_setup_teardown_count)) {
3408 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3409 		    "usb_ac_do_teardown: more than one setup/teardown, "
3410 		    "cnt=%d",
3411 		    streams_infop->acs_setup_teardown_count);
3412 
3413 		mutex_exit(&uacp->usb_ac_mutex);
3414 
3415 		return;
3416 	}
3417 
3418 	/* Send teardown command to usb_as */
3419 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_TEARDOWN,
3420 	    (void *)NULL) != USB_SUCCESS) {
3421 
3422 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3423 		    "usb_ac_do_teardown: failure");
3424 
3425 		streams_infop->acs_setup_teardown_count++;
3426 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3427 
3428 		mutex_exit(&uacp->usb_ac_mutex);
3429 
3430 		return;
3431 	}
3432 
3433 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3434 
3435 	mutex_exit(&uacp->usb_ac_mutex);
3436 
3437 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3438 	    "usb_ac_do_teardown: End");
3439 }
3440 
3441 
3442 /*
3443  * usb_ac_set_config:
3444  *	This routine will send control commands to get the max
3445  *	and min gain balance, calculate the gain to be set from the
3446  *	arguments and send another control command to set it.
3447  *	Check power is done here since we will access the default pipe
3448  */
3449 static int
3450 usb_ac_set_config(audiohdl_t ahdl, int stream, int command, int flag,
3451 	int arg1, int arg2)
3452 {
3453 	usb_ac_state_t	*uacp = audio_sup_get_private(ahdl);
3454 	char		*what;
3455 	int		rval = AUDIO_FAILURE;
3456 	uint_t		channel;
3457 	uchar_t 	n_channels = 0;
3458 	uint_t		dir, count;
3459 	short		muteval;
3460 
3461 	ASSERT(uacp != NULL);
3462 
3463 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3464 	    "usb_ac_set_config: Begin ahdl=0x%p\n\t"
3465 	    "stream=%d, cmd=%d, flag=%d, arg1=%d, arg2=%d",
3466 	    (void *)ahdl, stream, command, flag, arg1, arg2);
3467 
3468 	mutex_enter(&uacp->usb_ac_mutex);
3469 	if (uacp->usb_ac_plumbing_state < USB_AC_STATE_PLUMBED) {
3470 		mutex_exit(&uacp->usb_ac_mutex);
3471 
3472 		return (AUDIO_FAILURE);
3473 	}
3474 
3475 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3476 		mutex_exit(&uacp->usb_ac_mutex);
3477 
3478 		return (AUDIO_FAILURE);
3479 	}
3480 	mutex_exit(&uacp->usb_ac_mutex);
3481 	usb_ac_serialize_access(uacp);
3482 	mutex_enter(&uacp->usb_ac_mutex);
3483 
3484 	switch (command) {
3485 	case AM_SET_GAIN:
3486 		/*
3487 		 * Set the gain for a channel. The audio mixer calculates the
3488 		 * impact, if any, on the channel's gain.
3489 		 *
3490 		 *	0 <= gain <= AUDIO_MAX_GAIN
3491 		 *
3492 		 *	arg1 --> gain
3493 		 *	arg2 --> channel #, 0 == left, 1 == right
3494 		 */
3495 		what = "gain";
3496 		channel = ++arg2;
3497 		ASSERT(flag != AUDIO_BOTH);
3498 		dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3499 
3500 		/*
3501 		 * We service the set_config command when the device is
3502 		 * plumbed and opened.
3503 		 */
3504 		n_channels = usb_ac_get_curr_n_channels(uacp, dir);
3505 
3506 		if (channel > n_channels) {
3507 			USB_DPRINTF_L2(PRINT_MASK_ALL,
3508 			    uacp->usb_ac_log_handle,
3509 			    "usb_ac_set_config: channel(%d) passed is "
3510 			    " > n_channels(%d)", channel, n_channels);
3511 
3512 			goto done;
3513 		}
3514 		count = 0;
3515 		(void) usb_ac_set_control(uacp, dir,
3516 		    USB_AUDIO_FEATURE_UNIT, channel,
3517 		    USB_AUDIO_VOLUME_CONTROL,
3518 		    USB_AC_FIND_ALL, &count, arg1, usb_ac_set_gain);
3519 
3520 		/*
3521 		 * If feature unit id could not be found, it probably means
3522 		 * volume/gain control is not available for this device.
3523 		 * and we just return success if we haven't completed
3524 		 * the registration with the mixer yet
3525 		 */
3526 		if (count == 0) {
3527 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3528 			    "mixer=%d,	no featureID, arg1=%d",
3529 			    uacp->usb_ac_registered_with_mixer, arg1);
3530 			rval = (uacp->usb_ac_registered_with_mixer == 0) ?
3531 			    AUDIO_SUCCESS : AUDIO_FAILURE;
3532 		} else {
3533 			rval = AUDIO_SUCCESS;
3534 		}
3535 
3536 		break;
3537 	case AM_SET_PORT:
3538 		what = "port";
3539 		ASSERT(flag != AUDIO_BOTH);
3540 		dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3541 
3542 		rval = usb_ac_set_port(uacp, dir, arg1);
3543 		rval = (rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE;
3544 
3545 		break;
3546 	case AM_SET_MONITOR_GAIN:
3547 		what = "monitor gain";
3548 		channel = ++arg2;
3549 		dir = AUDIO_RECORD;
3550 
3551 		/*
3552 		 * We service the set_config command when the device is
3553 		 * plumbed and opened.
3554 		 */
3555 		n_channels = usb_ac_get_curr_n_channels(uacp, dir);
3556 
3557 		if (channel > n_channels) {
3558 			USB_DPRINTF_L2(PRINT_MASK_ALL,
3559 			    uacp->usb_ac_log_handle,
3560 			    "usb_ac_set_config: channel(%d) passed is "
3561 			    " > n_channels(%d)", channel, n_channels);
3562 
3563 			goto done;
3564 		}
3565 		count = 0;
3566 		(void) usb_ac_set_monitor_gain_control(uacp, dir,
3567 		    USB_AUDIO_INPUT_TERMINAL, channel,
3568 		    USB_AUDIO_VOLUME_CONTROL,
3569 		    USB_AC_FIND_ALL, &count, arg1,
3570 		    usb_ac_set_monitor_gain);
3571 
3572 		/*
3573 		 * always return success since we told the mixer
3574 		 * we always support this and sdtaudiocontrol displays
3575 		 * monitor gain regardless.
3576 		 */
3577 		rval = AUDIO_SUCCESS;
3578 
3579 		break;
3580 	case AM_OUTPUT_MUTE:
3581 		what = "mute";
3582 		ASSERT(flag != AUDIO_BOTH);
3583 		dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3584 
3585 		/*
3586 		 * arg1 != 0 --> mute
3587 		 * arg1 == 0 --> unmute
3588 		 * arg2 --> not used
3589 		 */
3590 		muteval = (arg1 == 0) ? USB_AUDIO_MUTE_OFF :
3591 		    USB_AUDIO_MUTE_ON;
3592 		count = 0;
3593 		(void) usb_ac_set_control(uacp, dir,
3594 		    USB_AUDIO_FEATURE_UNIT, 0,
3595 		    USB_AUDIO_MUTE_CONTROL,
3596 		    USB_AC_FIND_ALL, &count, muteval,
3597 		    usb_ac_set_mute);
3598 
3599 		rval = (count == 0) ? AUDIO_FAILURE : AUDIO_SUCCESS;
3600 
3601 		break;
3602 	case AM_MIC_BOOST:
3603 		what = "mic boost";
3604 		rval = AUDIO_SUCCESS;
3605 		break;
3606 	case AM_SET_GAIN_BAL:
3607 		what = "set gain bal";
3608 		rval = AUDIO_FAILURE;
3609 		break;
3610 	default:
3611 		what = "unknown";
3612 		rval = AUDIO_FAILURE;
3613 	}
3614 
3615 done:
3616 	mutex_exit(&uacp->usb_ac_mutex);
3617 
3618 	/* Now it's safe to release access to other routines */
3619 	usb_ac_release_access(uacp);
3620 
3621 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3622 	    "usb_ac_set_config: %s done, rval=%d", what, rval);
3623 
3624 	return (rval);
3625 }
3626 
3627 
3628 /*
3629  * usb_ac_set_monitor_gain:
3630  *	called for each output terminal which supports
3631  *	from usb_ac_traverse_connections
3632  */
3633 static int
3634 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
3635     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
3636 {
3637 	usb_audio_output_term_descr_t *d =
3638 	    uacp->usb_ac_units[unit].acu_descriptor;
3639 
3640 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3641 	    "usb_ac_set_monitor_gain: ");
3642 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3643 	    "id=%d dir=%d ch=%d cntl=%d gain=%d type=%d term type=0x%x",
3644 	    unit, dir, channel, control, gain,
3645 	    uacp->usb_ac_unit_type[unit], d->wTerminalType);
3646 
3647 	/* log how we got here */
3648 	usb_ac_push_unit_id(uacp, unit);
3649 	usb_ac_show_traverse_path(uacp);
3650 	usb_ac_pop_unit_id(uacp, unit);
3651 
3652 	/* we only care about the ITs connected to real hw inputs */
3653 	switch (d->wTerminalType) {
3654 	case USB_AUDIO_TERM_TYPE_STREAMING:
3655 
3656 		return (USB_FAILURE);
3657 
3658 	case USB_AUDIO_TERM_TYPE_DT_MICROPHONE:
3659 	case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE:
3660 	case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE:
3661 	case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY:
3662 	case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY:
3663 	default:
3664 
3665 		break;
3666 	}
3667 
3668 	/*
3669 	 * we can only do this if the microphone is mixed into the
3670 	 * audio output so look for a mixer first
3671 	 */
3672 	if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) ==
3673 	    USB_SUCCESS) {
3674 		int i, id;
3675 
3676 		/* now look for a feature unit */
3677 		for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0;
3678 		    i--) {
3679 			id = uacp->usb_ac_traverse_path[i];
3680 
3681 			switch (uacp->usb_ac_unit_type[id]) {
3682 			case USB_AUDIO_MIXER_UNIT:
3683 
3684 				/* the FU should be before the mixer */
3685 				return (USB_FAILURE);
3686 
3687 			case USB_AUDIO_FEATURE_UNIT:
3688 				/*
3689 				 * now set the volume
3690 				 */
3691 				if (usb_ac_set_gain(uacp, id, dir, channel,
3692 				    control, gain, depth) != USB_SUCCESS) {
3693 
3694 					/* try master channel */
3695 					if (usb_ac_set_gain(uacp, id, dir,
3696 					    0, control, gain, depth) !=
3697 					    USB_SUCCESS) {
3698 
3699 						return (USB_FAILURE);
3700 					}
3701 				}
3702 
3703 				return (USB_SUCCESS);
3704 
3705 			default:
3706 				continue;
3707 			}
3708 		}
3709 	}
3710 
3711 	return (USB_FAILURE);
3712 }
3713 
3714 
3715 /*
3716  * usb_ac_set_gain is called for each feature unit which supports
3717  * the requested controls from usb_ac_traverse_connections
3718  * we still need to check whether this unit supports the requested
3719  * control.
3720  */
3721 static int
3722 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
3723     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
3724 {
3725 	short max, min, current;
3726 
3727 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3728 	    "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
3729 	    featureID, dir, channel, control, gain);
3730 
3731 	if (usb_ac_feature_unit_check(uacp, featureID,
3732 	    dir, channel, control, gain, depth) != USB_SUCCESS) {
3733 
3734 		return (USB_FAILURE);
3735 	}
3736 
3737 	if ((max = usb_ac_get_maxmin_volume(uacp, channel,
3738 	    USB_AUDIO_GET_MAX, dir, featureID)) == USB_FAILURE) {
3739 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3740 		    "usb_ac_set_gain: getting max gain failed");
3741 
3742 		return (USB_FAILURE);
3743 	}
3744 
3745 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3746 	    "usb_ac_set_gain: channel %d, max=%d", channel, max);
3747 
3748 	if ((min = usb_ac_get_maxmin_volume(uacp, channel,
3749 	    USB_AUDIO_GET_MIN, dir, featureID)) == USB_FAILURE) {
3750 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3751 		    "usb_ac_set_gain: getting min gain failed");
3752 
3753 		return (USB_FAILURE);
3754 	}
3755 
3756 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3757 	    "usb_ac_set_gain: channel=%d, min=%d", channel, min);
3758 
3759 	if ((current = usb_ac_get_maxmin_volume(uacp, channel,
3760 	    USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) {
3761 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3762 		    "usb_ac_set_gain: getting cur gain failed");
3763 
3764 		return (USB_FAILURE);
3765 	}
3766 
3767 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3768 	    "usb_ac_set_gain: channel=%d, cur=%d", channel, current);
3769 
3770 	/*
3771 	 * Set the gain for a channel. The audio mixer calculates the
3772 	 * impact, if any, on the channel's gain.
3773 	 *
3774 	 *	0 <= gain <= AUDIO_MAX_GAIN
3775 	 *
3776 	 *	channel #, 0 == left, 1 == right
3777 	 */
3778 
3779 	if (gain == 0) {
3780 		gain = USB_AUDIO_VOLUME_SILENCE;
3781 	} else {
3782 		gain = max - ((max - min) * (0x100 - gain))/0x100;
3783 	}
3784 
3785 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3786 	    "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
3787 	    channel, dir, max, min, gain);
3788 
3789 	if (usb_ac_set_volume(uacp, channel, gain, dir,
3790 	    featureID) != USB_SUCCESS) {
3791 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3792 		    "usb_ac_set_gain: setting volume failed");
3793 
3794 		return (USB_FAILURE);
3795 	}
3796 
3797 	/* just curious, read it back, device may round up/down */
3798 	if ((current = usb_ac_get_maxmin_volume(uacp, channel,
3799 	    USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) {
3800 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3801 		    "usb_ac_set_gain: getting cur gain failed");
3802 	}
3803 
3804 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3805 	    "usb_ac_set_gain done: "
3806 	    "id=%d channel=%d, cur=%d gain=%d", featureID, channel,
3807 	    (ushort_t)current, (ushort_t)gain);
3808 
3809 	return (USB_SUCCESS);
3810 }
3811 
3812 
3813 /*
3814  * usb_ac_set_format
3815  *	This mixer callback initiates a command to be sent to
3816  *	usb_as to select an alternate with the passed characteristics
3817  *	and also to set the sample frequency.
3818  *	Note that this may be called when a playing is going on in
3819  *	the streaming interface. To handle that, first stop
3820  *	playing/recording, close the pipe by sending a teardown
3821  *	command, send the set_format command down and then reopen
3822  *	the pipe. Note : (1) audio framework will restart play/record
3823  *	after a set_format command. (2) Check power is done in
3824  *	usb_ac_send_as_cmd().
3825  */
3826 static int
3827 usb_ac_set_format(audiohdl_t ahdl, int stream, int flag,
3828 	int sample, int channels, int precision, int encoding)
3829 {
3830 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
3831 	usb_audio_formats_t	*format;
3832 	usb_audio_formats_t	old_format;
3833 	usb_ac_plumbed_t	*plumb_infop;
3834 	usb_ac_streams_info_t	*streams_infop = NULL;
3835 	int			old_setup_teardown_count;
3836 	int			dir;
3837 	int			rval;
3838 
3839 	ASSERT(uacp != NULL);
3840 
3841 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3842 	    "usb_ac_set_format: Begin ahdl=0x%p, stream=%d, flag=%d, "
3843 	    "sr=%d, chnls=%d, prec=%d, enc=%d", (void *)ahdl, stream, flag,
3844 	    sample, channels, precision, encoding);
3845 
3846 	mutex_enter(&uacp->usb_ac_mutex);
3847 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3848 		mutex_exit(&uacp->usb_ac_mutex);
3849 
3850 		return (AUDIO_FAILURE);
3851 	}
3852 	mutex_exit(&uacp->usb_ac_mutex);
3853 
3854 	usb_ac_serialize_access(uacp);
3855 
3856 	ASSERT(flag != AUDIO_BOTH);
3857 
3858 	mutex_enter(&uacp->usb_ac_mutex);
3859 	dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3860 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3861 	if (plumb_infop == NULL) {
3862 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3863 		    "usb_ac_set_format: no plumb info");
3864 		mutex_exit(&uacp->usb_ac_mutex);
3865 
3866 		usb_ac_release_access(uacp);
3867 
3868 		return (AUDIO_FAILURE);
3869 	}
3870 
3871 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3872 	ASSERT(streams_infop != NULL);
3873 
3874 	/* isoc pipe not open and playing is not in progress */
3875 	if (streams_infop->acs_setup_teardown_count == 0) {
3876 
3877 		mutex_exit(&uacp->usb_ac_mutex);
3878 
3879 		rval = usb_ac_send_format_cmd(ahdl, stream, dir, sample,
3880 		    channels, precision, encoding);
3881 
3882 		usb_ac_release_access(uacp);
3883 
3884 		return ((rval == USB_SUCCESS) ?
3885 		    AUDIO_SUCCESS : AUDIO_FAILURE);
3886 	}
3887 
3888 	/* isoc pipe is open and playing might be in progress */
3889 	format = &streams_infop->acs_ac_to_as_req.acr_curr_format;
3890 
3891 	/* Keep a copy of the old format */
3892 	bcopy((void *)format, (void *)&old_format,
3893 	    sizeof (usb_audio_formats_t));
3894 
3895 	ASSERT(streams_infop->acs_setup_teardown_count != 0);
3896 
3897 	old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3898 	streams_infop->acs_setup_teardown_count = 1;
3899 
3900 	mutex_exit(&uacp->usb_ac_mutex);
3901 
3902 	if (dir == AUDIO_PLAY) {
3903 		usb_ac_do_pause_play(ahdl, stream);
3904 	} else if (dir == AUDIO_RECORD) {
3905 		usb_ac_do_stop_record(ahdl, stream);
3906 	}
3907 
3908 	/* This blocks until the current isoc xfer is over */
3909 	usb_ac_do_teardown(ahdl, stream, dir);
3910 
3911 	if (usb_ac_send_format_cmd(ahdl, stream, dir, sample,
3912 	    channels, precision, encoding) != USB_SUCCESS) {
3913 		/*
3914 		 * Setting new alternate has failed, try restoring
3915 		 * old one.
3916 		 * If there is a bandwidth failure, hang around
3917 		 * till bandwidth is available. Also we know that
3918 		 * there is a matching alternate, so that can't fail.
3919 		 */
3920 		if (usb_ac_send_format_cmd(ahdl, stream, dir,
3921 		    old_format.fmt_sr, old_format.fmt_chns,
3922 		    old_format.fmt_precision, old_format.fmt_encoding) ==
3923 		    USB_FAILURE) {
3924 
3925 			/* We closed the pipe; reopen it */
3926 			(void) usb_ac_do_setup(ahdl, stream, dir);
3927 
3928 			mutex_enter(&uacp->usb_ac_mutex);
3929 			streams_infop->acs_setup_teardown_count =
3930 			    old_setup_teardown_count;
3931 			mutex_exit(&uacp->usb_ac_mutex);
3932 
3933 			usb_ac_release_access(uacp);
3934 
3935 			return (AUDIO_FAILURE);
3936 		}
3937 	}
3938 
3939 	/* This should block until successful */
3940 	(void) usb_ac_do_setup(ahdl, stream, dir);
3941 
3942 	mutex_enter(&uacp->usb_ac_mutex);
3943 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3944 	mutex_exit(&uacp->usb_ac_mutex);
3945 
3946 	usb_ac_release_access(uacp);
3947 
3948 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3949 	    "usb_ac_set_format: End");
3950 
3951 	return (AUDIO_SUCCESS);
3952 }
3953 
3954 
3955 /*
3956  * usb_ac_get_curr_n_channels:
3957  *	Return no. of channels from the current format table
3958  */
3959 static int
3960 usb_ac_get_curr_n_channels(usb_ac_state_t *uacp, int dir)
3961 {
3962 	usb_audio_formats_t *cur_fmt = usb_ac_get_curr_format(uacp, dir);
3963 
3964 	return (cur_fmt->fmt_chns);
3965 }
3966 
3967 
3968 /*
3969  * usb_ac_get_cur_format:
3970  *	Get format for the current alternate
3971  */
3972 static usb_audio_formats_t *
3973 usb_ac_get_curr_format(usb_ac_state_t *uacp, int dir)
3974 {
3975 	usb_ac_plumbed_t *plumb_infop;
3976 	usb_ac_streams_info_t *streams_infop = NULL;
3977 
3978 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3979 
3980 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3981 	if (plumb_infop == NULL) {
3982 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3983 		    "usb_ac_get_curr_format: no plumb info");
3984 
3985 		return (NULL);
3986 	}
3987 
3988 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3989 	ASSERT(streams_infop != NULL);
3990 
3991 	return (&streams_infop->acs_cur_fmt);
3992 }
3993 
3994 
3995 /*
3996  * usb_ac_send_format_cmd
3997  *	Sets format and get alternate setting that matches with
3998  *	the format from the usb_as playing or recording interface
3999  *	Send the set sample freq command down to usb_as.
4000  */
4001 static int
4002 usb_ac_send_format_cmd(audiohdl_t ahdl, int stream, int dir,
4003 	int sample, int channels, int precision, int encoding)
4004 {
4005 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
4006 	usb_audio_formats_t	*format;
4007 	usb_ac_plumbed_t	*plumb_infop = NULL;
4008 	usb_ac_streams_info_t	*streams_infop = NULL;
4009 
4010 	ASSERT(uacp != NULL);
4011 
4012 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4013 	    "usb_ac_send_format_cmd: Begin ahdl=0x%p, stream=%d, dir=%d, "
4014 	    "sr=%d, chnls=%d, prec=%d, enc=%d", (void *)ahdl, stream, dir,
4015 	    sample, channels, precision, encoding);
4016 
4017 	mutex_enter(&uacp->usb_ac_mutex);
4018 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4019 		mutex_exit(&uacp->usb_ac_mutex);
4020 
4021 		return (USB_FAILURE);
4022 	}
4023 
4024 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
4025 	ASSERT(plumb_infop);
4026 
4027 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4028 	ASSERT(streams_infop != NULL);
4029 
4030 	ASSERT(dir == AUDIO_PLAY || dir == AUDIO_RECORD);
4031 	streams_infop->acs_ac_to_as_req.acr_curr_dir = dir;
4032 
4033 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4034 	    "usb_ac_send_format_cmd: plumb_infop=0x%p, streams_infop=0x%p",
4035 	    (void *)plumb_infop, (void *)streams_infop);
4036 
4037 	format = &(streams_infop->acs_ac_to_as_req.acr_curr_format);
4038 	bzero(format, sizeof (usb_audio_formats_t));
4039 
4040 	/* save format info */
4041 	format->fmt_sr		= (uint_t)sample;
4042 	format->fmt_chns	= (uchar_t)channels;
4043 	format->fmt_precision	= (uchar_t)precision;
4044 	format->fmt_encoding	= (uchar_t)encoding;
4045 
4046 	streams_infop->acs_cur_fmt = *format;
4047 
4048 	/*
4049 	 * Set format for the streaming interface with lower write queue
4050 	 * This boils down to set_alternate  interface command in
4051 	 * usb_as and the reply mp contains the currently active
4052 	 * alternate number that is stored in the as_req structure
4053 	 */
4054 	if (usb_ac_send_as_cmd(uacp, plumb_infop,
4055 	    USB_AUDIO_SET_FORMAT, format) != USB_SUCCESS) {
4056 		USB_DPRINTF_L2(PRINT_MASK_ALL,
4057 		    uacp->usb_ac_log_handle,
4058 		    "usb_ac_send_format_cmd: failed");
4059 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4060 		mutex_exit(&uacp->usb_ac_mutex);
4061 
4062 		return (USB_FAILURE);
4063 	} else {
4064 		/* alternate number stored and reply mp freed */
4065 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4066 	}
4067 
4068 	/* Set the sample rate */
4069 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SET_SAMPLE_FREQ,
4070 	    &sample) != USB_SUCCESS) {
4071 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4072 		    "usb_ac_send_format_cmd: setting format failed");
4073 
4074 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4075 		mutex_exit(&uacp->usb_ac_mutex);
4076 
4077 		return (USB_FAILURE);
4078 	}
4079 
4080 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4081 
4082 	mutex_exit(&uacp->usb_ac_mutex);
4083 
4084 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4085 	    "usb_ac_send_format_cmd: End");
4086 
4087 	return (USB_SUCCESS);
4088 }
4089 
4090 
4091 /*
4092  * usb_ac_start_play
4093  *	Send a start_play command down to usb_as
4094  *	Check power is done in usb_ac_send_as_cmd()
4095  */
4096 static int
4097 usb_ac_start_play(audiohdl_t ahdl, int stream)
4098 {
4099 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
4100 	usb_audio_formats_t	*cur_fmt;
4101 	usb_ac_plumbed_t	*plumb_infop = NULL;
4102 	int			dir, samples;
4103 	usb_audio_play_req_t	play_req;
4104 	usb_ac_streams_info_t	*streams_infop = NULL;
4105 
4106 	ASSERT(uacp != NULL);
4107 
4108 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4109 	    "usb_ac_start_play: Begin ahdl=0x%p, stream=%d",
4110 	    (void *)ahdl, stream);
4111 
4112 	mutex_enter(&uacp->usb_ac_mutex);
4113 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4114 		mutex_exit(&uacp->usb_ac_mutex);
4115 
4116 		return (AUDIO_FAILURE);
4117 	}
4118 	mutex_exit(&uacp->usb_ac_mutex);
4119 
4120 	usb_ac_serialize_access(uacp);
4121 
4122 	mutex_enter(&uacp->usb_ac_mutex);
4123 
4124 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY);
4125 	ASSERT(plumb_infop);
4126 
4127 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4128 	ASSERT(streams_infop != NULL);
4129 
4130 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4131 	    "usb_ac_start_play: plumb_infop=0x%p, streams_infop=0x%p",
4132 	    (void *)plumb_infop, (void *)streams_infop);
4133 
4134 	dir = streams_infop->acs_ac_to_as_req.acr_curr_dir;
4135 	ASSERT(dir == AUDIO_PLAY);
4136 
4137 	cur_fmt = &streams_infop->acs_ac_to_as_req.acr_curr_format;
4138 
4139 	/* Check for continuous sample rate done in usb_as */
4140 	samples = cur_fmt->fmt_sr * cur_fmt->fmt_chns /
4141 	    uacp->usb_ac_am_ad_info.ad_play.ad_int_rate;
4142 	if (samples & cur_fmt->fmt_chns) {
4143 		samples++;
4144 	}
4145 
4146 	play_req.up_samples = samples;
4147 	play_req.up_handle = ahdl;
4148 
4149 	/* Send setup command to usb_as */
4150 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_PLAY,
4151 	    (void *)&play_req) != USB_SUCCESS) {
4152 
4153 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4154 		    "usb_ac_start_play: failure");
4155 
4156 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4157 		mutex_exit(&uacp->usb_ac_mutex);
4158 
4159 		usb_ac_release_access(uacp);
4160 
4161 		return (AUDIO_FAILURE);
4162 	}
4163 
4164 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4165 	mutex_exit(&uacp->usb_ac_mutex);
4166 
4167 	usb_ac_release_access(uacp);
4168 
4169 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4170 	    "usb_ac_start_play: End");
4171 
4172 	return (AUDIO_SUCCESS);
4173 }
4174 
4175 
4176 /*
4177  * usb_ac_pause_play:
4178  *	Wrapper function for usb_ac_do_pause_play and gets
4179  *	called from mixer framework.
4180  */
4181 static void
4182 usb_ac_pause_play(audiohdl_t ahdl, int stream)
4183 {
4184 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4185 
4186 	ASSERT(uacp != NULL);
4187 
4188 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4189 	    "usb_ac_pause_play: Begin ahdl=0x%p, stream=%d",
4190 	    (void *)ahdl, stream);
4191 
4192 	mutex_enter(&uacp->usb_ac_mutex);
4193 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4194 		mutex_exit(&uacp->usb_ac_mutex);
4195 
4196 		return;
4197 	}
4198 	mutex_exit(&uacp->usb_ac_mutex);
4199 
4200 	usb_ac_serialize_access(uacp);
4201 	usb_ac_do_pause_play(ahdl, stream);
4202 	usb_ac_release_access(uacp);
4203 
4204 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4205 	    "usb_ac_pause_play: End");
4206 }
4207 
4208 /*
4209  * usb_ac_do_pause_play:
4210  *	Send a pause_play command to usb_as.
4211  *	Check power is done in usb_ac_send_as_cmd()
4212  */
4213 static void
4214 usb_ac_do_pause_play(audiohdl_t ahdl, int stream)
4215 {
4216 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4217 	usb_ac_plumbed_t	*plumb_infop = NULL;
4218 	usb_ac_streams_info_t	*streams_infop = NULL;
4219 
4220 	ASSERT(uacp != NULL);
4221 
4222 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4223 	    "usb_ac_do_pause_play: Begin ahdl=0x%p, stream=%d",
4224 	    (void *)ahdl, stream);
4225 
4226 	mutex_enter(&uacp->usb_ac_mutex);
4227 
4228 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY);
4229 	ASSERT(plumb_infop);
4230 
4231 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4232 	ASSERT(streams_infop != NULL);
4233 
4234 	/* Send setup command to usb_as */
4235 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_PAUSE_PLAY,
4236 	    (void *)NULL) != USB_SUCCESS) {
4237 
4238 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4239 		    "usb_ac_do_pause_play: failure");
4240 
4241 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4242 	}
4243 
4244 	mutex_exit(&uacp->usb_ac_mutex);
4245 
4246 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4247 	    "usb_ac_do_pause_play: End");
4248 }
4249 
4250 
4251 /*
4252  * usb_ac_stop_play:
4253  *	Wrapper function for usb_ac_pause_play	and gets
4254  *	called from mixer framework.
4255  */
4256 static void
4257 usb_ac_stop_play(audiohdl_t ahdl, int stream)
4258 {
4259 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4260 
4261 	ASSERT(uacp != NULL);
4262 
4263 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4264 	    "usb_ac_stop_play: Begin ahdl=0x%p, stream=%d",
4265 	    (void *)ahdl, stream);
4266 
4267 	usb_ac_pause_play(ahdl, stream);
4268 
4269 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4270 	    "usb_ac_stop_play: End");
4271 }
4272 
4273 
4274 /*
4275  * usb_ac_start_record:
4276  *	Sends a start record command down to usb_as.
4277  *	Check power is done in usb_ac_send_as_cmd()
4278  */
4279 static int
4280 usb_ac_start_record(audiohdl_t ahdl, int stream)
4281 {
4282 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4283 	usb_ac_plumbed_t	*plumb_infop = NULL;
4284 	usb_ac_streams_info_t	*streams_infop = NULL;
4285 
4286 	ASSERT(uacp != NULL);
4287 
4288 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4289 	    "usb_ac_start_record: Begin ahdl=0x%p, stream=%d",
4290 	    (void *)ahdl, stream);
4291 
4292 	mutex_enter(&uacp->usb_ac_mutex);
4293 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4294 		mutex_exit(&uacp->usb_ac_mutex);
4295 
4296 		return (AUDIO_FAILURE);
4297 	}
4298 	mutex_exit(&uacp->usb_ac_mutex);
4299 
4300 	usb_ac_serialize_access(uacp);
4301 
4302 	mutex_enter(&uacp->usb_ac_mutex);
4303 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD);
4304 	ASSERT(plumb_infop);
4305 
4306 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4307 	ASSERT(streams_infop != NULL);
4308 
4309 	/* Send setup command to usb_as */
4310 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_RECORD,
4311 	    (void *)&ahdl) != USB_SUCCESS) {
4312 
4313 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4314 		    "usb_ac_start_record: failure");
4315 
4316 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4317 		mutex_exit(&uacp->usb_ac_mutex);
4318 
4319 		usb_ac_release_access(uacp);
4320 
4321 		return (AUDIO_FAILURE);
4322 	}
4323 
4324 	mutex_exit(&uacp->usb_ac_mutex);
4325 
4326 	usb_ac_release_access(uacp);
4327 
4328 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4329 	    "usb_ac_start_record: End");
4330 
4331 	return (AUDIO_SUCCESS);
4332 }
4333 
4334 
4335 /*
4336  * usb_ac_stop_record:
4337  *	Wrapper function for usb_ac_do_stop_record and is
4338  *	called form mixer framework.
4339  */
4340 static void
4341 usb_ac_stop_record(audiohdl_t ahdl, int stream)
4342 {
4343 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4344 
4345 	ASSERT(uacp != NULL);
4346 
4347 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4348 	    "usb_ac_stop_record: Begin ahdl=0x%p, stream=%d",
4349 	    (void *)ahdl, stream);
4350 
4351 	usb_ac_serialize_access(uacp);
4352 	usb_ac_do_stop_record(ahdl, stream);
4353 	usb_ac_release_access(uacp);
4354 
4355 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4356 	    "usb_ac_stop_record: End");
4357 }
4358 
4359 
4360 /*
4361  * usb_ac_do_stop_record:
4362  *	Sends a stop_record command down.
4363  *	Check power is done in usb_ac_send_as_cmd()
4364  */
4365 static void
4366 usb_ac_do_stop_record(audiohdl_t ahdl, int stream)
4367 {
4368 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4369 	usb_ac_plumbed_t	*plumb_infop = NULL;
4370 	usb_ac_streams_info_t	*streams_infop = NULL;
4371 
4372 	ASSERT(uacp != NULL);
4373 
4374 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4375 	    "usb_ac_do_stop_record: Begin ahdl=0x%p, stream=%d",
4376 	    (void *)ahdl, stream);
4377 
4378 	mutex_enter(&uacp->usb_ac_mutex);
4379 
4380 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD);
4381 	ASSERT(plumb_infop != NULL);
4382 
4383 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4384 	ASSERT(streams_infop != NULL);
4385 
4386 	/* Send setup command to usb_as */
4387 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_STOP_RECORD,
4388 	    NULL) != USB_SUCCESS) {
4389 
4390 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4391 		    "usb_ac_do_stop_record: failure");
4392 
4393 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4394 	}
4395 
4396 	mutex_exit(&uacp->usb_ac_mutex);
4397 
4398 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4399 	    "usb_ac_do_stop_record: End");
4400 }
4401 
4402 
4403 /*
4404  * Helper Functions for Mixer callbacks
4405  *
4406  * usb_ac_get_maxmin_volume:
4407  *	Send USBA command down to get the maximum or minimum gain balance
4408  *	Calculate min or max gain balance and return that. Return
4409  *	USB_FAILURE for failure cases
4410  */
4411 static int
4412 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
4413     int dir, int feature_unitID)
4414 {
4415 	mblk_t		*data = NULL;
4416 	short		max_or_min;
4417 	usb_cr_t	cr;
4418 	usb_cb_flags_t	cb_flags;
4419 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4420 	    "usb_ac_get_maxmin_volume: channel=%d, cmd=%d dir=%d",
4421 	    channel, cmd, dir);
4422 
4423 	mutex_exit(&uacp->usb_ac_mutex);
4424 
4425 	if (usb_pipe_sync_ctrl_xfer(
4426 	    uacp->usb_ac_dip,
4427 	    uacp->usb_ac_default_ph,
4428 	    USB_DEV_REQ_DEV_TO_HOST |
4429 	    USB_DEV_REQ_TYPE_CLASS |
4430 	    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
4431 	    cmd,			/* bRequest */
4432 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
4433 					/* feature unit and id */
4434 	    (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
4435 	    2,				/* wLength */
4436 	    &data,
4437 	    USB_ATTRS_NONE,
4438 	    &cr, &cb_flags,
4439 	    USB_FLAGS_SLEEP) != USB_SUCCESS) {
4440 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4441 		    "usb_ac_get_maxmin_volume: failed, "
4442 		    "cr=%d, cb=0x%x cmd=%d, data=0x%p",
4443 		    cr, cb_flags, cmd, (void *)data);
4444 
4445 		freemsg(data);
4446 		mutex_enter(&uacp->usb_ac_mutex);
4447 
4448 		return (USB_FAILURE);
4449 	}
4450 
4451 	mutex_enter(&uacp->usb_ac_mutex);
4452 	ASSERT((data->b_wptr - data->b_rptr) == 2);
4453 
4454 	max_or_min = (*(data->b_rptr+1) << 8) | *data->b_rptr;
4455 
4456 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4457 	    "usb_ac_get_maxmin_volume: max_or_min=0x%x", max_or_min);
4458 
4459 	freemsg(data);
4460 
4461 	return (max_or_min);
4462 }
4463 
4464 
4465 /*
4466  * usb_ac_set_volume:
4467  *	Send USBA command down to set the gain balance
4468  */
4469 static int
4470 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
4471     int feature_unitID)
4472 {
4473 	mblk_t		*data = NULL;
4474 	usb_cr_t	cr;
4475 	usb_cb_flags_t	cb_flags;
4476 	int		rval = USB_FAILURE;
4477 
4478 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4479 	    "usb_ac_set_volume: channel=%d gain=%d dir=%d FU=%d",
4480 	    channel, gain, dir, feature_unitID);
4481 
4482 	mutex_exit(&uacp->usb_ac_mutex);
4483 
4484 	/* Construct the mblk_t from gain for sending to USBA */
4485 	data = allocb_wait(4, BPRI_HI, STR_NOSIG, NULL);
4486 
4487 	*(data->b_wptr++) = (char)gain;
4488 	*(data->b_wptr++) = (char)(gain >> 8);
4489 
4490 	if ((rval = usb_pipe_sync_ctrl_xfer(
4491 	    uacp->usb_ac_dip,
4492 	    uacp->usb_ac_default_ph,
4493 	    USB_DEV_REQ_HOST_TO_DEV |
4494 	    USB_DEV_REQ_TYPE_CLASS |
4495 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
4496 	    USB_AUDIO_SET_CUR,			/* bRequest */
4497 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
4498 						/* feature unit and id */
4499 	    (feature_unitID << 8) | uacp->usb_ac_ifno,	/* wIndex */
4500 	    2,					/* wLength */
4501 	    &data, 0,
4502 	    &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
4503 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4504 		    "usb_ac_set_volume: failed, cr=%d cb=0x%x",
4505 		    cr, cb_flags);
4506 	}
4507 
4508 	freemsg(data);
4509 	mutex_enter(&uacp->usb_ac_mutex);
4510 
4511 	return (rval);
4512 }
4513 
4514 
4515 /*
4516  * usb_ac_set_mute is called for each unit that supports the
4517  * requested control from usb_ac_traverse_connections
4518  */
4519 static int
4520 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
4521     uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
4522 {
4523 	mblk_t		*data;
4524 	usb_cr_t	cr;
4525 	usb_cb_flags_t	cb_flags;
4526 	int		rval = USB_FAILURE;
4527 
4528 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4529 	    "usb_ac_set_mute: muteval=0x%x, dir=%d", muteval, dir);
4530 
4531 	if (usb_ac_feature_unit_check(uacp, featureID,
4532 	    dir, channel, control, 0, depth) != USB_SUCCESS) {
4533 
4534 		return (USB_FAILURE);
4535 	}
4536 
4537 	mutex_exit(&uacp->usb_ac_mutex);
4538 
4539 	/* Construct the mblk_t for sending to USBA */
4540 	data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
4541 	*(data->b_wptr++) = (char)muteval;
4542 
4543 	if ((rval = usb_pipe_sync_ctrl_xfer(
4544 	    uacp->usb_ac_dip,
4545 	    uacp->usb_ac_default_ph,
4546 	    USB_DEV_REQ_HOST_TO_DEV |
4547 	    USB_DEV_REQ_TYPE_CLASS |
4548 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
4549 	    USB_AUDIO_SET_CUR,			/* bRequest */
4550 	    (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
4551 						/* feature unit and id */
4552 	    (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
4553 	    1,					/* wLength */
4554 	    &data,
4555 	    0,					/* attributes */
4556 	    &cr, &cb_flags, 0)) != USB_SUCCESS) {
4557 
4558 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4559 		    "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
4560 	}
4561 
4562 	freemsg(data);
4563 	mutex_enter(&uacp->usb_ac_mutex);
4564 
4565 	return (rval);
4566 }
4567 
4568 
4569 /*
4570  * usb_ac_send_as_cmd:
4571  *	Allocate message blk, send a command down to usb_as,
4572  *	wait for the reply and free the message
4573  *
4574  *	although not really needed to raise power if sending to as
4575  *	it seems better to ensure that both interfaces are at full power
4576  */
4577 static int
4578 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_ac_plumbed_t *plumb_infop,
4579     int cmd, void *arg)
4580 {
4581 	mblk_t		*mp = NULL;
4582 	struct iocblk	*iocp;
4583 	queue_t 	*lwq = plumb_infop->acp_lwq;
4584 	usb_ac_streams_info_t *streams_infop;
4585 	int		error = USB_FAILURE;
4586 
4587 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4588 	ASSERT(plumb_infop != NULL);
4589 
4590 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4591 	ASSERT(streams_infop != NULL);
4592 
4593 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4594 	    "usb_ac_send_as_cmd: Begin lwq=0x%p, cmd=0x%x, arg=0x%p",
4595 	    (void *)lwq, cmd, arg);
4596 
4597 	if (!canputnext(lwq)) {
4598 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4599 		    "usb_ac_send_as_cmd: canputnext failed");
4600 
4601 		return (error);
4602 	}
4603 
4604 	/*
4605 	 * Allocate mblk for a particular command
4606 	 */
4607 	switch (cmd) {
4608 	case USB_AUDIO_SET_FORMAT:
4609 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4610 		    sizeof (usb_audio_formats_t));
4611 		break;
4612 	case USB_AUDIO_TEARDOWN:
4613 	case USB_AUDIO_STOP_RECORD:
4614 	case USB_AUDIO_PAUSE_PLAY:
4615 	case USB_AUDIO_SETUP:
4616 		mp = usb_ac_allocate_req_mblk(uacp, cmd, NULL, 0);
4617 		break;
4618 	case USB_AUDIO_START_RECORD:
4619 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4620 		    sizeof (audiohdl_t *));
4621 		break;
4622 	case USB_AUDIO_SET_SAMPLE_FREQ:
4623 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4624 		    sizeof (int));
4625 		break;
4626 	case USB_AUDIO_START_PLAY:
4627 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4628 		    sizeof (usb_audio_play_req_t));
4629 		break;
4630 	default:
4631 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4632 		    "usb_ac_send_as_cmd: unknown cmd=%d", cmd);
4633 
4634 		return (error);
4635 	}
4636 
4637 	if (mp == NULL) {
4638 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4639 		    "usb_ac_send_as_cmd: can't get mblk to send cmd down");
4640 
4641 		return (error);
4642 	}
4643 
4644 	/*
4645 	 * Set wait flag and send message down; we have made sure
4646 	 * before that canputnext succeeds. Note mp will be freed down
4647 	 */
4648 	streams_infop->acs_ac_to_as_req.acr_wait_flag = 1;
4649 
4650 	mutex_exit(&uacp->usb_ac_mutex);
4651 	putnext(lwq, mp);
4652 	mutex_enter(&uacp->usb_ac_mutex);
4653 
4654 	/*
4655 	 * Wait for the response; reply will arrive through rput()
4656 	 * M_CTL and the cv_wait will be signaled there and wait flag
4657 	 * will be reset
4658 	 */
4659 	while (streams_infop->acs_ac_to_as_req.acr_wait_flag) {
4660 #ifndef DEBUG
4661 		cv_wait(&streams_infop->acs_ac_to_as_req.acr_cv,
4662 		    &uacp->usb_ac_mutex);
4663 #else
4664 		clock_t tm = ddi_get_lbolt() +
4665 		    drv_usectohz(usb_ac_wait_timeout);
4666 		int rval;
4667 
4668 		rval = cv_timedwait(&streams_infop->acs_ac_to_as_req.acr_cv,
4669 		    &uacp->usb_ac_mutex, tm);
4670 
4671 		if (streams_infop->acs_ac_to_as_req.acr_wait_flag) {
4672 			if (rval == -1) {
4673 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4674 				    uacp->usb_ac_log_handle,
4675 				    "usb_ac_send_as_cmd:"
4676 				    " timeout happen before cmd complete.");
4677 			} else {
4678 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4679 				    uacp->usb_ac_log_handle,
4680 				    "usb_ac_send_as_cmd:"
4681 				    " not signaled by USB_AS_PLUMBED.");
4682 			}
4683 		}
4684 #endif
4685 	}
4686 
4687 	/* Wait is over, get the reply data */
4688 	mp = streams_infop->acs_ac_to_as_req.acr_reply_mp;
4689 	ASSERT(mp != NULL);
4690 
4691 	iocp = (struct iocblk *)mp->b_rptr;
4692 
4693 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4694 	    "usb_ac_send_as_cmd: db_type=0x%x cmd=0x%x",
4695 	    mp->b_datap->db_type, iocp->ioc_cmd);
4696 
4697 	switch (mp->b_datap->db_type) {
4698 	case M_CTL:
4699 		switch (iocp->ioc_cmd) {
4700 		case USB_AUDIO_SET_FORMAT:
4701 			/*
4702 			 * This command sets mixer format data
4703 			 * and returns alternate setting that matches
4704 			 */
4705 			ASSERT(mp->b_cont != NULL);
4706 			ASSERT((mp->b_cont->b_wptr - mp->b_cont->b_rptr) ==
4707 			    sizeof (int));
4708 			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4709 			    "alternate returned %d",
4710 			    *((int *)(mp->b_cont->b_rptr)));
4711 
4712 			streams_infop->acs_ac_to_as_req.acr_curr_format.
4713 			    fmt_alt = *((int *)(mp->b_cont->b_rptr));
4714 
4715 			/*FALLTHROUGH*/
4716 		case USB_AUDIO_SET_SAMPLE_FREQ:
4717 		case USB_AUDIO_SETUP:
4718 		case USB_AUDIO_START_PLAY:
4719 		case USB_AUDIO_PAUSE_PLAY:
4720 		case USB_AUDIO_START_RECORD:
4721 		case USB_AUDIO_STOP_RECORD:
4722 		case USB_AUDIO_TEARDOWN:
4723 			error = USB_SUCCESS;
4724 			break;
4725 		default:
4726 			break;
4727 		}
4728 		break;
4729 	case M_ERROR:
4730 	default:
4731 		error = USB_FAILURE;
4732 	}
4733 
4734 	if (mp) {
4735 		usb_ac_free_mblk(mp);
4736 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4737 	}
4738 
4739 	return (error);
4740 }
4741 
4742 
4743 /*
4744  * usb_ac_allocate_req_mblk:
4745  *	Allocate a message block with the specified M_CTL cmd,
4746  *	The 2nd mblk contains the data for the command with a length len
4747  */
4748 static mblk_t *
4749 usb_ac_allocate_req_mblk(usb_ac_state_t *uacp, int cmd, void *buf, uint_t len)
4750 {
4751 	mblk_t	*mp, *mp2;
4752 	struct iocblk *mctlmsg;
4753 
4754 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4755 	    "usb_ac_allocate_req_mblk: cmd=0x%x, buf=0x%p, len=%d",
4756 	    cmd, buf, len);
4757 
4758 	mp = allocb_wait(sizeof (struct iocblk), BPRI_HI, STR_NOSIG, NULL);
4759 	mp->b_datap->db_type = M_CTL;
4760 	mctlmsg = (struct iocblk *)mp->b_datap->db_base;
4761 	mctlmsg->ioc_cmd = cmd;
4762 	mctlmsg->ioc_count = len;
4763 
4764 	mp->b_wptr = mp->b_wptr + sizeof (struct iocblk);
4765 
4766 	if ((len == 0) || (buf == NULL)) {
4767 
4768 		return (mp);
4769 	}
4770 
4771 	mp2 = allocb_wait(len, BPRI_HI, STR_NOSIG, NULL);
4772 	mp->b_cont = mp2;
4773 	bcopy(buf, mp->b_cont->b_datap->db_base, len);
4774 	mp->b_cont->b_wptr = mp->b_cont->b_wptr + len;
4775 
4776 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4777 	    "usb_ac_allocate_req_mblk: mp=0x%p", (void *)mp);
4778 
4779 	return (mp);
4780 }
4781 
4782 
4783 /*
4784  * usb_ac_free_mblk:
4785  *	Free the message block
4786  */
4787 static void
4788 usb_ac_free_mblk(mblk_t *mp)
4789 {
4790 	if (mp->b_cont) {
4791 		freemsg(mp->b_cont);
4792 		mp->b_cont = NULL;
4793 	}
4794 	freemsg(mp);
4795 }
4796 
4797 
4798 /*
4799  * usb_ac_serialize/release_access:
4800  */
4801 static void
4802 usb_ac_serialize_access(usb_ac_state_t	*uacp)
4803 {
4804 	(void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
4805 }
4806 
4807 static void
4808 usb_ac_release_access(usb_ac_state_t *uacp)
4809 {
4810 	usb_release_access(uacp->usb_ac_ser_acc);
4811 }
4812 
4813 
4814 static void
4815 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
4816 {
4817 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
4818 
4819 	if (usb_ac_statep->usb_ac_pm != NULL) {
4820 		mutex_enter(&usb_ac_statep->usb_ac_mutex);
4821 		usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
4822 
4823 		USB_DPRINTF_L4(PRINT_MASK_PM,
4824 		    usb_ac_statep->usb_ac_log_handle,
4825 		    "usb_ac_pm_busy_component: %d",
4826 		    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
4827 
4828 		mutex_exit(&usb_ac_statep->usb_ac_mutex);
4829 
4830 		if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
4831 		    DDI_SUCCESS) {
4832 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
4833 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
4834 
4835 			USB_DPRINTF_L2(PRINT_MASK_PM,
4836 			    usb_ac_statep->usb_ac_log_handle,
4837 			    "usb_ac_pm_busy_component failed: %d",
4838 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
4839 
4840 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
4841 		}
4842 	}
4843 }
4844 
4845 
4846 static void
4847 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
4848 {
4849 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
4850 
4851 	if (usb_ac_statep->usb_ac_pm != NULL) {
4852 		if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
4853 		    DDI_SUCCESS) {
4854 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
4855 			ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
4856 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
4857 
4858 			USB_DPRINTF_L4(PRINT_MASK_PM,
4859 			    usb_ac_statep->usb_ac_log_handle,
4860 			    "usb_ac_pm_idle_component: %d",
4861 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
4862 
4863 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
4864 		}
4865 	}
4866 }
4867