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