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