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