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