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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * AUDIO CONTROL Driver: usb_ac is a streams multiplexor that sits
30  * on top of usb_as and hid and is responsible for
31  * (1) providing the entry points to audio mixer framework, (2) passing
32  * streams messages to and from usb_as and hid and (3) processing
33  * control messages that it can handle.
34  *
35  * 1. Mixer entry points are: usb_ac_setup(), usb_ac_teardown(),
36  *	usb_ac_set_config(), usb_ac_set_format(), usb_ac_start_play(),
37  *	usb_ac_pause_play(), usb_ac_stop_play, usb_ac_start_record(),
38  *	usb_ac_stop_record().
39  * 2. usb_ac is a streams driver that passes streams messages down to
40  *	usb_as that selects the correct alternate with passed format
41  *	parameters, sets sample frequency, starts play/record, stops
42  *	play/record, pause play/record, open/close isoc pipe.
43  * 3. usb_ac handles the set_config command through the default pipe
44  *	of sound control interface of the audio device in a synchronous
45  *	manner.
46  *
47  * Serialization: usb_ac being a streams driver and having the requirement
48  * of making non-blockings calls (USBA or streams or mixer) needs to drop
49  * mutexes over such calls. But at the same time, a competing thread
50  * can't be allowed to interfere with (1) pipe, (2) streams state.
51  * So we need some kind of serialization among the asynchronous
52  * threads that can run in the driver. The serialization is mostly
53  * needed to avoid races among open/close/events/power entry points
54  * etc. Once a routine takes control, it checks if the resource (pipe or
55  * stream or dev state) is still accessible. If so, it proceeds with
56  * its job and until it completes, no other thread requiring the same
57  * resource can run.
58  *
59  * PM model in usb_ac: Raise power during attach. If a device is not at full
60  * power, raise power in the entry points. After the command is over,
61  * pm_idle_component() is called. The power is lowered in detach().
62  *
63  * locking: Warlock is not aware of the automatic locking mechanisms for
64  * streams drivers.
65  */
66 #include <sys/usb/usba/usbai_version.h>
67 #include <sys/usb/usba.h>
68 #include <sys/stropts.h>
69 #include <sys/sunndi.h>
70 #include <sys/ndi_impldefs.h>
71 #include <sys/strsubr.h>
72 
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 %I%",		/* 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", 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", 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 		    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", q, uacp->usb_ac_busy_count);
982 
983 	mutex_exit(&uacp->usb_ac_mutex);
984 
985 	return (0);
986 }
987 
988 
989 /*
990  * usb_ac_close :
991  *	Close entry point
992  */
993 /*ARGSUSED*/
994 static int
995 usb_ac_close(queue_t *q, int flag, cred_t *credp)
996 {
997 	dev_t dev = audio_sup_get_qptr_dev(q);
998 	int minor = getminor(dev);
999 	int instance = audio_sup_get_qptr_instance(q);
1000 	usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance);
1001 	int rval;
1002 
1003 	mutex_enter(&uacp->usb_ac_mutex);
1004 
1005 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1006 	    "usb_ac_close: Begin q=0x%p, opencount=%d",
1007 	    q, uacp->usb_ac_busy_count);
1008 
1009 	/* closing the mux? */
1010 	if (minor == uacp->usb_ac_mux_minor) {
1011 		USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1012 		    "usb_ac_close: closing mux plumbing stream");
1013 		mutex_exit(&uacp->usb_ac_mutex);
1014 
1015 		/* Wait till all activity in the default pipe has drained */
1016 		usb_ac_serialize_access(uacp);
1017 		usb_ac_release_access(uacp);
1018 
1019 		audio_sup_free_qptr(q);
1020 		qprocsoff(q);
1021 
1022 		return (0);
1023 	}
1024 
1025 	mutex_exit(&uacp->usb_ac_mutex);
1026 
1027 	rval = audio_sup_close(q, flag, credp);
1028 
1029 	if (rval != 0) {
1030 		USB_DPRINTF_L2(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1031 		    "audio_sup_close fails %d", rval);
1032 
1033 		return (rval);
1034 	}
1035 
1036 	mutex_enter(&uacp->usb_ac_mutex);
1037 
1038 	/* normal streams closing */
1039 	ASSERT(uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED);
1040 
1041 	uacp->usb_ac_busy_count --;
1042 
1043 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle,
1044 	    "usb_ac_close: End rval=%d q=0x%p, opencount=%d",
1045 	    rval, q, uacp->usb_ac_busy_count);
1046 
1047 	mutex_exit(&uacp->usb_ac_mutex);
1048 
1049 	usb_ac_pm_idle_component(uacp);
1050 
1051 	return (0);
1052 }
1053 
1054 
1055 /*
1056  * usb_ac_uwput:
1057  *	write put entry point for the upper mux. Only PLUMB/UNPLUMB ioctls
1058  *	are processed here. All other ioctls are passed to audio_sup routines
1059  *	for further processing.
1060  */
1061 static int
1062 usb_ac_uwput(queue_t *q, mblk_t *mp)
1063 {
1064 	int instance = audio_sup_get_qptr_instance(q);
1065 	usb_ac_state_t	*uacp = ddi_get_soft_state(usb_ac_statep, instance);
1066 	int error = DDI_SUCCESS;
1067 
1068 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1069 	    "usb_ac_uwput: q=0x%p, mp=0x%p", q, mp);
1070 
1071 	ASSERT(mp != NULL);
1072 	ASSERT(mp->b_datap != NULL);
1073 
1074 	mutex_enter(&uacp->usb_ac_mutex);
1075 	if (uacp->usb_ac_wq == q) {
1076 		ASSERT(mp->b_datap->db_type == M_IOCTL);
1077 
1078 		mutex_exit(&uacp->usb_ac_mutex);
1079 
1080 		/* ioctl from plumbing thread (namely P_LINK) */
1081 		usb_ac_plumb_ioctl(q, mp);
1082 
1083 		return (error);
1084 	}
1085 	mutex_exit(&uacp->usb_ac_mutex);
1086 
1087 	/* Pass to audio_sup routine */
1088 	(void) audio_sup_wput(q, mp);
1089 
1090 	return (error);
1091 }
1092 
1093 
1094 /*
1095  * usb_ac_lrput:
1096  *	read put entry point for the lower mux. Get the response from the
1097  *	lower module, signal usb_ac_send_as_cmd(), the thread that is waiting
1098  *	for a response to a message sent earlier anbd pass the response
1099  *	message	block.
1100  */
1101 static int
1102 usb_ac_lrput(queue_t *q, mblk_t *mp)
1103 {
1104 	int instance = audio_sup_get_qptr_instance(q);
1105 	usb_ac_state_t	*uacp;
1106 	int error = DDI_SUCCESS;
1107 	usb_ac_plumbed_t *plumb_infop;
1108 	usb_ac_streams_info_t *streams_infop = NULL;
1109 	int	val;
1110 	char	val1;
1111 	struct iocblk *iocp;
1112 
1113 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
1114 
1115 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1116 	    "usb_ac_lrput: q=0x%p, mp=0x%p, instance=%d", q, mp, instance);
1117 	ASSERT(mp != NULL);
1118 
1119 	mutex_enter(&uacp->usb_ac_mutex);
1120 	plumb_infop = usb_ac_get_plumb_info_from_lrq(uacp, q);
1121 	ASSERT(plumb_infop != NULL);
1122 
1123 	switch (mp->b_datap->db_type) {
1124 	case M_CTL:
1125 	case M_ERROR:
1126 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1127 		    "M_CTL/M_ERROR");
1128 
1129 		switch (plumb_infop->acp_driver) {
1130 		case USB_AS_PLUMBED:
1131 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1132 			    "reply from usb_as, lrq=0x%p", q);
1133 			streams_infop = (usb_ac_streams_info_t *)
1134 							plumb_infop->acp_data;
1135 			ASSERT(streams_infop != NULL);
1136 			streams_infop->acs_ac_to_as_req.acr_reply_mp = mp;
1137 			streams_infop->acs_ac_to_as_req.acr_wait_flag = 0;
1138 			cv_signal(&streams_infop->acs_ac_to_as_req.acr_cv);
1139 
1140 			break;
1141 		case USB_AH_PLUMBED:
1142 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1143 			    "M_CTL from hid, lrq=0x%p", q);
1144 
1145 			iocp = (struct iocblk *)mp->b_rptr;
1146 			ASSERT(mp->b_cont != NULL);
1147 
1148 			if (uacp->usb_ac_registered_with_mixer) {
1149 
1150 				val1 = *((char *)mp->b_cont->b_rptr);
1151 				val = (int)val1;
1152 
1153 				USB_DPRINTF_L4(PRINT_MASK_ALL,
1154 				    uacp->usb_ac_log_handle, "val1=0x%x(%d),"
1155 				    "val=0x%x(%d)", val1, val1, val, val);
1156 
1157 				switch (iocp->ioc_cmd) {
1158 				/* Handle relative volume change */
1159 				case USB_AUDIO_VOL_CHANGE:
1160 					/* prevent unplumbing */
1161 					uacp->usb_ac_busy_count++;
1162 					if (uacp->usb_ac_plumbing_state ==
1163 					    USB_AC_STATE_PLUMBED) {
1164 						mutex_exit(&uacp->usb_ac_mutex);
1165 						(void) am_hw_state_change(
1166 						    uacp->usb_ac_audiohdl,
1167 						    AM_HWSC_SET_GAIN_DELTA,
1168 						    AUDIO_PLAY, val,
1169 						    AUDIO_NO_SLEEP);
1170 						mutex_enter(&uacp->
1171 								usb_ac_mutex);
1172 					}
1173 					uacp->usb_ac_busy_count--;
1174 					/* FALLTHRU */
1175 				case USB_AUDIO_MUTE:
1176 				default:
1177 					freemsg(mp);
1178 					break;
1179 				}
1180 			} else {
1181 				freemsg(mp);
1182 			}
1183 
1184 			break;
1185 		default:
1186 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1187 			    "M_CTL from unknown module(%s)",
1188 			    ddi_driver_name(plumb_infop->acp_dip));
1189 			freemsg(mp);
1190 		}
1191 
1192 		break;
1193 	default:
1194 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1195 		    "Unknown type=%d", mp->b_datap->db_type);
1196 		usb_ac_free_mblk(mp);
1197 	}
1198 	mutex_exit(&uacp->usb_ac_mutex);
1199 
1200 	/*
1201 	 * Nobody is waiting; nothing to send up.
1202 	 */
1203 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1204 	    "usb_ac_lrput: done");
1205 
1206 	return (error);
1207 }
1208 
1209 
1210 /*
1211  * Power Management
1212  * usb_ac_power:
1213  *	power entry point
1214  */
1215 static int
1216 usb_ac_power(dev_info_t *dip, int comp, int level)
1217 {
1218 	int		instance = ddi_get_instance(dip);
1219 	usb_ac_state_t	*uacp;
1220 	usb_ac_power_t	*uacpm;
1221 	int		rval = DDI_FAILURE;
1222 
1223 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
1224 
1225 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1226 	    "usb_ac_power: comp=%d level=%d", comp, level);
1227 
1228 	mutex_enter(&uacp->usb_ac_mutex);
1229 	uacpm = uacp->usb_ac_pm;
1230 
1231 	if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) {
1232 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1233 		    "usb_ac_power: illegal level=%d pwr_states=%d",
1234 		    level, uacpm->acpm_pwr_states);
1235 
1236 		goto done;
1237 	}
1238 
1239 	switch (level) {
1240 	case USB_DEV_OS_PWR_OFF:
1241 		rval = usb_ac_pwrlvl0(uacp);
1242 		break;
1243 	case USB_DEV_OS_PWR_1:
1244 		rval = usb_ac_pwrlvl1(uacp);
1245 		break;
1246 	case USB_DEV_OS_PWR_2:
1247 		rval = usb_ac_pwrlvl2(uacp);
1248 		break;
1249 	case USB_DEV_OS_FULL_PWR:
1250 		rval = usb_ac_pwrlvl3(uacp);
1251 		break;
1252 	}
1253 
1254 done:
1255 	mutex_exit(&uacp->usb_ac_mutex);
1256 
1257 	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
1258 }
1259 
1260 
1261 /*
1262  * functions to handle power transition for various levels
1263  * These functions act as place holders to issue USB commands
1264  * to the devices to change their power levels
1265  * Level 0 = Device is powered off
1266  * Level 3 = Device if full powered
1267  * Level 1,2 = Intermediate power level of the device as implemented
1268  *	by the hardware.
1269  * Note that Level 0 is OS power-off and Level 3 is OS full-power.
1270  */
1271 static int
1272 usb_ac_pwrlvl0(usb_ac_state_t *uacp)
1273 {
1274 	usb_ac_power_t	*uacpm;
1275 	int		rval;
1276 
1277 	uacpm = uacp->usb_ac_pm;
1278 
1279 	switch (uacp->usb_ac_dev_state) {
1280 	case USB_DEV_ONLINE:
1281 		/* Deny the powerdown request if the device is busy */
1282 		if (uacpm->acpm_pm_busy != 0) {
1283 
1284 			return (USB_FAILURE);
1285 		}
1286 
1287 		/* Issue USB D3 command to the device here */
1288 		rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip);
1289 		ASSERT(rval == USB_SUCCESS);
1290 
1291 		uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN;
1292 		uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF;
1293 
1294 		/* FALLTHRU */
1295 	case USB_DEV_DISCONNECTED:
1296 	case USB_DEV_SUSPENDED:
1297 	case USB_DEV_PWRED_DOWN:
1298 	default:
1299 		return (USB_SUCCESS);
1300 	}
1301 }
1302 
1303 
1304 /* ARGSUSED */
1305 static int
1306 usb_ac_pwrlvl1(usb_ac_state_t *uacp)
1307 {
1308 	int		rval;
1309 
1310 	/* Issue USB D2 command to the device here */
1311 	rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip);
1312 	ASSERT(rval == USB_SUCCESS);
1313 
1314 	return (USB_FAILURE);
1315 }
1316 
1317 
1318 /* ARGSUSED */
1319 static int
1320 usb_ac_pwrlvl2(usb_ac_state_t *uacp)
1321 {
1322 	int		rval;
1323 
1324 	rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip);
1325 	ASSERT(rval == USB_SUCCESS);
1326 
1327 	return (USB_FAILURE);
1328 }
1329 
1330 
1331 static int
1332 usb_ac_pwrlvl3(usb_ac_state_t *uacp)
1333 {
1334 	usb_ac_power_t	*uacpm;
1335 	int		rval;
1336 
1337 	uacpm = uacp->usb_ac_pm;
1338 
1339 	switch (uacp->usb_ac_dev_state) {
1340 	case USB_DEV_PWRED_DOWN:
1341 		/* Issue USB D0 command to the device here */
1342 		rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip);
1343 		ASSERT(rval == USB_SUCCESS);
1344 
1345 		uacp->usb_ac_dev_state = USB_DEV_ONLINE;
1346 		uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1347 		/* FALLTHRU */
1348 	case USB_DEV_ONLINE:
1349 		/* we are already in full power */
1350 
1351 		/* FALLTHRU */
1352 	case USB_DEV_DISCONNECTED:
1353 	case USB_DEV_SUSPENDED:
1354 
1355 		return (USB_SUCCESS);
1356 	default:
1357 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1358 		    "usb_ac_pwerlvl3: Illegal dev_state");
1359 
1360 		return (USB_FAILURE);
1361 	}
1362 }
1363 
1364 
1365 static void
1366 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
1367 {
1368 	usb_ac_power_t	*uacpm;
1369 	uint_t		pwr_states;
1370 
1371 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1372 	    "usb_ac_create_pm_components: begin");
1373 
1374 	/* Allocate the state structure */
1375 	uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP);
1376 	uacp->usb_ac_pm = uacpm;
1377 	uacpm->acpm_state = uacp;
1378 	uacpm->acpm_capabilities = 0;
1379 	uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1380 
1381 	if (usb_create_pm_components(dip, &pwr_states) ==
1382 	    USB_SUCCESS) {
1383 		if (usb_handle_remote_wakeup(dip,
1384 		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1385 			uacpm->acpm_wakeup_enabled = 1;
1386 
1387 			USB_DPRINTF_L4(PRINT_MASK_PM,
1388 			    uacp->usb_ac_log_handle,
1389 			    "remote Wakeup enabled");
1390 		}
1391 		uacpm->acpm_pwr_states = (uint8_t)pwr_states;
1392 		(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1393 	} else {
1394 		if (uacpm) {
1395 			kmem_free(uacpm,  sizeof (usb_ac_power_t));
1396 			uacp->usb_ac_pm = NULL;
1397 		}
1398 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1399 		    "pm not enabled");
1400 	}
1401 
1402 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1403 	    "usb_ac_create_pm_components: end");
1404 }
1405 
1406 
1407 /*
1408  * usb_ac_plumb_ioctl:
1409  *	IOCTL issued from plumbing thread (only P_LINK_LH/P_UNLINK for now
1410  *	caused by ldi_ioctl). Maybe we will need to use this function
1411  *	to issue other IOCTLS to children in future from plumbing thread
1412  */
1413 static void
1414 usb_ac_plumb_ioctl(queue_t *q, mblk_t *mp)
1415 {
1416 	int		instance = audio_sup_get_qptr_instance(q);
1417 	usb_ac_state_t	*uacp = ddi_get_soft_state(usb_ac_statep, instance);
1418 	struct iocblk	*iocp;
1419 	struct linkblk	*linkp;
1420 	int		n;
1421 	usb_ac_streams_info_t *streams_infop;
1422 
1423 	ASSERT(uacp != NULL);
1424 	ASSERT(mp != NULL);
1425 	ASSERT(mp->b_cont != NULL);
1426 
1427 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1428 	    "usb_ac_plumb_ioctl, q=0x%p mp=0x%p instance=%d",
1429 	    q, mp, instance);
1430 
1431 	iocp = (struct iocblk *)mp->b_rptr;
1432 	mutex_enter(&uacp->usb_ac_mutex);
1433 	n = uacp->usb_ac_current_plumbed_index;
1434 
1435 	switch (iocp->ioc_cmd) {
1436 	case I_PLINK:
1437 		linkp = (struct linkblk *)mp->b_cont->b_rptr;
1438 
1439 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1440 		    "LINK ioctl, index=%d linkblk ptr=0x%p", n, linkp);
1441 
1442 		/*
1443 		 * We keep track of the module that is being
1444 		 * currently plumbed through usb_ac_current_plumbed_index
1445 		 * to the plumb structure array. We set the lwq field
1446 		 * of the plumb structure here.
1447 		 */
1448 		ASSERT(uacp->usb_ac_plumbed[n].acp_lwq == NULL);
1449 		uacp->usb_ac_plumbed[n].acp_lwq = linkp->l_qbot;
1450 		uacp->usb_ac_plumbed[n].acp_lrq = RD(linkp->l_qbot);
1451 
1452 		audio_sup_set_qptr(uacp->usb_ac_plumbed[n].acp_lrq,
1453 		    uacp->usb_ac_dev, (void *)uacp);
1454 
1455 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1456 		    "index=%d lwq=0x%p lrq=0x%p", n, linkp->l_qbot,
1457 		    RD(linkp->l_qbot));
1458 		break;
1459 	case I_UNLINK:
1460 	case I_PUNLINK:
1461 		linkp = (struct linkblk *)mp->b_cont->b_rptr;
1462 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1463 		    "UNLINK ioctl, linkblk ptr=0x%p", linkp);
1464 
1465 		audio_sup_free_qptr(RD(linkp->l_qbot));
1466 		uacp->usb_ac_dev = 0;
1467 
1468 		if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) {
1469 
1470 			/*
1471 			 * we bzero the streams info and plumbed structure
1472 			 * since there is no guarantee that the next plumbing
1473 			 * will be identical
1474 			 */
1475 			streams_infop = (usb_ac_streams_info_t *)
1476 					uacp->usb_ac_plumbed[n].acp_data;
1477 			cv_destroy(&(streams_infop->acs_ac_to_as_req.acr_cv));
1478 
1479 			/* bzero the relevant plumbing structure */
1480 			bzero(streams_infop, sizeof (usb_ac_streams_info_t));
1481 		}
1482 		bzero(&uacp->usb_ac_plumbed[n], sizeof (usb_ac_plumbed_t));
1483 
1484 		iocp->ioc_count = 0;
1485 		break;
1486 	default:
1487 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1488 		    "Unknown ioctl, cmd=%d", iocp->ioc_cmd);
1489 		iocp->ioc_error = EINVAL;
1490 		mutex_exit(&uacp->usb_ac_mutex);
1491 
1492 		goto iocnak;
1493 	}
1494 
1495 	mutex_exit(&uacp->usb_ac_mutex);
1496 
1497 	/*
1498 	 * Common exit path for calls that return a positive
1499 	 * acknowledgment with a return value of 0.
1500 	 */
1501 	iocp->ioc_rval = 0;
1502 	iocp->ioc_error = 0;
1503 	mp->b_datap->db_type = M_IOCACK;
1504 	qreply(q, mp);
1505 
1506 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1507 	    "usb_ac_plumb_ioctl: End (ACK)");
1508 
1509 	return;
1510 
1511 iocnak:
1512 
1513 	iocp->ioc_rval = 0;
1514 	mp->b_datap->db_type = M_IOCNAK;
1515 	qreply(q, mp);
1516 
1517 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1518 	    "usb_ac_plumb_ioctl: End: (NAK)");
1519 }
1520 
1521 
1522 /*
1523  * usb_ac_get_plumb_info:
1524  *	Get plumb_info pointer that matches module "name"
1525  *	If name = "usb_as", match the direction also (record or play)
1526  */
1527 static usb_ac_plumbed_t *
1528 usb_ac_get_plumb_info(usb_ac_state_t *uacp, char *name, uchar_t reg_play_type)
1529 {
1530 	int			n;
1531 	usb_ac_plumbed_t	*plumb_infop = NULL;
1532 	usb_as_registration_t	*asreg;
1533 	usb_ac_streams_info_t	*asinfo;
1534 
1535 	for (n = 0; n < USB_AC_MAX_PLUMBED; n++) {
1536 		if (uacp->usb_ac_plumbed[n].acp_dip == NULL) {
1537 			continue;
1538 		}
1539 		if (strcmp(ddi_driver_name(uacp->
1540 		    usb_ac_plumbed[n].acp_dip), name) != 0) {
1541 			continue;
1542 		}
1543 		if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) {
1544 			asinfo = uacp->usb_ac_plumbed[n].acp_data;
1545 			asreg = asinfo->acs_streams_reg;
1546 			/* Match direction */
1547 			if (asreg->reg_mode & reg_play_type) {
1548 				break;
1549 			}
1550 		} else if (uacp->usb_ac_plumbed[n].acp_driver ==
1551 		    USB_AH_PLUMBED) {
1552 			break;
1553 		}
1554 	}
1555 
1556 	if (n < USB_AC_MAX_PLUMBED) {
1557 		plumb_infop = &uacp->usb_ac_plumbed[n];
1558 	}
1559 
1560 	return (plumb_infop);
1561 }
1562 
1563 
1564 /*
1565  * usb_ac_get_pinfo_from_lrq:
1566  *	Get plumb_info pointer that matches the lrq passed
1567  */
1568 static usb_ac_plumbed_t *
1569 usb_ac_get_plumb_info_from_lrq(usb_ac_state_t *uacp, queue_t *lrq)
1570 {
1571 	int	n;
1572 
1573 	for (n = 0; n < USB_AC_MAX_PLUMBED; n++) {
1574 		if (uacp->usb_ac_plumbed[n].acp_lrq == lrq) {
1575 
1576 			return (&uacp->usb_ac_plumbed[n]);
1577 		}
1578 	}
1579 
1580 	return (NULL);
1581 }
1582 
1583 
1584 /*
1585  * usb_ac_get_featureID:
1586  *	find out if there is at least one feature unit that supports
1587  *	the request controls.
1588  *	Return featureID or USB_AC_ID_NONE.
1589  */
1590 static uint_t
1591 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir,
1592     uint_t channel, uint_t control)
1593 {
1594 	uint_t count = 0;
1595 
1596 	return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT,
1597 		    channel, control, USB_AC_FIND_ONE, &count, 0,
1598 		    usb_ac_feature_unit_check));
1599 }
1600 
1601 
1602 /*
1603  * usb_ac_feature_unit_check:
1604  *	check if a feature unit can support the required channel
1605  *	and control combination. Return USB_SUCCESS or USB_FAILURE.
1606  *	Called for each matching unit from usb_ac_traverse_connections.
1607  */
1608 /*ARGSUSED*/
1609 static int
1610 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
1611     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1612 {
1613 	usb_audio_feature_unit_descr1_t *feature_descrp;
1614 	int				n_channel_controls;
1615 
1616 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1617 	    "usb_ac_feature_unit_check: ID=%d ch=%d cntrl=%d",
1618 	    featureID, channel, control);
1619 
1620 	ASSERT((featureID >= 0) && (featureID < uacp->usb_ac_max_unit));
1621 
1622 	/*
1623 	 * check if this control is supported on this channel
1624 	 */
1625 	feature_descrp = (usb_audio_feature_unit_descr1_t *)
1626 		uacp->usb_ac_units[featureID].acu_descriptor;
1627 	ASSERT(feature_descrp->bUnitID == featureID);
1628 
1629 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1630 	    "bControlSize=%d", feature_descrp->bControlSize);
1631 
1632 	if (feature_descrp->bControlSize == 0) {
1633 		featureID = USB_AC_ID_NONE;
1634 	} else {
1635 		uint_t index;
1636 
1637 		n_channel_controls = (feature_descrp->bLength -
1638 		    offsetof(usb_audio_feature_unit_descr1_t,
1639 		    bmaControls))/feature_descrp->bControlSize;
1640 
1641 		USB_DPRINTF_L3(PRINT_MASK_ALL,
1642 		    uacp->usb_ac_log_handle,
1643 		    "#controls: %d index=%d", n_channel_controls,
1644 		    feature_descrp->bControlSize * channel);
1645 
1646 		if (channel > n_channel_controls) {
1647 			featureID = USB_AC_ID_NONE;
1648 		} else {
1649 			/*
1650 			 * we only support MUTE and VOLUME
1651 			 * which are in the first byte
1652 			 */
1653 			index = feature_descrp->bControlSize *
1654 						channel;
1655 
1656 			USB_DPRINTF_L3(PRINT_MASK_ALL,
1657 			    uacp->usb_ac_log_handle,
1658 			    "control: 0x%x",
1659 			    feature_descrp->bmaControls[index]);
1660 
1661 			if ((feature_descrp->bmaControls[index] &
1662 			    control) == 0) {
1663 				featureID = USB_AC_ID_NONE;
1664 			}
1665 		}
1666 	}
1667 
1668 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1669 	    "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
1670 	    dir, featureID);
1671 
1672 	return ((featureID != USB_AC_ID_NONE) ?
1673 		USB_SUCCESS : USB_FAILURE);
1674 }
1675 
1676 
1677 /*
1678  * Descriptor Management
1679  *
1680  * usb_ac_handle_descriptors:
1681  *	extract interesting descriptors from the config cloud
1682  */
1683 static int
1684 usb_ac_handle_descriptors(usb_ac_state_t *uacp)
1685 {
1686 	int			rest, len, index;
1687 	int			rval = USB_FAILURE;
1688 	usb_audio_cs_if_descr_t descr;
1689 	usb_client_dev_data_t	*dev_data = uacp->usb_ac_dev_data;
1690 	usb_alt_if_data_t	*altif_data;
1691 	usb_cvs_data_t		*cvs;
1692 
1693 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1694 	    "config=%d, interface=%d",
1695 	    dev_data->dev_curr_cfg - &dev_data->dev_cfg[0],
1696 	    dev_data->dev_curr_if);
1697 
1698 	altif_data = &dev_data->dev_curr_cfg->
1699 			cfg_if[dev_data->dev_curr_if].if_alt[0];
1700 
1701 	uacp->usb_ac_ifno	= dev_data->dev_curr_if;
1702 	uacp->usb_ac_if_descr	= altif_data->altif_descr;
1703 
1704 	/* find USB_AUDIO_CS_INTERFACE type descriptor */
1705 	for (index = 0; index < altif_data->altif_n_cvs; index++) {
1706 		cvs = &altif_data->altif_cvs[index];
1707 		if (cvs->cvs_buf == NULL) {
1708 			continue;
1709 		}
1710 		if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) {
1711 			break;
1712 		}
1713 	}
1714 
1715 	if (index == altif_data->altif_n_cvs) {
1716 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1717 		    "cannot find descriptor type %d", USB_AUDIO_CS_INTERFACE);
1718 
1719 		return (rval);
1720 	}
1721 
1722 	len = usb_parse_data(
1723 		CS_AC_IF_HEADER_FORMAT,
1724 		cvs->cvs_buf, cvs->cvs_buf_len,
1725 		(void *)&descr, sizeof (usb_audio_cs_if_descr_t));
1726 
1727 	/* is this a sane header descriptor */
1728 	if (!((len >= CS_AC_IF_HEADER_SIZE) &&
1729 	    (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
1730 	    (descr.bDescriptorSubType == USB_AUDIO_HEADER))) {
1731 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1732 		    "invalid header");
1733 
1734 		return (rval);
1735 	}
1736 
1737 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1738 	    "header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
1739 	    "total=0x%x InCol=0x%x",
1740 	    descr.bDescriptorType,
1741 	    descr.bDescriptorSubType,
1742 	    descr.bcdADC,
1743 	    descr.wTotalLength,
1744 	    descr.blnCollection);
1745 
1746 	/*
1747 	 * we read descriptors by index and store them in ID array.
1748 	 * the actual parsing is done in usb_ac_add_unit_descriptor()
1749 	 */
1750 	rest = descr.wTotalLength - descr.bLength;
1751 	for (index++; rest > 0; index++) {
1752 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1753 		    "index=%d rest=%d", index, rest);
1754 
1755 		cvs = &altif_data->altif_cvs[index];
1756 		if (cvs->cvs_buf == NULL) {
1757 			continue;
1758 		}
1759 
1760 		/* add to ID array */
1761 		usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf,
1762 						cvs->cvs_buf_len);
1763 		rest -= cvs->cvs_buf[0];
1764 	}
1765 	rval = USB_SUCCESS;
1766 
1767 	usb_ac_setup_connections(uacp);
1768 
1769 	/* determine port types */
1770 	usb_ac_map_termtype_to_port(uacp, AUDIO_PLAY);
1771 	usb_ac_map_termtype_to_port(uacp, AUDIO_RECORD);
1772 
1773 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1774 	    "input port types=0x%x output port types =0x%x",
1775 	    uacp->usb_ac_input_ports, uacp->usb_ac_output_ports);
1776 
1777 
1778 	return (rval);
1779 }
1780 
1781 
1782 /*
1783  * usb_ac_setup_connections:
1784  *	build a matrix reflecting all connections
1785  */
1786 static void
1787 usb_ac_setup_connections(usb_ac_state_t *uacp)
1788 {
1789 	usb_ac_unit_list_t	*units = uacp->usb_ac_units;
1790 	uchar_t			*a, **p, i, unit;
1791 	size_t			a_len, p_len;
1792 
1793 	/* allocate array for unit types for quick reference */
1794 	uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit,
1795 							KM_SLEEP);
1796 	/* allocate array for traversal path */
1797 	uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit,
1798 							KM_SLEEP);
1799 
1800 
1801 	/* allocate the connection matrix and set it up */
1802 	a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit;
1803 	p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *);
1804 
1805 	/* trick to create a 2 dimensional array */
1806 	a = kmem_zalloc(a_len, KM_SLEEP);
1807 	p = kmem_zalloc(p_len, KM_SLEEP);
1808 	for (i = 0; i < uacp->usb_ac_max_unit; i++) {
1809 		p[i] = a + i * uacp->usb_ac_max_unit;
1810 	}
1811 	uacp->usb_ac_connections = p;
1812 	uacp->usb_ac_connections_len = p_len;
1813 	uacp->usb_ac_connections_a = a;
1814 	uacp->usb_ac_connections_a_len = a_len;
1815 
1816 	/* traverse all units and set connections */
1817 	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1818 
1819 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1820 		    "traversing unit=0x%x type=0x%x",
1821 		    unit, units[unit].acu_type);
1822 
1823 		/* store type in the first unused column */
1824 		uacp->usb_ac_unit_type[unit] = units[unit].acu_type;
1825 
1826 		/* save the Unit ID in the unit it points to */
1827 		switch (units[unit].acu_type) {
1828 		case USB_AUDIO_FEATURE_UNIT:
1829 		{
1830 			usb_audio_feature_unit_descr1_t *d =
1831 					units[unit].acu_descriptor;
1832 
1833 			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1834 			    "sourceID=0x%x type=0x%x", d->bSourceID,
1835 			    units[d->bSourceID].acu_type);
1836 
1837 			if (d->bSourceID != 0) {
1838 				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1839 				p[unit][d->bSourceID] = B_TRUE;
1840 			}
1841 
1842 			break;
1843 		}
1844 		case USB_AUDIO_OUTPUT_TERMINAL:
1845 		{
1846 			usb_audio_output_term_descr_t *d =
1847 					units[unit].acu_descriptor;
1848 
1849 			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1850 			    "sourceID=0x%x type=0x%x", d->bSourceID,
1851 			    units[d->bSourceID].acu_type);
1852 
1853 			if (d->bSourceID != 0) {
1854 				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1855 				p[unit][d->bSourceID] = B_TRUE;
1856 			}
1857 
1858 			break;
1859 		}
1860 		case USB_AUDIO_MIXER_UNIT:
1861 		{
1862 			usb_audio_mixer_unit_descr1_t *d =
1863 					units[unit].acu_descriptor;
1864 			int n_sourceID = d->bNrInPins;
1865 			int id;
1866 
1867 			for (id = 0; id < n_sourceID; id++) {
1868 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1869 				    uacp->usb_ac_log_handle,
1870 				    "sourceID=0x%x type=0x%x c=%d",
1871 				    d->baSourceID[id],
1872 				    units[d->baSourceID[id]].acu_type,
1873 				    p[unit][d->baSourceID[id]]);
1874 
1875 				if (d->baSourceID[id] != 0) {
1876 					ASSERT(p[unit][d->baSourceID[id]] ==
1877 					    B_FALSE);
1878 					p[unit][d->baSourceID[id]] = B_TRUE;
1879 				}
1880 			}
1881 
1882 			break;
1883 		}
1884 		case USB_AUDIO_SELECTOR_UNIT:
1885 		{
1886 			usb_audio_selector_unit_descr1_t *d =
1887 					units[unit].acu_descriptor;
1888 			int n_sourceID = d->bNrInPins;
1889 			int id;
1890 
1891 			for (id = 0; id < n_sourceID; id++) {
1892 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1893 				    uacp->usb_ac_log_handle,
1894 				    "sourceID=0x%x type=0x%x",
1895 				    d->baSourceID[id],
1896 				    units[d->baSourceID[id]].acu_type);
1897 
1898 				if (d->baSourceID[id] != 0) {
1899 					ASSERT(p[unit][d->baSourceID[id]] ==
1900 					    B_FALSE);
1901 					p[unit][d->baSourceID[id]] = B_TRUE;
1902 				}
1903 			}
1904 
1905 			break;
1906 		}
1907 		case USB_AUDIO_PROCESSING_UNIT:
1908 		{
1909 			usb_audio_mixer_unit_descr1_t *d =
1910 					units[unit].acu_descriptor;
1911 			int n_sourceID = d->bNrInPins;
1912 			int id;
1913 
1914 			for (id = 0; id < n_sourceID; id++) {
1915 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1916 				    uacp->usb_ac_log_handle,
1917 				    "sourceID=0x%x type=0x%x",
1918 				    d->baSourceID[id],
1919 				    units[d->baSourceID[id]].acu_type);
1920 
1921 				if (d->baSourceID[id] != 0) {
1922 					ASSERT(p[unit][d->baSourceID[id]] ==
1923 					    B_FALSE);
1924 					p[unit][d->baSourceID[id]] = B_TRUE;
1925 				}
1926 			}
1927 
1928 			break;
1929 		}
1930 		case USB_AUDIO_EXTENSION_UNIT:
1931 		{
1932 			usb_audio_extension_unit_descr1_t *d =
1933 					units[unit].acu_descriptor;
1934 			int n_sourceID = d->bNrInPins;
1935 			int id;
1936 
1937 			for (id = 0; id < n_sourceID; id++) {
1938 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1939 				    uacp->usb_ac_log_handle,
1940 				    "sourceID=0x%x type=0x%x",
1941 				    d->baSourceID[id],
1942 				    units[d->baSourceID[id]].acu_type);
1943 
1944 				if (d->baSourceID[id] != 0) {
1945 					ASSERT(p[unit][d->baSourceID[id]] ==
1946 					    B_TRUE);
1947 					p[unit][d->baSourceID[id]] = B_FALSE;
1948 				}
1949 			}
1950 
1951 			break;
1952 		}
1953 		case USB_AUDIO_INPUT_TERMINAL:
1954 
1955 			break;
1956 		default:
1957 			/*
1958 			 * Ignore the rest because they are not support yet
1959 			 */
1960 			break;
1961 		}
1962 	}
1963 
1964 #ifdef DEBUG
1965 	/* display topology in log buffer */
1966 {
1967 	uint_t i, j, l;
1968 	char *buf;
1969 
1970 	l = uacp->usb_ac_max_unit * 5;
1971 
1972 	buf = kmem_alloc(l, KM_SLEEP);
1973 
1974 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1975 	    "unit types:");
1976 
1977 	/* two	strings so they won't be replaced accidentily by tab */
1978 	(void) sprintf(&buf[0], "    ""    ");
1979 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1980 		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1981 	}
1982 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1983 
1984 	(void) sprintf(&buf[0], "  +-------");
1985 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1986 		(void) sprintf(&buf[5+((i-1)*3)], "---");
1987 	}
1988 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1989 
1990 	(void) sprintf(&buf[0], "    ""    ");
1991 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1992 		(void) sprintf(&buf[2 + (i*3)], "%02d ",
1993 			uacp->usb_ac_unit_type[i]);
1994 	}
1995 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1996 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " ");
1997 
1998 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1999 	    "adjacency matrix:");
2000 	(void) sprintf(&buf[0], "    ""    ");
2001 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
2002 		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
2003 	}
2004 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
2005 
2006 	(void) sprintf(&buf[0], "  +-------");
2007 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
2008 		(void) sprintf(&buf[5+((i-1)*3)], "---");
2009 	}
2010 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
2011 
2012 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
2013 		(void) sprintf(&buf[0], "%02d| "" ", i);
2014 		for (j = 1; j < uacp->usb_ac_max_unit; j++) {
2015 			(void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]);
2016 		}
2017 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
2018 	}
2019 	kmem_free(buf, l);
2020 }
2021 #endif
2022 }
2023 
2024 
2025 /*
2026  * usb_ac_add_unit_descriptor:
2027  *	take the parsed descriptor in the buffer and store it in the ID unit
2028  *	array. we grow the unit array if the ID exceeds the current max
2029  */
2030 static void
2031 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
2032 	size_t buflen)
2033 {
2034 	void	*descr;
2035 	int	len;
2036 	char	*format;
2037 	size_t	size;
2038 
2039 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2040 	    "usb_ac_add_unit_descriptor: 0x%x 0x%x 0x%x",
2041 	    buffer[0], buffer[1], buffer[2]);
2042 
2043 	/* doubling the length should allow for padding */
2044 	len = 2 * buffer[0];
2045 	descr = kmem_zalloc(len, KM_SLEEP);
2046 
2047 	switch (buffer[2]) {
2048 	case USB_AUDIO_INPUT_TERMINAL:
2049 		format = CS_AC_INPUT_TERM_FORMAT;
2050 		size = CS_AC_INPUT_TERM_SIZE;
2051 
2052 		break;
2053 	case USB_AUDIO_OUTPUT_TERMINAL:
2054 		format = CS_AC_OUTPUT_TERM_FORMAT;
2055 		size = CS_AC_OUTPUT_TERM_SIZE;
2056 
2057 		break;
2058 	case USB_AUDIO_MIXER_UNIT:
2059 		format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c";
2060 		size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1;
2061 
2062 		break;
2063 	case USB_AUDIO_SELECTOR_UNIT:
2064 		format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c";
2065 		size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1;
2066 
2067 		break;
2068 	case USB_AUDIO_FEATURE_UNIT:
2069 		format = CS_AC_FEATURE_UNIT_FORMAT "255c";
2070 		size = CS_AC_FEATURE_UNIT_SIZE;
2071 
2072 		break;
2073 	case USB_AUDIO_PROCESSING_UNIT:
2074 		format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c";
2075 		size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1;
2076 
2077 		break;
2078 	case USB_AUDIO_EXTENSION_UNIT:
2079 		format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c";
2080 		size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1;
2081 
2082 		break;
2083 	default:
2084 		USB_DPRINTF_L2(PRINT_MASK_ATTA,
2085 		    uacp->usb_ac_log_handle,
2086 		    "unsupported descriptor %d", buffer[2]);
2087 
2088 		/* ignore this descriptor */
2089 		kmem_free(descr, len);
2090 
2091 		return;
2092 	}
2093 
2094 	if (usb_parse_data(format, buffer, buflen, descr, len) < size) {
2095 		/* ignore this descriptor */
2096 		kmem_free(descr, len);
2097 
2098 		return;
2099 	}
2100 
2101 	switch (buffer[2]) {
2102 	case USB_AUDIO_INPUT_TERMINAL:
2103 	{
2104 		usb_audio_input_term_descr_t *d =
2105 		    (usb_audio_input_term_descr_t *)descr;
2106 
2107 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2108 		    uacp->usb_ac_log_handle,
2109 		    "input term: type=0x%x sub=0x%x termid=0x%x\n\t"
2110 		    "termtype=0x%x assoc=0x%x #ch=%d "
2111 		    "chconf=0x%x ich=0x%x iterm=0x%x",
2112 		    d->bDescriptorType, d->bDescriptorSubType,
2113 		    d->bTerminalID, d->wTerminalType,
2114 		    d->bAssocTerminal, d->bNrChannels,
2115 		    d->wChannelConfig, d->iChannelNames,
2116 		    d->iTerminal);
2117 
2118 		usb_ac_alloc_unit(uacp, d->bTerminalID);
2119 		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
2120 		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
2121 		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
2122 
2123 		break;
2124 	}
2125 	case USB_AUDIO_OUTPUT_TERMINAL:
2126 	{
2127 		usb_audio_output_term_descr_t *d =
2128 		    (usb_audio_output_term_descr_t *)descr;
2129 
2130 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2131 		    uacp->usb_ac_log_handle,
2132 		    "output term: type=0x%x sub=0x%x termid=0x%x\n\t"
2133 		    "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
2134 		    d->bDescriptorType, d->bDescriptorSubType,
2135 		    d->bTerminalID, d->wTerminalType,
2136 		    d->bAssocTerminal, d->bSourceID,
2137 		    d->iTerminal);
2138 
2139 		usb_ac_alloc_unit(uacp, d->bTerminalID);
2140 		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
2141 		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
2142 		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
2143 
2144 		break;
2145 	}
2146 	case USB_AUDIO_MIXER_UNIT:
2147 	{
2148 		usb_audio_mixer_unit_descr1_t *d =
2149 		    (usb_audio_mixer_unit_descr1_t *)descr;
2150 
2151 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2152 		    uacp->usb_ac_log_handle,
2153 		    "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2154 		    "#pins=0x%x sourceid[0]=0x%x",
2155 		    d->bDescriptorType, d->bDescriptorSubType,
2156 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2157 		usb_ac_alloc_unit(uacp, d->bUnitID);
2158 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2159 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2160 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2161 
2162 		break;
2163 	}
2164 	case USB_AUDIO_SELECTOR_UNIT:
2165 	{
2166 		usb_audio_selector_unit_descr1_t *d =
2167 		    (usb_audio_selector_unit_descr1_t *)descr;
2168 
2169 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2170 		    uacp->usb_ac_log_handle,
2171 		    "selector unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2172 		    "#pins=0x%x sourceid[0]=0x%x",
2173 		    d->bDescriptorType, d->bDescriptorSubType,
2174 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2175 		usb_ac_alloc_unit(uacp, d->bUnitID);
2176 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2177 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2178 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2179 
2180 		break;
2181 	}
2182 	case USB_AUDIO_FEATURE_UNIT:
2183 	{
2184 		usb_audio_feature_unit_descr1_t *d =
2185 		    (usb_audio_feature_unit_descr1_t *)descr;
2186 
2187 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2188 		    uacp->usb_ac_log_handle,
2189 		    "feature unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2190 		    "sourceid=0x%x size=0x%x",
2191 		    d->bDescriptorType, d->bDescriptorSubType,
2192 		    d->bUnitID, d->bSourceID, d->bControlSize);
2193 
2194 		usb_ac_alloc_unit(uacp, d->bUnitID);
2195 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2196 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2197 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2198 
2199 		break;
2200 	}
2201 	case USB_AUDIO_PROCESSING_UNIT:
2202 	{
2203 		usb_audio_processing_unit_descr1_t *d =
2204 		    (usb_audio_processing_unit_descr1_t *)descr;
2205 
2206 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2207 		    uacp->usb_ac_log_handle,
2208 		    "processing unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2209 		    "#pins=0x%x sourceid[0]=0x%x",
2210 		    d->bDescriptorType, d->bDescriptorSubType,
2211 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2212 		usb_ac_alloc_unit(uacp, d->bUnitID);
2213 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2214 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2215 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2216 
2217 		break;
2218 	}
2219 	case USB_AUDIO_EXTENSION_UNIT:
2220 	{
2221 		usb_audio_extension_unit_descr1_t *d =
2222 		    (usb_audio_extension_unit_descr1_t *)descr;
2223 
2224 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
2225 		    uacp->usb_ac_log_handle,
2226 		    "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t"
2227 		    "#pins=0x%x sourceid[0]=0x%x",
2228 		    d->bDescriptorType, d->bDescriptorSubType,
2229 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
2230 		usb_ac_alloc_unit(uacp, d->bUnitID);
2231 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
2232 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
2233 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
2234 
2235 		break;
2236 	}
2237 	default:
2238 		break;
2239 	}
2240 }
2241 
2242 
2243 /*
2244  * usb_ac_alloc_unit:
2245  *	check if the unit ID is less than max_unit in which case no
2246  *	extra entries are needed. If more entries are needed, copy over
2247  *	the existing array into a new larger array
2248  */
2249 static void
2250 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
2251 {
2252 	usb_ac_unit_list_t *old = NULL;
2253 	uint_t	max_unit;
2254 
2255 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2256 	    "usb_ac_alloc_unit: unit=%d", unit);
2257 
2258 	if (uacp->usb_ac_units) {
2259 		if (unit < uacp->usb_ac_max_unit) {
2260 			/* existing array is big enough */
2261 
2262 			return;
2263 		}
2264 		old = uacp->usb_ac_units;
2265 		max_unit = uacp->usb_ac_max_unit;
2266 	}
2267 
2268 	/* allocate two extra ones */
2269 	unit += 2;
2270 	uacp->usb_ac_max_unit = unit;
2271 	uacp->usb_ac_units = kmem_zalloc(unit *
2272 				sizeof (usb_ac_unit_list_t), KM_SLEEP);
2273 
2274 	if (old) {
2275 		size_t len = max_unit * sizeof (usb_ac_unit_list_t);
2276 		bcopy(old, uacp->usb_ac_units, len);
2277 
2278 		kmem_free(old, len);
2279 	}
2280 }
2281 
2282 
2283 /*
2284  * usb_ac_free_all_units:
2285  *	free the entire unit list
2286  */
2287 static void
2288 usb_ac_free_all_units(usb_ac_state_t *uacp)
2289 {
2290 	uint_t	unit;
2291 	usb_ac_unit_list_t *unitp;
2292 
2293 	if (uacp->usb_ac_units == NULL) {
2294 
2295 		return;
2296 	}
2297 
2298 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2299 	    "usb_ac_alloc_unit: max_unit=%d", uacp->usb_ac_max_unit);
2300 
2301 	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
2302 		unitp = &uacp->usb_ac_units[unit];
2303 		if (unitp) {
2304 			if (unitp->acu_descriptor) {
2305 				kmem_free(unitp->acu_descriptor,
2306 					unitp->acu_descr_length);
2307 			}
2308 		}
2309 	}
2310 
2311 	kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit *
2312 					sizeof (usb_ac_unit_list_t));
2313 }
2314 
2315 
2316 /*
2317  * usb_ac_lookup_port_type:
2318  *	map term type to port type
2319  *	default just return LINE_IN + LINE_OUT
2320  */
2321 static int
2322 usb_ac_lookup_port_type(ushort_t termtype)
2323 {
2324 	uint_t i;
2325 
2326 	for (i = 0; ; i++) {
2327 		if (usb_ac_term_type_map[i].term_type == 0) {
2328 
2329 			break;
2330 		}
2331 
2332 		if (usb_ac_term_type_map[i].term_type == termtype) {
2333 
2334 			return (usb_ac_term_type_map[i].port_type);
2335 		}
2336 	}
2337 
2338 	return (AUDIO_LINE_IN|AUDIO_LINE_OUT);
2339 }
2340 
2341 
2342 /*
2343  * usb_ac_update_port:
2344  *	called for each terminal
2345  */
2346 /*ARGSUSED*/
2347 static int
2348 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
2349     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
2350 {
2351 	if (dir & AUDIO_PLAY) {
2352 		usb_audio_output_term_descr_t *d =
2353 		    (usb_audio_output_term_descr_t *)
2354 		    uacp->usb_ac_units[id].acu_descriptor;
2355 		uint_t port_type =
2356 			usb_ac_lookup_port_type(d->wTerminalType);
2357 
2358 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2359 		    "usb_ac_update_port: dir=%d type=0x%x port type=%d",
2360 		    dir, d->wTerminalType, port_type);
2361 
2362 		uacp->usb_ac_output_ports |= port_type;
2363 		uacp->usb_ac_output_ports &= ~AUDIO_LINE_IN;
2364 	} else {
2365 		usb_audio_output_term_descr_t *d =
2366 			(usb_audio_output_term_descr_t *)
2367 			uacp->usb_ac_units[id].acu_descriptor;
2368 		uint_t port_type =
2369 			usb_ac_lookup_port_type(d->wTerminalType);
2370 
2371 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2372 		    "usb_ac_update_port: dir=%d type=0x%x port type=%d",
2373 		    dir, d->wTerminalType, port_type);
2374 
2375 		uacp->usb_ac_input_ports |=
2376 			usb_ac_lookup_port_type(d->wTerminalType);
2377 		uacp->usb_ac_input_ports &= ~AUDIO_LINE_OUT;
2378 	}
2379 
2380 	return (USB_SUCCESS);
2381 }
2382 
2383 
2384 /*
2385  * usb_ac_map_termtype_to_port:
2386  *	starting from a streaming termtype find all
2387  *	input or output terminals and OR into uacp->usb_ac_input_ports
2388  *	or uacp->usb_ac_output_ports;
2389  */
2390 static void
2391 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
2392 {
2393 	uint_t count = 0;
2394 	uint_t depth = 0;
2395 	uint_t search_type = (dir & AUDIO_PLAY) ?
2396 	    USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
2397 
2398 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2399 	    "usb_ac_map_term_to_port: dir=%d", dir);
2400 
2401 	(void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
2402 	    0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
2403 
2404 	ASSERT(depth == 0);
2405 }
2406 
2407 
2408 /*
2409  * usb_ac_set_port:
2410  *	find a selector port (record side only) and set the
2411  *	input to the matching pin
2412  */
2413 static uint_t
2414 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
2415 {
2416 	uint_t count = 0;
2417 	uint_t id;
2418 	uint_t depth = 0;
2419 
2420 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2421 	    "usb_ac_set_port: dir=%d port=%d", dir, port);
2422 
2423 	/* we only support the selector for the record side */
2424 	if (dir & AUDIO_RECORD) {
2425 		id = usb_ac_traverse_all_units(uacp, dir,
2426 		    USB_AUDIO_SELECTOR_UNIT, 0,
2427 		    0, USB_AC_FIND_ONE, &count, port, &depth,
2428 		    usb_ac_set_selector);
2429 
2430 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2431 		    "usb_ac_set_port: id=%d count=%d port=%d",
2432 		    id, count, port);
2433 
2434 		ASSERT(depth == 0);
2435 	}
2436 
2437 	return (USB_SUCCESS);
2438 }
2439 
2440 
2441 /*
2442  * usb_ac_match_port:
2443  *	given the requested port type, find a correspondig term type
2444  *	Called from usb_ac_traverse_all_units()
2445  */
2446 /*ARGSUSED*/
2447 static int
2448 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
2449     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
2450 {
2451 	uint_t port_type;
2452 
2453 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2454 	    "usb_ac_match_port: id=%d dir=%d port=%d",
2455 	    id, dir, arg1);
2456 
2457 	if (dir & AUDIO_PLAY) {
2458 		usb_audio_output_term_descr_t *d =
2459 		    (usb_audio_output_term_descr_t *)
2460 		    uacp->usb_ac_units[id].acu_descriptor;
2461 		port_type = usb_ac_lookup_port_type(d->wTerminalType);
2462 
2463 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2464 		    "usb_ac_match_port: "
2465 		    "dir=%d type=0x%x port_type=%d port=%d",
2466 		    dir, d->wTerminalType, port_type, arg1);
2467 	} else {
2468 		usb_audio_output_term_descr_t *d =
2469 			(usb_audio_output_term_descr_t *)
2470 			uacp->usb_ac_units[id].acu_descriptor;
2471 		port_type = usb_ac_lookup_port_type(d->wTerminalType);
2472 
2473 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2474 		    "usb_ac_match_port: "
2475 		    "dir=%d type=0x%x port_type=%d port=%d",
2476 		    dir, d->wTerminalType, port_type, arg1);
2477 	}
2478 
2479 	return ((port_type & arg1) ? USB_SUCCESS : USB_FAILURE);
2480 }
2481 
2482 
2483 /*
2484  * usb_ac_set_selector:
2485  *	Called from usb_ac_traverse_all_units()
2486  *	Find the correct pin and set selector to this pin
2487  */
2488 /*ARGSUSED*/
2489 static int
2490 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
2491     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
2492 {
2493 	uint_t count = 0;
2494 	uint_t unit = USB_AC_ID_NONE;
2495 	uint_t pin;
2496 	uint_t search_target =
2497 	    (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2498 				USB_AUDIO_INPUT_TERMINAL;
2499 	usb_audio_selector_unit_descr1_t *d =
2500 		    (usb_audio_selector_unit_descr1_t *)
2501 		    uacp->usb_ac_units[id].acu_descriptor;
2502 	int n_sourceID = d->bNrInPins;
2503 	int rval = USB_FAILURE;
2504 
2505 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2506 	    "usb_ac_set_selector: id=%d dir=%d port=%d",
2507 	    id, dir, arg1);
2508 
2509 	/*
2510 	 * for each pin, find a term type that matches the
2511 	 * requested port type
2512 	 */
2513 	for (pin = 0; pin < n_sourceID; pin++) {
2514 		if (d->baSourceID[pin] == 0) {
2515 
2516 			break;
2517 		}
2518 		unit = d->baSourceID[pin];
2519 
2520 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2521 		    "usb_ac_set_selector: pin=%d unit=%d", pin, unit);
2522 
2523 		if (uacp->usb_ac_unit_type[unit] == search_target) {
2524 			if (usb_ac_match_port(uacp, unit, dir, channel,
2525 			    control, arg1, depth) == USB_SUCCESS) {
2526 
2527 				break;
2528 			} else {
2529 				unit = USB_AC_ID_NONE;
2530 
2531 				continue;
2532 			}
2533 		}
2534 
2535 		/* find units connected to this unit */
2536 		unit = usb_ac_traverse_connections(uacp, unit,
2537 				dir, search_target, channel, control,
2538 				USB_AC_FIND_ONE, &count, arg1, depth,
2539 				usb_ac_match_port);
2540 
2541 		if (unit != USB_AC_ID_NONE) {
2542 
2543 			break;
2544 		}
2545 	}
2546 
2547 
2548 	if (unit != USB_AC_ID_NONE) {
2549 		mblk_t		*data;
2550 		usb_cr_t	cr;
2551 		usb_cb_flags_t	cb_flags;
2552 
2553 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2554 		    "usb_ac_set_selector: found id=%d at pin %d", unit, pin);
2555 
2556 		mutex_exit(&uacp->usb_ac_mutex);
2557 
2558 		data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
2559 
2560 		/* pins are 1-based */
2561 		*(data->b_rptr) = (char)++pin;
2562 
2563 		if (usb_pipe_sync_ctrl_xfer(
2564 		    uacp->usb_ac_dip,
2565 		    uacp->usb_ac_default_ph,
2566 		    USB_DEV_REQ_HOST_TO_DEV |
2567 		    USB_DEV_REQ_TYPE_CLASS |
2568 		    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
2569 		    USB_AUDIO_SET_CUR,		/* bRequest */
2570 		    0,				/* wValue */
2571 						/* feature unit and id */
2572 		    (id << 8)| uacp->usb_ac_ifno, /* wIndex */
2573 		    1,				/* wLength */
2574 		    &data,
2575 		    USB_ATTRS_NONE,
2576 		    &cr, &cb_flags,
2577 		    USB_FLAGS_SLEEP) == USB_SUCCESS) {
2578 			USB_DPRINTF_L3(PRINT_MASK_ALL,
2579 			    uacp->usb_ac_log_handle,
2580 			    "set current selection: %d", *data->b_rptr);
2581 
2582 			rval = USB_SUCCESS;
2583 		} else {
2584 			USB_DPRINTF_L2(PRINT_MASK_ALL,
2585 			    uacp->usb_ac_log_handle,
2586 			    "set current pin selection failed");
2587 		}
2588 		freemsg(data);
2589 
2590 		mutex_enter(&uacp->usb_ac_mutex);
2591 	} else {
2592 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2593 		    "usb_ac_set_selector: nothing found");
2594 	}
2595 
2596 	return (rval);
2597 }
2598 
2599 
2600 /*
2601  * usb_ac_set_control:
2602  *	apply func to all units of search_target type for both the
2603  *	requested channel and master channel
2604  */
2605 static uint_t
2606 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
2607 	uint_t channel, uint_t control, uint_t all_or_one,
2608 	uint_t *count, uint_t arg1,
2609 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2610 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2611 {
2612 	uint_t id;
2613 	uint_t depth = 0;
2614 
2615 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2616 	    "usb_ac_set_control: dir=%d type=%d ch=%d cntl=%d",
2617 	    dir, search_target, channel, control);
2618 
2619 
2620 	id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
2621 	    control, all_or_one, count, arg1, &depth, func);
2622 
2623 	if ((channel != 0) &&
2624 	    (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) ||
2625 	    (all_or_one == USB_AC_FIND_ALL)))  {
2626 		/* try master channel */
2627 		channel = 0;
2628 		id = usb_ac_traverse_all_units(uacp, dir, search_target,
2629 			channel, control, all_or_one, count, arg1,
2630 			&depth, func);
2631 	}
2632 
2633 	ASSERT(depth == 0);
2634 
2635 	return (id);
2636 }
2637 
2638 
2639 /*
2640  * usb_ac_traverse_all_units:
2641  *	traverse all units starting with all IT or OT depending on direction.
2642  *	If no unit is found for the particular channel, try master channel
2643  *	If a matching unit is found, apply the function passed by
2644  *	the caller
2645  */
2646 static uint_t
2647 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
2648 	uint_t search_target, uint_t channel, uint_t control,
2649 	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2650 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2651 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2652 {
2653 	uint_t unit, start_type, id;
2654 
2655 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2656 	    "usb_ac_traverse_all_units: "
2657 	    "dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
2658 	    dir, search_target, channel, control, all_or_one, *depth);
2659 
2660 	start_type = (dir & AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
2661 				USB_AUDIO_OUTPUT_TERMINAL;
2662 
2663 	/* keep track of recursion */
2664 	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2665 		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2666 		    "Unit topology too complex, giving up");
2667 
2668 		return (USB_AC_ID_NONE);
2669 	}
2670 
2671 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2672 		/* is this an IT or OT? */
2673 		if (uacp->usb_ac_unit_type[unit] != start_type) {
2674 
2675 			continue;
2676 		}
2677 
2678 		/* start at streaming term types */
2679 		if (dir & AUDIO_PLAY) {
2680 			usb_audio_input_term_descr_t *d =
2681 			    uacp->usb_ac_units[unit].acu_descriptor;
2682 			if (d->wTerminalType !=
2683 			    USB_AUDIO_TERM_TYPE_STREAMING) {
2684 
2685 				continue;
2686 			}
2687 		} else {
2688 			usb_audio_output_term_descr_t *d =
2689 			    uacp->usb_ac_units[unit].acu_descriptor;
2690 			if (d->wTerminalType !=
2691 			    USB_AUDIO_TERM_TYPE_STREAMING) {
2692 
2693 				continue;
2694 			}
2695 		}
2696 
2697 		/* find units connected to this unit */
2698 		id = usb_ac_traverse_connections(uacp, unit, dir,
2699 		    search_target, channel, control, all_or_one, count,
2700 		    arg1, depth, func);
2701 
2702 		if ((all_or_one == USB_AC_FIND_ONE) &&
2703 		    (id != USB_AC_ID_NONE)) {
2704 			unit = id;
2705 
2706 			break;
2707 		}
2708 	}
2709 
2710 	(*depth)--;
2711 
2712 	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2713 }
2714 
2715 
2716 /*
2717  * usb_ac_set_monitor_gain_control:
2718  *	search for a feature unit between output terminal (OT) and
2719  *	input terminal. We are looking for a path between
2720  *	for example a microphone and a speaker through a feature unit
2721  *	and mixer
2722  */
2723 static uint_t
2724 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
2725 	uint_t search_target, uint_t channel, uint_t control,
2726 	uint_t all_or_one, uint_t *count, uint_t arg1,
2727 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2728 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2729 {
2730 	uint_t unit, id;
2731 	uint_t depth = 0;
2732 
2733 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2734 	    "usb_ac_set_monitor_gain_control: dir=%d type=%d ch=%d cntl=%d",
2735 	    dir, search_target, channel, control);
2736 
2737 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2738 		usb_audio_output_term_descr_t *d =
2739 			    uacp->usb_ac_units[unit].acu_descriptor;
2740 
2741 		/* is this an OT and not stream type? */
2742 		if ((uacp->usb_ac_unit_type[unit] ==
2743 		    USB_AUDIO_OUTPUT_TERMINAL) &&
2744 		    (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) {
2745 
2746 			/* find units connected to this unit */
2747 			id = usb_ac_traverse_connections(uacp, unit, dir,
2748 			    search_target, channel, control, all_or_one, count,
2749 			    arg1, &depth, func);
2750 
2751 			if ((all_or_one == USB_AC_FIND_ONE) &&
2752 			    (id != USB_AC_ID_NONE)) {
2753 
2754 				break;
2755 			}
2756 		}
2757 	}
2758 
2759 	ASSERT(depth == 0);
2760 
2761 	return (id);
2762 }
2763 
2764 
2765 /*
2766  * usb_ac_push/pop_unit
2767  *	add/remove unit ID to the traverse path
2768  */
2769 static void
2770 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
2771 {
2772 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2773 	    "usb_ac_push_unit_id: pushing %d at %d", unit,
2774 	    uacp->usb_ac_traverse_path_index);
2775 
2776 	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] = unit;
2777 	ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
2778 }
2779 
2780 
2781 static void
2782 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
2783 {
2784 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2785 	    "usb_ac_push_unit_id: popping %d at %d", unit,
2786 	    uacp->usb_ac_traverse_path_index);
2787 
2788 	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
2789 }
2790 
2791 
2792 /*
2793  * usb_ac_show_traverse_path:
2794  *	display entire path, just for debugging
2795  */
2796 static void
2797 usb_ac_show_traverse_path(usb_ac_state_t *uacp)
2798 {
2799 	int i;
2800 
2801 	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2802 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2803 		    "traverse path %d: unit=%d type=%d",
2804 		i, uacp->usb_ac_traverse_path[i],
2805 		uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]);
2806 	}
2807 }
2808 
2809 
2810 /*
2811  * usb_ac_check_path:
2812  *	check for a specified type in the traverse path
2813  */
2814 static int
2815 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type)
2816 {
2817 	int i;
2818 
2819 	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2820 		uint_t unit = uacp->usb_ac_traverse_path[i];
2821 
2822 		if (uacp->usb_ac_unit_type[unit] == type) {
2823 
2824 			return (USB_SUCCESS);
2825 		}
2826 	}
2827 
2828 	return (USB_FAILURE);
2829 }
2830 
2831 
2832 /*
2833  * usb_ac_traverse_connections:
2834  *	traverse all units and for each unit with the right type, call
2835  *	func. If the func returns a success and search == USB_AC_FIND_ONE,
2836  *	we are done. If all is set then we continue until we terminate
2837  *	and input or output terminal.
2838  *	For audio play, we traverse columns starting from an input terminal
2839  *	to an output terminal while for record we traverse rows from output
2840  *	terminal to input terminal.
2841  */
2842 static uint_t
2843 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
2844 	uint_t search_target, uint_t channel, uint_t control,
2845 	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2846 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2847 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2848 {
2849 	uint_t unit, id;
2850 	uint_t done = (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2851 				USB_AUDIO_INPUT_TERMINAL;
2852 
2853 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2854 	    "usb_ac_traverse_connections: "
2855 	    "start=%d dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
2856 	    start_unit, dir, search_target, channel, control,
2857 	    all_or_one, *depth);
2858 
2859 	/* keep track of recursion depth */
2860 	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2861 		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2862 		    "Unit topology too complex, giving up");
2863 
2864 		return (USB_AC_ID_NONE);
2865 	}
2866 
2867 	usb_ac_push_unit_id(uacp, start_unit);
2868 
2869 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2870 		uint_t entry = (dir & AUDIO_PLAY) ?
2871 			uacp->usb_ac_connections[unit][start_unit] :
2872 			uacp->usb_ac_connections[start_unit][unit];
2873 
2874 		if (entry) {
2875 			USB_DPRINTF_L3(PRINT_MASK_ALL,
2876 			    uacp->usb_ac_log_handle,
2877 			    "start=%d unit=%d entry=%d type=%d "
2878 			    "done=%d found=%d",
2879 			    start_unit, unit, entry, search_target, done,
2880 			    uacp->usb_ac_unit_type[unit]);
2881 
2882 			/* did we find a matching type? */
2883 			if (uacp->usb_ac_unit_type[unit] == search_target) {
2884 				USB_DPRINTF_L3(PRINT_MASK_ALL,
2885 				    uacp->usb_ac_log_handle,
2886 				    "match: dir=%d unit=%d type=%d",
2887 				    dir, unit, search_target);
2888 
2889 				/* yes, no apply function to this unit */
2890 				if (func(uacp, unit, dir, channel,
2891 				    control, arg1, depth) == USB_SUCCESS) {
2892 					(*count)++;
2893 
2894 					USB_DPRINTF_L3(PRINT_MASK_ALL,
2895 					    uacp->usb_ac_log_handle,
2896 					    "func returned success, "
2897 					    "unit=%d all=%d", unit,
2898 					    all_or_one);
2899 
2900 					/* are we done? */
2901 					if (all_or_one == USB_AC_FIND_ONE) {
2902 
2903 						break;
2904 					}
2905 				}
2906 			}
2907 
2908 			/* did we find the terminating unit */
2909 			if (uacp->usb_ac_unit_type[unit] == done) {
2910 
2911 				continue;
2912 			}
2913 			id = usb_ac_traverse_connections(uacp, unit, dir,
2914 				search_target, channel, control,
2915 				all_or_one, count, arg1, depth, func);
2916 			if ((id != USB_AC_ID_NONE) &&
2917 			    (all_or_one == USB_AC_FIND_ONE)) {
2918 				unit = id;
2919 
2920 				break;
2921 			}
2922 		}
2923 	}
2924 
2925 	(*depth)--;
2926 	usb_ac_pop_unit_id(uacp, start_unit);
2927 
2928 	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2929 }
2930 
2931 
2932 /*
2933  * Event Management
2934  *
2935  * usb_ac_disconnect_event_cb:
2936  *	The device has been disconnected. we either wait for
2937  *	detach or a reconnect event.
2938  */
2939 static int
2940 usb_ac_disconnect_event_cb(dev_info_t *dip)
2941 {
2942 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2943 	    usb_ac_statep, ddi_get_instance(dip));
2944 
2945 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2946 	    "usb_ac_disconnect_event_cb: dip=0x%p", dip);
2947 
2948 	usb_ac_serialize_access(uacp);
2949 
2950 	/* setting to disconnect state will prevent replumbing */
2951 	mutex_enter(&uacp->usb_ac_mutex);
2952 	uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2953 
2954 	if (uacp->usb_ac_busy_count) {
2955 		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2956 		    "device was disconnected while busy. "
2957 		    "Data may have been lost");
2958 	}
2959 	mutex_exit(&uacp->usb_ac_mutex);
2960 
2961 	USB_DPRINTF_L3(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2962 	    "usb_ac_disconnect_event_cb: done");
2963 
2964 	usb_ac_release_access(uacp);
2965 
2966 	return (USB_SUCCESS);
2967 }
2968 
2969 
2970 /*
2971  * usb_ac_cpr_suspend:
2972  */
2973 static int
2974 usb_ac_cpr_suspend(dev_info_t *dip)
2975 {
2976 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2977 	    usb_ac_statep, ddi_get_instance(dip));
2978 
2979 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2980 	    "usb_ac_cpr_suspend: Begin");
2981 
2982 	mutex_enter(&uacp->usb_ac_mutex);
2983 	uacp->usb_ac_dev_state = USB_DEV_SUSPENDED;
2984 	mutex_exit(&uacp->usb_ac_mutex);
2985 
2986 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2987 	    "usb_ac_cpr_suspend: End");
2988 
2989 	return (USB_SUCCESS);
2990 }
2991 
2992 
2993 
2994 /*
2995  * usb_ac_reconnect_event_cb:
2996  *	The device was disconnected but this instance not detached, probably
2997  *	because the device was busy.
2998  *	if the same device, continue with restoring state
2999  *	We should either be in the unplumbed state or the plumbed open
3000  *	state.
3001  */
3002 static int
3003 usb_ac_reconnect_event_cb(dev_info_t *dip)
3004 {
3005 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
3006 	    usb_ac_statep, ddi_get_instance(dip));
3007 
3008 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
3009 	    "usb_ac_reconnect_event_cb: dip=0x%p", dip);
3010 
3011 	mutex_enter(&uacp->usb_ac_mutex);
3012 	mutex_exit(&uacp->usb_ac_mutex);
3013 
3014 	usb_ac_serialize_access(uacp);
3015 
3016 	/* check the plumbing state */
3017 	mutex_enter(&uacp->usb_ac_mutex);
3018 	uacp->usb_ac_busy_count++;
3019 	if (uacp->usb_ac_plumbing_state ==
3020 	    USB_AC_STATE_PLUMBED) {
3021 		mutex_exit(&uacp->usb_ac_mutex);
3022 		usb_ac_restore_device_state(dip, uacp);
3023 		mutex_enter(&uacp->usb_ac_mutex);
3024 	}
3025 	uacp->usb_ac_busy_count--;
3026 
3027 	if (uacp->usb_ac_busy_count) {
3028 		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
3029 		    "busy device has been reconnected");
3030 	}
3031 	mutex_exit(&uacp->usb_ac_mutex);
3032 
3033 	usb_ac_release_access(uacp);
3034 
3035 	return (USB_SUCCESS);
3036 }
3037 
3038 
3039 /*
3040  * usb_ac_cpr_resume:
3041  *	Restore device state
3042  */
3043 static void
3044 usb_ac_cpr_resume(dev_info_t *dip)
3045 {
3046 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
3047 	    usb_ac_statep, ddi_get_instance(dip));
3048 
3049 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
3050 	    "usb_ac_cpr_resume");
3051 
3052 	usb_ac_serialize_access(uacp);
3053 
3054 	usb_ac_restore_device_state(dip, uacp);
3055 
3056 	usb_ac_release_access(uacp);
3057 }
3058 
3059 
3060 /*
3061  * usb_ac_restore_device_state:
3062  *	Set original configuration of the device
3063  *	enable wrq - this starts new transactions on the control pipe
3064  */
3065 static void
3066 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp)
3067 {
3068 	usb_ac_power_t	*uacpm;
3069 	int	rval;
3070 
3071 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
3072 	    "usb_ac_restore_device_state:");
3073 
3074 	usb_ac_pm_busy_component(uacp);
3075 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3076 
3077 	/* Check if we are talking to the same device */
3078 	if (usb_check_same_device(dip, uacp->usb_ac_log_handle,
3079 	    USB_LOG_L0, PRINT_MASK_ALL,
3080 	    USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
3081 		usb_ac_pm_idle_component(uacp);
3082 
3083 		/* change the device state from suspended to disconnected */
3084 		mutex_enter(&uacp->usb_ac_mutex);
3085 		uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
3086 		mutex_exit(&uacp->usb_ac_mutex);
3087 
3088 		return;
3089 	}
3090 
3091 	mutex_enter(&uacp->usb_ac_mutex);
3092 	uacpm = uacp->usb_ac_pm;
3093 	if (uacpm) {
3094 		if (uacpm->acpm_wakeup_enabled) {
3095 			mutex_exit(&uacp->usb_ac_mutex);
3096 
3097 			if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip,
3098 			    USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
3099 
3100 				USB_DPRINTF_L4(PRINT_MASK_ATTA,
3101 				    uacp->usb_ac_log_handle,
3102 				    "usb_ac_restore_device_state: "
3103 				    "remote wakeup "
3104 				    "enable failed, rval=%d", rval);
3105 			}
3106 
3107 			mutex_enter(&uacp->usb_ac_mutex);
3108 		}
3109 	}
3110 
3111 	/* prevent unplumbing */
3112 	uacp->usb_ac_busy_count++;
3113 	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
3114 	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) {
3115 		(void) usb_ac_restore_audio_state(uacp, 0);
3116 	}
3117 	uacp->usb_ac_busy_count--;
3118 	mutex_exit(&uacp->usb_ac_mutex);
3119 	usb_ac_pm_idle_component(uacp);
3120 }
3121 
3122 
3123 /*
3124  * usb_ac_am_restore_state
3125  */
3126 static void
3127 usb_ac_am_restore_state(void *arg)
3128 {
3129 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3130 
3131 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3132 	    "usb_ac_am_restore_state: Begin");
3133 
3134 	usb_ac_serialize_access(uacp);
3135 
3136 	mutex_enter(&uacp->usb_ac_mutex);
3137 
3138 	if (uacp->usb_ac_plumbing_state ==
3139 	    USB_AC_STATE_PLUMBED_RESTORING) {
3140 		mutex_exit(&uacp->usb_ac_mutex);
3141 
3142 		/*
3143 		 * allow hid and usb_as to restore themselves
3144 		 * (some handshake would have been preferable though)
3145 		 */
3146 		delay(USB_AC_RESTORE_DELAY);
3147 
3148 		(void) audio_sup_restore_state(uacp->usb_ac_audiohdl,
3149 		    AUDIO_ALL_DEVICES, AUDIO_BOTH);
3150 
3151 		mutex_enter(&uacp->usb_ac_mutex);
3152 		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3153 	}
3154 
3155 	/* allow unplumbing */
3156 	uacp->usb_ac_busy_count--;
3157 	mutex_exit(&uacp->usb_ac_mutex);
3158 
3159 	usb_ac_release_access(uacp);
3160 
3161 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3162 	    "usb_ac_am_restore_state: End");
3163 }
3164 
3165 
3166 /*
3167  * usb_ac_restore_audio_state:
3168  */
3169 static int
3170 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
3171 {
3172 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3173 
3174 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3175 	    "usb_ac_restore_audio_state: flag=%d", flag);
3176 
3177 	switch (uacp->usb_ac_plumbing_state) {
3178 	case USB_AC_STATE_PLUMBED:
3179 		uacp->usb_ac_plumbing_state =
3180 				USB_AC_STATE_PLUMBED_RESTORING;
3181 
3182 		break;
3183 	case USB_AC_STATE_UNPLUMBED:
3184 
3185 		return (USB_SUCCESS);
3186 	case USB_AC_STATE_PLUMBED_RESTORING:
3187 	default:
3188 
3189 		return (USB_FAILURE);
3190 	}
3191 
3192 	/*
3193 	 * increment busy_count again, it will be decremented
3194 	 * in usb_ac_am_restore_state
3195 	 */
3196 	uacp->usb_ac_busy_count++;
3197 
3198 	if (flag & USB_FLAGS_SLEEP) {
3199 		mutex_exit(&uacp->usb_ac_mutex);
3200 		usb_ac_am_restore_state((void *)uacp);
3201 		mutex_enter(&uacp->usb_ac_mutex);
3202 	} else {
3203 		mutex_exit(&uacp->usb_ac_mutex);
3204 		if (usb_async_req(uacp->usb_ac_dip,
3205 		    usb_ac_am_restore_state,
3206 		    (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) {
3207 
3208 			mutex_enter(&uacp->usb_ac_mutex);
3209 			uacp->usb_ac_busy_count--;
3210 
3211 			return (USB_FAILURE);
3212 		}
3213 		mutex_enter(&uacp->usb_ac_mutex);
3214 	}
3215 
3216 	return (USB_SUCCESS);
3217 }
3218 
3219 
3220 /*
3221  * Mixer Callback Management
3222  * NOTE: all mixer callbacks are serialized. we cannot be closed while
3223  *	we are in the middle of a callback. There needs to be a
3224  *	teardown first. We cannot be unplumbed as long as we are
3225  *	still open.
3226  *
3227  * usb_ac_setup:
3228  *	Send setup to usb_as if the first setup
3229  *	Check power is done in usb_ac_send_as_cmd()
3230  */
3231 static int
3232 usb_ac_setup(audiohdl_t ahdl, int stream, int flag)
3233 {
3234 	int	rval = AUDIO_SUCCESS;
3235 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
3236 
3237 	ASSERT(uacp != NULL);
3238 
3239 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3240 	    "usb_ac_setup: Begin ahdl=0x%p, stream=%d, flag=%d",
3241 	    ahdl, stream, flag);
3242 
3243 	mutex_enter(&uacp->usb_ac_mutex);
3244 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3245 		mutex_exit(&uacp->usb_ac_mutex);
3246 
3247 		return (AUDIO_FAILURE);
3248 	}
3249 	mutex_exit(&uacp->usb_ac_mutex);
3250 
3251 	usb_ac_serialize_access(uacp);
3252 
3253 	if (flag & AUDIO_PLAY) {
3254 		rval = usb_ac_do_setup(ahdl, stream, AUDIO_PLAY);
3255 	}
3256 
3257 	if ((rval == USB_SUCCESS) && (flag & AUDIO_RECORD)) {
3258 		rval = usb_ac_do_setup(ahdl, stream, AUDIO_RECORD);
3259 	}
3260 
3261 	usb_ac_release_access(uacp);
3262 
3263 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3264 	    "usb_ac_setup: rval=%d", rval);
3265 
3266 	return ((rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE);
3267 }
3268 
3269 
3270 /*
3271  * usb_ac_do_setup:
3272  *	Wrapper function for usb_ac_setup which can be called
3273  *	either from audio framework for usb_ac_set_format
3274  */
3275 static int
3276 usb_ac_do_setup(audiohdl_t ahdl, int stream, int flag)
3277 {
3278 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
3279 	usb_ac_plumbed_t	*plumb_infop = NULL;
3280 	usb_ac_streams_info_t	*streams_infop = NULL;
3281 	int	dir;
3282 
3283 	ASSERT(uacp != NULL);
3284 
3285 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3286 	    "usb_ac_do_setup: Begin ahdl=0x%p, stream=%d, flag=%d",
3287 	    ahdl, stream, flag);
3288 
3289 	mutex_enter(&uacp->usb_ac_mutex);
3290 
3291 	dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3292 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3293 	ASSERT(plumb_infop != NULL);
3294 
3295 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3296 	ASSERT(streams_infop != NULL);
3297 
3298 	/*
3299 	 * Handle multiple setup calls. Pass the setup call to usb_as only
3300 	 * the first time so isoc pipe will be opened only once
3301 	 */
3302 	if (streams_infop->acs_setup_teardown_count++) {
3303 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3304 		    "usb_ac_do_setup: more than one setup, cnt=%d",
3305 		    streams_infop->acs_setup_teardown_count);
3306 
3307 		mutex_exit(&uacp->usb_ac_mutex);
3308 
3309 		return (USB_SUCCESS);
3310 	}
3311 
3312 	/* Send setup command to usb_as */
3313 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SETUP, 0) !=
3314 	    USB_SUCCESS) {
3315 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3316 		    "usb_ac_do_setup: failure");
3317 
3318 		streams_infop->acs_setup_teardown_count--;
3319 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3320 
3321 		mutex_exit(&uacp->usb_ac_mutex);
3322 
3323 		return (USB_FAILURE);
3324 	}
3325 
3326 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3327 
3328 	mutex_exit(&uacp->usb_ac_mutex);
3329 
3330 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3331 	    "usb_ac_do_setup: End");
3332 
3333 	return (USB_SUCCESS);
3334 }
3335 
3336 
3337 /*
3338  * usb_ac_teardown:
3339  *	Send teardown to usb_as if the last teardown
3340  *	Check power is done in usb_ac_send_as_cmd()
3341  *	NOTE: allow teardown when disconnected
3342  */
3343 static void
3344 usb_ac_teardown(audiohdl_t ahdl, int stream, int flag)
3345 {
3346 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
3347 
3348 	ASSERT(uacp != NULL);
3349 
3350 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3351 	    "usb_ac_teardown: Begin ahdl=0x%p, stream=%d",
3352 	    ahdl, stream);
3353 
3354 	usb_ac_serialize_access(uacp);
3355 
3356 	if (flag & AUDIO_PLAY) {
3357 		usb_ac_do_teardown(ahdl, stream, AUDIO_PLAY);
3358 	}
3359 
3360 	if (flag & AUDIO_RECORD) {
3361 		usb_ac_do_teardown(ahdl, stream, AUDIO_RECORD);
3362 	}
3363 
3364 	usb_ac_release_access(uacp);
3365 
3366 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3367 	    "usb_ac_teardown: End");
3368 }
3369 
3370 
3371 /*
3372  * usb_ac_do_teardown()
3373  *	Check power is done in usb_ac_send_as_cmd()
3374  */
3375 static void
3376 usb_ac_do_teardown(audiohdl_t ahdl, int stream, int flag)
3377 {
3378 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
3379 	usb_ac_plumbed_t	*plumb_infop = NULL;
3380 	usb_ac_streams_info_t	*streams_infop = NULL;
3381 	int			dir;
3382 
3383 	ASSERT(uacp != NULL);
3384 
3385 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3386 	    "usb_ac_do_teardown: Begin ahdl=0x%p, stream=%d",
3387 	    ahdl, stream);
3388 
3389 	mutex_enter(&uacp->usb_ac_mutex);
3390 
3391 	dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3392 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3393 	ASSERT(plumb_infop != NULL);
3394 
3395 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3396 	ASSERT(streams_infop != NULL);
3397 
3398 	/* There should be at least one matching setup call */
3399 	ASSERT(streams_infop->acs_setup_teardown_count);
3400 
3401 	/*
3402 	 * Handle multiple setup/teardown calls. Pass the call to usb_as
3403 	 * only this is the last teardown so that isoc pipe is closed
3404 	 * only once
3405 	 */
3406 	if (--(streams_infop->acs_setup_teardown_count)) {
3407 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3408 		    "usb_ac_do_teardown: more than one setup/teardown, "
3409 		    "cnt=%d",
3410 		    streams_infop->acs_setup_teardown_count);
3411 
3412 		mutex_exit(&uacp->usb_ac_mutex);
3413 
3414 		return;
3415 	}
3416 
3417 	/* Send teardown command to usb_as */
3418 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_TEARDOWN,
3419 	    (void *)NULL) != USB_SUCCESS) {
3420 
3421 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3422 		    "usb_ac_do_teardown: failure");
3423 
3424 		streams_infop->acs_setup_teardown_count++;
3425 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3426 
3427 		mutex_exit(&uacp->usb_ac_mutex);
3428 
3429 		return;
3430 	}
3431 
3432 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
3433 
3434 	mutex_exit(&uacp->usb_ac_mutex);
3435 
3436 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3437 	    "usb_ac_do_teardown: End");
3438 }
3439 
3440 
3441 /*
3442  * usb_ac_set_config:
3443  *	This routine will send control commands to get the max
3444  *	and min gain balance, calculate the gain to be set from the
3445  *	arguments and send another control command to set it.
3446  *	Check power is done here since we will access the default pipe
3447  */
3448 static int
3449 usb_ac_set_config(audiohdl_t ahdl, int stream, int command, int flag,
3450 	int arg1, int arg2)
3451 {
3452 	usb_ac_state_t	*uacp = audio_sup_get_private(ahdl);
3453 	char		*what;
3454 	int		rval = AUDIO_FAILURE;
3455 	uint_t		channel;
3456 	uchar_t 	n_channels = 0;
3457 	uint_t		dir, count;
3458 	short		muteval;
3459 
3460 	ASSERT(uacp != NULL);
3461 
3462 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3463 	    "usb_ac_set_config: Begin ahdl=0x%p\n\t"
3464 	    "stream=%d, cmd=%d, flag=%d, arg1=%d, arg2=%d",
3465 	    ahdl, stream, command, flag, arg1, arg2);
3466 
3467 	mutex_enter(&uacp->usb_ac_mutex);
3468 	if (uacp->usb_ac_plumbing_state < USB_AC_STATE_PLUMBED) {
3469 		mutex_exit(&uacp->usb_ac_mutex);
3470 
3471 		return (AUDIO_FAILURE);
3472 	}
3473 
3474 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3475 		mutex_exit(&uacp->usb_ac_mutex);
3476 
3477 		return (AUDIO_FAILURE);
3478 	}
3479 	mutex_exit(&uacp->usb_ac_mutex);
3480 	usb_ac_serialize_access(uacp);
3481 	mutex_enter(&uacp->usb_ac_mutex);
3482 
3483 	switch (command) {
3484 	case AM_SET_GAIN:
3485 		/*
3486 		 * Set the gain for a channel. The audio mixer calculates the
3487 		 * impact, if any, on the channel's gain.
3488 		 *
3489 		 *	0 <= gain <= AUDIO_MAX_GAIN
3490 		 *
3491 		 *	arg1 --> gain
3492 		 *	arg2 --> channel #, 0 == left, 1 == right
3493 		 */
3494 		what = "gain";
3495 		channel = ++arg2;
3496 		ASSERT(flag != AUDIO_BOTH);
3497 		dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3498 
3499 		/*
3500 		 * We service the set_config command when the device is
3501 		 * plumbed and opened.
3502 		 */
3503 		n_channels = usb_ac_get_curr_n_channels(uacp, dir);
3504 
3505 		if (channel > n_channels) {
3506 			USB_DPRINTF_L2(PRINT_MASK_ALL,
3507 			    uacp->usb_ac_log_handle,
3508 			    "usb_ac_set_config: channel(%d) passed is "
3509 			    " > n_channels(%d)", channel, n_channels);
3510 
3511 			goto done;
3512 		}
3513 		count = 0;
3514 		(void) usb_ac_set_control(uacp, dir,
3515 			    USB_AUDIO_FEATURE_UNIT, channel,
3516 			    USB_AUDIO_VOLUME_CONTROL,
3517 			    USB_AC_FIND_ALL, &count, arg1, usb_ac_set_gain);
3518 
3519 		/*
3520 		 * If feature unit id could not be found, it probably means
3521 		 * volume/gain control is not available for this device.
3522 		 * and we just return success if we haven't completed
3523 		 * the registration with the mixer yet
3524 		 */
3525 		if (count == 0) {
3526 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3527 			    "mixer=%d,	no featureID, arg1=%d",
3528 			    uacp->usb_ac_registered_with_mixer, arg1);
3529 			rval = (uacp->usb_ac_registered_with_mixer == 0) ?
3530 					AUDIO_SUCCESS : AUDIO_FAILURE;
3531 		} else {
3532 			rval = AUDIO_SUCCESS;
3533 		}
3534 
3535 		break;
3536 	case AM_SET_PORT:
3537 		what = "port";
3538 		ASSERT(flag != AUDIO_BOTH);
3539 		dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3540 
3541 		rval = usb_ac_set_port(uacp, dir, arg1);
3542 		rval = (rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE;
3543 
3544 		break;
3545 	case AM_SET_MONITOR_GAIN:
3546 		what = "monitor gain";
3547 		channel = ++arg2;
3548 		dir = AUDIO_RECORD;
3549 
3550 		/*
3551 		 * We service the set_config command when the device is
3552 		 * plumbed and opened.
3553 		 */
3554 		n_channels = usb_ac_get_curr_n_channels(uacp, dir);
3555 
3556 		if (channel > n_channels) {
3557 			USB_DPRINTF_L2(PRINT_MASK_ALL,
3558 			    uacp->usb_ac_log_handle,
3559 			    "usb_ac_set_config: channel(%d) passed is "
3560 			    " > n_channels(%d)", channel, n_channels);
3561 
3562 			goto done;
3563 		}
3564 		count = 0;
3565 		(void) usb_ac_set_monitor_gain_control(uacp, dir,
3566 			    USB_AUDIO_INPUT_TERMINAL, channel,
3567 			    USB_AUDIO_VOLUME_CONTROL,
3568 			    USB_AC_FIND_ALL, &count, arg1,
3569 			    usb_ac_set_monitor_gain);
3570 
3571 		/*
3572 		 * always return success since we told the mixer
3573 		 * we always support this and sdtaudiocontrol displays
3574 		 * monitor gain regardless.
3575 		 */
3576 		rval = AUDIO_SUCCESS;
3577 
3578 		break;
3579 	case AM_OUTPUT_MUTE:
3580 		what = "mute";
3581 		ASSERT(flag != AUDIO_BOTH);
3582 		dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3583 
3584 		/*
3585 		 * arg1 != 0 --> mute
3586 		 * arg1 == 0 --> unmute
3587 		 * arg2 --> not used
3588 		 */
3589 		muteval = (arg1 == 0) ? USB_AUDIO_MUTE_OFF :
3590 					USB_AUDIO_MUTE_ON;
3591 		count = 0;
3592 		(void) usb_ac_set_control(uacp, dir,
3593 			    USB_AUDIO_FEATURE_UNIT, 0,
3594 			    USB_AUDIO_MUTE_CONTROL,
3595 			    USB_AC_FIND_ALL, &count, muteval,
3596 			    usb_ac_set_mute);
3597 
3598 		rval = (count == 0) ? AUDIO_FAILURE : AUDIO_SUCCESS;
3599 
3600 		break;
3601 	case AM_MIC_BOOST:
3602 		what = "mic boost";
3603 		rval = AUDIO_SUCCESS;
3604 		break;
3605 	case AM_SET_GAIN_BAL:
3606 		what = "set gain bal";
3607 		rval = AUDIO_FAILURE;
3608 		break;
3609 	default:
3610 		what = "unknown";
3611 		rval = AUDIO_FAILURE;
3612 	}
3613 
3614 done:
3615 	mutex_exit(&uacp->usb_ac_mutex);
3616 
3617 	/* Now it's safe to release access to other routines */
3618 	usb_ac_release_access(uacp);
3619 
3620 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3621 	    "usb_ac_set_config: %s done, rval=%d", what, rval);
3622 
3623 	return (rval);
3624 }
3625 
3626 
3627 /*
3628  * usb_ac_set_monitor_gain:
3629  *	called for each output terminal which supports
3630  *	from usb_ac_traverse_connections
3631  */
3632 static int
3633 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
3634     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
3635 {
3636 	usb_audio_output_term_descr_t *d =
3637 			    uacp->usb_ac_units[unit].acu_descriptor;
3638 
3639 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3640 	    "usb_ac_set_monitor_gain: ");
3641 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3642 	    "id=%d dir=%d ch=%d cntl=%d gain=%d type=%d term type=0x%x",
3643 	    unit, dir, channel, control, gain,
3644 	    uacp->usb_ac_unit_type[unit], d->wTerminalType);
3645 
3646 	/* log how we got here */
3647 	usb_ac_push_unit_id(uacp, unit);
3648 	usb_ac_show_traverse_path(uacp);
3649 	usb_ac_pop_unit_id(uacp, unit);
3650 
3651 	/* we only care about the ITs connected to real hw inputs */
3652 	switch (d->wTerminalType) {
3653 	case USB_AUDIO_TERM_TYPE_STREAMING:
3654 
3655 		return (USB_FAILURE);
3656 
3657 	case USB_AUDIO_TERM_TYPE_DT_MICROPHONE:
3658 	case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE:
3659 	case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE:
3660 	case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY:
3661 	case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY:
3662 	default:
3663 
3664 		break;
3665 	}
3666 
3667 	/*
3668 	 * we can only do this if the microphone is mixed into the
3669 	 * audio output so look for a mixer first
3670 	 */
3671 	if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) ==
3672 	    USB_SUCCESS) {
3673 		int i, id;
3674 
3675 		/* now look for a feature unit */
3676 		for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0;
3677 		    i--) {
3678 			id = uacp->usb_ac_traverse_path[i];
3679 
3680 			switch (uacp->usb_ac_unit_type[id]) {
3681 			case USB_AUDIO_MIXER_UNIT:
3682 
3683 				/* the FU should be before the mixer */
3684 				return (USB_FAILURE);
3685 
3686 			case USB_AUDIO_FEATURE_UNIT:
3687 				/*
3688 				 * now set the volume
3689 				 */
3690 				if (usb_ac_set_gain(uacp, id, dir, channel,
3691 				    control, gain, depth) != USB_SUCCESS) {
3692 
3693 					/* try master channel */
3694 					if (usb_ac_set_gain(uacp, id, dir,
3695 					    0, control, gain, depth) !=
3696 					    USB_SUCCESS) {
3697 
3698 						return (USB_FAILURE);
3699 					}
3700 				}
3701 
3702 				return (USB_SUCCESS);
3703 
3704 			default:
3705 				continue;
3706 			}
3707 		}
3708 	}
3709 
3710 	return (USB_FAILURE);
3711 }
3712 
3713 
3714 /*
3715  * usb_ac_set_gain is called for each feature unit which supports
3716  * the requested controls from usb_ac_traverse_connections
3717  * we still need to check whether this unit supports the requested
3718  * control.
3719  */
3720 static int
3721 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
3722     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
3723 {
3724 	short max, min, current;
3725 
3726 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3727 	    "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
3728 	    featureID, dir, channel, control, gain);
3729 
3730 	if (usb_ac_feature_unit_check(uacp, featureID,
3731 	    dir, channel, control, gain, depth) != USB_SUCCESS) {
3732 
3733 		return (USB_FAILURE);
3734 	}
3735 
3736 	if ((max = usb_ac_get_maxmin_volume(uacp, channel,
3737 	    USB_AUDIO_GET_MAX, dir, featureID)) == USB_FAILURE) {
3738 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3739 		    "usb_ac_set_gain: getting max gain failed");
3740 
3741 		return (USB_FAILURE);
3742 	}
3743 
3744 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3745 	    "usb_ac_set_gain: channel %d, max=%d", channel, max);
3746 
3747 	if ((min = usb_ac_get_maxmin_volume(uacp, channel,
3748 	    USB_AUDIO_GET_MIN, dir, featureID)) == USB_FAILURE) {
3749 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3750 		    "usb_ac_set_gain: getting min gain failed");
3751 
3752 		return (USB_FAILURE);
3753 	}
3754 
3755 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3756 	    "usb_ac_set_gain: channel=%d, min=%d", channel, min);
3757 
3758 	if ((current = usb_ac_get_maxmin_volume(uacp, channel,
3759 	    USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) {
3760 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3761 		    "usb_ac_set_gain: getting cur gain failed");
3762 
3763 		return (USB_FAILURE);
3764 	}
3765 
3766 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3767 	    "usb_ac_set_gain: channel=%d, cur=%d", channel, current);
3768 
3769 	/*
3770 	 * Set the gain for a channel. The audio mixer calculates the
3771 	 * impact, if any, on the channel's gain.
3772 	 *
3773 	 *	0 <= gain <= AUDIO_MAX_GAIN
3774 	 *
3775 	 *	channel #, 0 == left, 1 == right
3776 	 */
3777 
3778 	if (gain == 0) {
3779 		gain = USB_AUDIO_VOLUME_SILENCE;
3780 	} else {
3781 		gain = max - ((max - min) * (0x100 - gain))/0x100;
3782 	}
3783 
3784 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3785 	    "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
3786 	    channel, dir, max, min, gain);
3787 
3788 	if (usb_ac_set_volume(uacp, channel, gain, dir,
3789 	    featureID) != USB_SUCCESS) {
3790 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3791 		    "usb_ac_set_gain: setting volume failed");
3792 
3793 		return (USB_FAILURE);
3794 	}
3795 
3796 	/* just curious, read it back, device may round up/down */
3797 	if ((current = usb_ac_get_maxmin_volume(uacp, channel,
3798 	    USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) {
3799 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3800 		    "usb_ac_set_gain: getting cur gain failed");
3801 	}
3802 
3803 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3804 	    "usb_ac_set_gain done: "
3805 	    "id=%d channel=%d, cur=%d gain=%d", featureID, channel,
3806 	    (ushort_t)current, (ushort_t)gain);
3807 
3808 	return (USB_SUCCESS);
3809 }
3810 
3811 
3812 /*
3813  * usb_ac_set_format
3814  *	This mixer callback initiates a command to be sent to
3815  *	usb_as to select an alternate with the passed characteristics
3816  *	and also to set the sample frequency.
3817  *	Note that this may be called when a playing is going on in
3818  *	the streaming interface. To handle that, first stop
3819  *	playing/recording, close the pipe by sending a teardown
3820  *	command, send the set_format command down and then reopen
3821  *	the pipe. Note : (1) audio framework will restart play/record
3822  *	after a set_format command. (2) Check power is done in
3823  *	usb_ac_send_as_cmd().
3824  */
3825 static int
3826 usb_ac_set_format(audiohdl_t ahdl, int stream, int flag,
3827 	int sample, int channels, int precision, int encoding)
3828 {
3829 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
3830 	usb_audio_formats_t	*format;
3831 	usb_audio_formats_t	old_format;
3832 	usb_ac_plumbed_t	*plumb_infop;
3833 	usb_ac_streams_info_t	*streams_infop = NULL;
3834 	int			old_setup_teardown_count;
3835 	int			dir;
3836 	int			rval;
3837 
3838 	ASSERT(uacp != NULL);
3839 
3840 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3841 	    "usb_ac_set_format: Begin ahdl=0x%p, stream=%d, flag=%d, "
3842 	    "sr=%d, chnls=%d, prec=%d, enc=%d", ahdl, stream, flag,
3843 	    sample, channels, precision, encoding);
3844 
3845 	mutex_enter(&uacp->usb_ac_mutex);
3846 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3847 		mutex_exit(&uacp->usb_ac_mutex);
3848 
3849 		return (AUDIO_FAILURE);
3850 	}
3851 	mutex_exit(&uacp->usb_ac_mutex);
3852 
3853 	usb_ac_serialize_access(uacp);
3854 
3855 	ASSERT(flag != AUDIO_BOTH);
3856 
3857 	mutex_enter(&uacp->usb_ac_mutex);
3858 	dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD;
3859 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3860 	if (plumb_infop == NULL) {
3861 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3862 		    "usb_ac_set_format: no plumb info");
3863 		mutex_exit(&uacp->usb_ac_mutex);
3864 
3865 		usb_ac_release_access(uacp);
3866 
3867 		return (AUDIO_FAILURE);
3868 	}
3869 
3870 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3871 	ASSERT(streams_infop != NULL);
3872 
3873 	/* isoc pipe not open and playing is not in progress */
3874 	if (streams_infop->acs_setup_teardown_count == 0) {
3875 
3876 		mutex_exit(&uacp->usb_ac_mutex);
3877 
3878 		rval = usb_ac_send_format_cmd(ahdl, stream, dir, sample,
3879 		    channels, precision, encoding);
3880 
3881 		usb_ac_release_access(uacp);
3882 
3883 		return ((rval == USB_SUCCESS) ?
3884 		    AUDIO_SUCCESS : AUDIO_FAILURE);
3885 	}
3886 
3887 	/* isoc pipe is open and playing might be in progress */
3888 	format = &streams_infop->acs_ac_to_as_req.acr_curr_format;
3889 
3890 	/* Keep a copy of the old format */
3891 	bcopy((void *)format, (void *)&old_format,
3892 	    sizeof (usb_audio_formats_t));
3893 
3894 	ASSERT(streams_infop->acs_setup_teardown_count != 0);
3895 
3896 	old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3897 	streams_infop->acs_setup_teardown_count = 1;
3898 
3899 	mutex_exit(&uacp->usb_ac_mutex);
3900 
3901 	if (dir == AUDIO_PLAY) {
3902 		usb_ac_do_pause_play(ahdl, stream);
3903 	} else if (dir == AUDIO_RECORD) {
3904 		usb_ac_do_stop_record(ahdl, stream);
3905 	}
3906 
3907 	/* This blocks until the current isoc xfer is over */
3908 	usb_ac_do_teardown(ahdl, stream, dir);
3909 
3910 	if (usb_ac_send_format_cmd(ahdl, stream, dir, sample,
3911 	    channels, precision, encoding) != USB_SUCCESS) {
3912 		/*
3913 		 * Setting new alternate has failed, try restoring
3914 		 * old one.
3915 		 * If there is a bandwidth failure, hang around
3916 		 * till bandwidth is available. Also we know that
3917 		 * there is a matching alternate, so that can't fail.
3918 		 */
3919 		if (usb_ac_send_format_cmd(ahdl, stream, dir,
3920 		    old_format.fmt_sr, old_format.fmt_chns,
3921 		    old_format.fmt_precision, old_format.fmt_encoding) ==
3922 		    USB_FAILURE) {
3923 
3924 			/* We closed the pipe; reopen it */
3925 			(void) usb_ac_do_setup(ahdl, stream, dir);
3926 
3927 			mutex_enter(&uacp->usb_ac_mutex);
3928 			streams_infop->acs_setup_teardown_count =
3929 			    old_setup_teardown_count;
3930 			mutex_exit(&uacp->usb_ac_mutex);
3931 
3932 			usb_ac_release_access(uacp);
3933 
3934 			return (AUDIO_FAILURE);
3935 		}
3936 	}
3937 
3938 	/* This should block until successful */
3939 	(void) usb_ac_do_setup(ahdl, stream, dir);
3940 
3941 	mutex_enter(&uacp->usb_ac_mutex);
3942 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3943 	mutex_exit(&uacp->usb_ac_mutex);
3944 
3945 	usb_ac_release_access(uacp);
3946 
3947 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3948 	    "usb_ac_set_format: End");
3949 
3950 	return (AUDIO_SUCCESS);
3951 }
3952 
3953 
3954 /*
3955  * usb_ac_get_curr_n_channels:
3956  *	Return no. of channels from the current format table
3957  */
3958 static int
3959 usb_ac_get_curr_n_channels(usb_ac_state_t *uacp, int dir)
3960 {
3961 	usb_audio_formats_t *cur_fmt = usb_ac_get_curr_format(uacp, dir);
3962 
3963 	return (cur_fmt->fmt_chns);
3964 }
3965 
3966 
3967 /*
3968  * usb_ac_get_cur_format:
3969  *	Get format for the current alternate
3970  */
3971 static usb_audio_formats_t *
3972 usb_ac_get_curr_format(usb_ac_state_t *uacp, int dir)
3973 {
3974 	usb_ac_plumbed_t *plumb_infop;
3975 	usb_ac_streams_info_t *streams_infop = NULL;
3976 
3977 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3978 
3979 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
3980 	if (plumb_infop == NULL) {
3981 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3982 		    "usb_ac_get_curr_format: no plumb info");
3983 
3984 		return (NULL);
3985 	}
3986 
3987 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
3988 	ASSERT(streams_infop != NULL);
3989 
3990 	return (&streams_infop->acs_cur_fmt);
3991 }
3992 
3993 
3994 /*
3995  * usb_ac_send_format_cmd
3996  *	Sets format and get alternate setting that matches with
3997  *	the format from the usb_as playing or recording interface
3998  *	Send the set sample freq command down to usb_as.
3999  */
4000 static int
4001 usb_ac_send_format_cmd(audiohdl_t ahdl, int stream, int dir,
4002 	int sample, int channels, int precision, int encoding)
4003 {
4004 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
4005 	usb_audio_formats_t	*format;
4006 	usb_ac_plumbed_t	*plumb_infop = NULL;
4007 	usb_ac_streams_info_t	*streams_infop = NULL;
4008 
4009 	ASSERT(uacp != NULL);
4010 
4011 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4012 	    "usb_ac_send_format_cmd: Begin ahdl=0x%p, stream=%d, dir=%d, "
4013 	    "sr=%d, chnls=%d, prec=%d, enc=%d", ahdl, stream, dir,
4014 	    sample, channels, precision, encoding);
4015 
4016 	mutex_enter(&uacp->usb_ac_mutex);
4017 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4018 		mutex_exit(&uacp->usb_ac_mutex);
4019 
4020 		return (USB_FAILURE);
4021 	}
4022 
4023 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir);
4024 	ASSERT(plumb_infop);
4025 
4026 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4027 	ASSERT(streams_infop != NULL);
4028 
4029 	ASSERT(dir == AUDIO_PLAY || dir == AUDIO_RECORD);
4030 	streams_infop->acs_ac_to_as_req.acr_curr_dir = dir;
4031 
4032 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4033 	    "usb_ac_send_format_cmd: plumb_infop=0x%p, streams_infop=0x%p",
4034 	    plumb_infop, streams_infop);
4035 
4036 	format = &(streams_infop->acs_ac_to_as_req.acr_curr_format);
4037 	bzero(format, sizeof (usb_audio_formats_t));
4038 
4039 	/* save format info */
4040 	format->fmt_sr		= (uint_t)sample;
4041 	format->fmt_chns	= (uchar_t)channels;
4042 	format->fmt_precision	= (uchar_t)precision;
4043 	format->fmt_encoding	= (uchar_t)encoding;
4044 
4045 	streams_infop->acs_cur_fmt = *format;
4046 
4047 	/*
4048 	 * Set format for the streaming interface with lower write queue
4049 	 * This boils down to set_alternate  interface command in
4050 	 * usb_as and the reply mp contains the currently active
4051 	 * alternate number that is stored in the as_req structure
4052 	 */
4053 	if (usb_ac_send_as_cmd(uacp, plumb_infop,
4054 	    USB_AUDIO_SET_FORMAT, format) != USB_SUCCESS) {
4055 		USB_DPRINTF_L2(PRINT_MASK_ALL,
4056 		    uacp->usb_ac_log_handle,
4057 		    "usb_ac_send_format_cmd: failed");
4058 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4059 		mutex_exit(&uacp->usb_ac_mutex);
4060 
4061 		return (USB_FAILURE);
4062 	} else {
4063 		/* alternate number stored and reply mp freed */
4064 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4065 	}
4066 
4067 	/* Set the sample rate */
4068 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SET_SAMPLE_FREQ,
4069 	    &sample) != USB_SUCCESS) {
4070 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4071 		    "usb_ac_send_format_cmd: setting format failed");
4072 
4073 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4074 		mutex_exit(&uacp->usb_ac_mutex);
4075 
4076 		return (USB_FAILURE);
4077 	}
4078 
4079 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4080 
4081 	mutex_exit(&uacp->usb_ac_mutex);
4082 
4083 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4084 	    "usb_ac_send_format_cmd: End");
4085 
4086 	return (USB_SUCCESS);
4087 }
4088 
4089 
4090 /*
4091  * usb_ac_start_play
4092  *	Send a start_play command down to usb_as
4093  *	Check power is done in usb_ac_send_as_cmd()
4094  */
4095 static int
4096 usb_ac_start_play(audiohdl_t ahdl, int stream)
4097 {
4098 	usb_ac_state_t		*uacp = audio_sup_get_private(ahdl);
4099 	usb_audio_formats_t	*cur_fmt;
4100 	usb_ac_plumbed_t	*plumb_infop = NULL;
4101 	int			dir, samples;
4102 	usb_audio_play_req_t	play_req;
4103 	usb_ac_streams_info_t	*streams_infop = NULL;
4104 
4105 	ASSERT(uacp != NULL);
4106 
4107 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4108 	    "usb_ac_start_play: Begin ahdl=0x%p, stream=%d",
4109 	    ahdl, stream);
4110 
4111 	mutex_enter(&uacp->usb_ac_mutex);
4112 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4113 		mutex_exit(&uacp->usb_ac_mutex);
4114 
4115 		return (AUDIO_FAILURE);
4116 	}
4117 	mutex_exit(&uacp->usb_ac_mutex);
4118 
4119 	usb_ac_serialize_access(uacp);
4120 
4121 	mutex_enter(&uacp->usb_ac_mutex);
4122 
4123 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY);
4124 	ASSERT(plumb_infop);
4125 
4126 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4127 	ASSERT(streams_infop != NULL);
4128 
4129 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4130 	    "usb_ac_start_play: plumb_infop=0x%p, streams_infop=0x%p",
4131 	    plumb_infop, streams_infop);
4132 
4133 	dir = streams_infop->acs_ac_to_as_req.acr_curr_dir;
4134 	ASSERT(dir == AUDIO_PLAY);
4135 
4136 	cur_fmt = &streams_infop->acs_ac_to_as_req.acr_curr_format;
4137 
4138 	/* Check for continuous sample rate done in usb_as */
4139 	samples = cur_fmt->fmt_sr * cur_fmt->fmt_chns /
4140 				uacp->usb_ac_am_ad_info.ad_play.ad_int_rate;
4141 	if (samples & cur_fmt->fmt_chns) {
4142 		samples++;
4143 	}
4144 
4145 	play_req.up_samples = samples;
4146 	play_req.up_handle = ahdl;
4147 
4148 	/* Send setup command to usb_as */
4149 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_PLAY,
4150 	    (void *)&play_req) != USB_SUCCESS) {
4151 
4152 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4153 		    "usb_ac_start_play: failure");
4154 
4155 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4156 		mutex_exit(&uacp->usb_ac_mutex);
4157 
4158 		usb_ac_release_access(uacp);
4159 
4160 		return (AUDIO_FAILURE);
4161 	}
4162 
4163 	streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4164 	mutex_exit(&uacp->usb_ac_mutex);
4165 
4166 	usb_ac_release_access(uacp);
4167 
4168 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4169 	    "usb_ac_start_play: End");
4170 
4171 	return (AUDIO_SUCCESS);
4172 }
4173 
4174 
4175 /*
4176  * usb_ac_pause_play:
4177  *	Wrapper function for usb_ac_do_pause_play and gets
4178  *	called from mixer framework.
4179  */
4180 static void
4181 usb_ac_pause_play(audiohdl_t ahdl, int stream)
4182 {
4183 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4184 
4185 	ASSERT(uacp != NULL);
4186 
4187 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4188 	    "usb_ac_pause_play: Begin ahdl=0x%p, stream=%d",
4189 	    ahdl, stream);
4190 
4191 	mutex_enter(&uacp->usb_ac_mutex);
4192 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4193 		mutex_exit(&uacp->usb_ac_mutex);
4194 
4195 		return;
4196 	}
4197 	mutex_exit(&uacp->usb_ac_mutex);
4198 
4199 	usb_ac_serialize_access(uacp);
4200 	usb_ac_do_pause_play(ahdl, stream);
4201 	usb_ac_release_access(uacp);
4202 
4203 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4204 	    "usb_ac_pause_play: End");
4205 }
4206 
4207 /*
4208  * usb_ac_do_pause_play:
4209  *	Send a pause_play command to usb_as.
4210  *	Check power is done in usb_ac_send_as_cmd()
4211  */
4212 static void
4213 usb_ac_do_pause_play(audiohdl_t ahdl, int stream)
4214 {
4215 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4216 	usb_ac_plumbed_t	*plumb_infop = NULL;
4217 	usb_ac_streams_info_t	*streams_infop = NULL;
4218 
4219 	ASSERT(uacp != NULL);
4220 
4221 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4222 	    "usb_ac_do_pause_play: Begin ahdl=0x%p, stream=%d",
4223 	    ahdl, stream);
4224 
4225 	mutex_enter(&uacp->usb_ac_mutex);
4226 
4227 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY);
4228 	ASSERT(plumb_infop);
4229 
4230 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4231 	ASSERT(streams_infop != NULL);
4232 
4233 	/* Send setup command to usb_as */
4234 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_PAUSE_PLAY,
4235 	    (void *)NULL) != USB_SUCCESS) {
4236 
4237 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4238 		    "usb_ac_do_pause_play: failure");
4239 
4240 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4241 	}
4242 
4243 	mutex_exit(&uacp->usb_ac_mutex);
4244 
4245 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4246 	    "usb_ac_do_pause_play: End");
4247 }
4248 
4249 
4250 /*
4251  * usb_ac_stop_play:
4252  *	Wrapper function for usb_ac_pause_play	and gets
4253  *	called from mixer framework.
4254  */
4255 static void
4256 usb_ac_stop_play(audiohdl_t ahdl, int stream)
4257 {
4258 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4259 
4260 	ASSERT(uacp != NULL);
4261 
4262 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4263 	    "usb_ac_stop_play: Begin ahdl=0x%p, stream=%d",
4264 	    ahdl, stream);
4265 
4266 	usb_ac_pause_play(ahdl, stream);
4267 
4268 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4269 	    "usb_ac_stop_play: End");
4270 }
4271 
4272 
4273 /*
4274  * usb_ac_start_record:
4275  *	Sends a start record command down to usb_as.
4276  *	Check power is done in usb_ac_send_as_cmd()
4277  */
4278 static int
4279 usb_ac_start_record(audiohdl_t ahdl, int stream)
4280 {
4281 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4282 	usb_ac_plumbed_t	*plumb_infop = NULL;
4283 	usb_ac_streams_info_t	*streams_infop = NULL;
4284 
4285 	ASSERT(uacp != NULL);
4286 
4287 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4288 	    "usb_ac_start_record: Begin ahdl=0x%p, stream=%d",
4289 	    ahdl, stream);
4290 
4291 	mutex_enter(&uacp->usb_ac_mutex);
4292 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
4293 		mutex_exit(&uacp->usb_ac_mutex);
4294 
4295 		return (AUDIO_FAILURE);
4296 	}
4297 	mutex_exit(&uacp->usb_ac_mutex);
4298 
4299 	usb_ac_serialize_access(uacp);
4300 
4301 	mutex_enter(&uacp->usb_ac_mutex);
4302 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD);
4303 	ASSERT(plumb_infop);
4304 
4305 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4306 	ASSERT(streams_infop != NULL);
4307 
4308 	/* Send setup command to usb_as */
4309 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_RECORD,
4310 	    (void *)&ahdl) != USB_SUCCESS) {
4311 
4312 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4313 		    "usb_ac_start_record: failure");
4314 
4315 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4316 		mutex_exit(&uacp->usb_ac_mutex);
4317 
4318 		usb_ac_release_access(uacp);
4319 
4320 		return (AUDIO_FAILURE);
4321 	}
4322 
4323 	mutex_exit(&uacp->usb_ac_mutex);
4324 
4325 	usb_ac_release_access(uacp);
4326 
4327 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4328 	    "usb_ac_start_record: End");
4329 
4330 	return (AUDIO_SUCCESS);
4331 }
4332 
4333 
4334 /*
4335  * usb_ac_stop_record:
4336  *	Wrapper function for usb_ac_do_stop_record and is
4337  *	called form mixer framework.
4338  */
4339 static void
4340 usb_ac_stop_record(audiohdl_t ahdl, int stream)
4341 {
4342 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4343 
4344 	ASSERT(uacp != NULL);
4345 
4346 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4347 	    "usb_ac_stop_record: Begin ahdl=0x%p, stream=%d",
4348 	    ahdl, stream);
4349 
4350 	usb_ac_serialize_access(uacp);
4351 	usb_ac_do_stop_record(ahdl, stream);
4352 	usb_ac_release_access(uacp);
4353 
4354 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4355 	    "usb_ac_stop_record: End");
4356 }
4357 
4358 
4359 /*
4360  * usb_ac_do_stop_record:
4361  *	Sends a stop_record command down.
4362  *	Check power is done in usb_ac_send_as_cmd()
4363  */
4364 static void
4365 usb_ac_do_stop_record(audiohdl_t ahdl, int stream)
4366 {
4367 	usb_ac_state_t *uacp = audio_sup_get_private(ahdl);
4368 	usb_ac_plumbed_t	*plumb_infop = NULL;
4369 	usb_ac_streams_info_t	*streams_infop = NULL;
4370 
4371 	ASSERT(uacp != NULL);
4372 
4373 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4374 	    "usb_ac_do_stop_record: Begin ahdl=0x%p, stream=%d",
4375 	    ahdl, stream);
4376 
4377 	mutex_enter(&uacp->usb_ac_mutex);
4378 
4379 	plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD);
4380 	ASSERT(plumb_infop != NULL);
4381 
4382 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4383 	ASSERT(streams_infop != NULL);
4384 
4385 	/* Send setup command to usb_as */
4386 	if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_STOP_RECORD,
4387 	    NULL) != USB_SUCCESS) {
4388 
4389 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4390 		    "usb_ac_do_stop_record: failure");
4391 
4392 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4393 	}
4394 
4395 	mutex_exit(&uacp->usb_ac_mutex);
4396 
4397 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4398 	    "usb_ac_do_stop_record: End");
4399 }
4400 
4401 
4402 /*
4403  * Helper Functions for Mixer callbacks
4404  *
4405  * usb_ac_get_maxmin_volume:
4406  *	Send USBA command down to get the maximum or minimum gain balance
4407  *	Calculate min or max gain balance and return that. Return
4408  *	USB_FAILURE for failure cases
4409  */
4410 static int
4411 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
4412     int dir, int feature_unitID)
4413 {
4414 	mblk_t		*data = NULL;
4415 	short		max_or_min;
4416 	usb_cr_t	cr;
4417 	usb_cb_flags_t	cb_flags;
4418 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4419 	    "usb_ac_get_maxmin_volume: channel=%d, cmd=%d dir=%d",
4420 	    channel, cmd, dir);
4421 
4422 	mutex_exit(&uacp->usb_ac_mutex);
4423 
4424 	if (usb_pipe_sync_ctrl_xfer(
4425 	    uacp->usb_ac_dip,
4426 	    uacp->usb_ac_default_ph,
4427 	    USB_DEV_REQ_DEV_TO_HOST |
4428 	    USB_DEV_REQ_TYPE_CLASS |
4429 	    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
4430 	    cmd,			/* bRequest */
4431 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
4432 					/* feature unit and id */
4433 	    (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
4434 	    2,				/* wLength */
4435 	    &data,
4436 	    USB_ATTRS_NONE,
4437 	    &cr, &cb_flags,
4438 	    USB_FLAGS_SLEEP) != USB_SUCCESS) {
4439 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4440 		    "usb_ac_get_maxmin_volume: failed, "
4441 		    "cr=%d, cb=0x%x cmd=%d, data=0x%p",
4442 		    cr, cb_flags, cmd, data);
4443 
4444 		freemsg(data);
4445 		mutex_enter(&uacp->usb_ac_mutex);
4446 
4447 		return (USB_FAILURE);
4448 	}
4449 
4450 	mutex_enter(&uacp->usb_ac_mutex);
4451 	ASSERT((data->b_wptr - data->b_rptr) == 2);
4452 
4453 	max_or_min = (*(data->b_rptr+1) << 8) | *data->b_rptr;
4454 
4455 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4456 	    "usb_ac_get_maxmin_volume: max_or_min=0x%x", max_or_min);
4457 
4458 	freemsg(data);
4459 
4460 	return (max_or_min);
4461 }
4462 
4463 
4464 /*
4465  * usb_ac_set_volume:
4466  *	Send USBA command down to set the gain balance
4467  */
4468 static int
4469 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
4470     int feature_unitID)
4471 {
4472 	mblk_t		*data = NULL;
4473 	usb_cr_t	cr;
4474 	usb_cb_flags_t	cb_flags;
4475 	int		rval = USB_FAILURE;
4476 
4477 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4478 	    "usb_ac_set_volume: channel=%d gain=%d dir=%d FU=%d",
4479 	    channel, gain, dir, feature_unitID);
4480 
4481 	mutex_exit(&uacp->usb_ac_mutex);
4482 
4483 	/* Construct the mblk_t from gain for sending to USBA */
4484 	data = allocb_wait(4, BPRI_HI, STR_NOSIG, NULL);
4485 
4486 	*(data->b_wptr++) = (char)gain;
4487 	*(data->b_wptr++) = (char)(gain >> 8);
4488 
4489 	if ((rval = usb_pipe_sync_ctrl_xfer(
4490 	    uacp->usb_ac_dip,
4491 	    uacp->usb_ac_default_ph,
4492 	    USB_DEV_REQ_HOST_TO_DEV |
4493 	    USB_DEV_REQ_TYPE_CLASS |
4494 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
4495 	    USB_AUDIO_SET_CUR,			/* bRequest */
4496 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
4497 						/* feature unit and id */
4498 	    (feature_unitID << 8) | uacp->usb_ac_ifno,	/* wIndex */
4499 	    2,					/* wLength */
4500 	    &data, 0,
4501 	    &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
4502 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4503 		    "usb_ac_set_volume: failed, cr=%d cb=0x%x",
4504 		    cr, cb_flags);
4505 	}
4506 
4507 	freemsg(data);
4508 	mutex_enter(&uacp->usb_ac_mutex);
4509 
4510 	return (rval);
4511 }
4512 
4513 
4514 /*
4515  * usb_ac_set_mute is called for each unit that supports the
4516  * requested control from usb_ac_traverse_connections
4517  */
4518 static int
4519 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
4520     uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
4521 {
4522 	mblk_t		*data;
4523 	usb_cr_t	cr;
4524 	usb_cb_flags_t	cb_flags;
4525 	int		rval = USB_FAILURE;
4526 
4527 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4528 	    "usb_ac_set_mute: muteval=0x%x, dir=%d", muteval, dir);
4529 
4530 	if (usb_ac_feature_unit_check(uacp, featureID,
4531 	    dir, channel, control, 0, depth) != USB_SUCCESS) {
4532 
4533 		return (USB_FAILURE);
4534 	}
4535 
4536 	mutex_exit(&uacp->usb_ac_mutex);
4537 
4538 	/* Construct the mblk_t for sending to USBA */
4539 	data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL);
4540 	*(data->b_wptr++) = (char)muteval;
4541 
4542 	if ((rval = usb_pipe_sync_ctrl_xfer(
4543 	    uacp->usb_ac_dip,
4544 	    uacp->usb_ac_default_ph,
4545 	    USB_DEV_REQ_HOST_TO_DEV |
4546 	    USB_DEV_REQ_TYPE_CLASS |
4547 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
4548 	    USB_AUDIO_SET_CUR,			/* bRequest */
4549 	    (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
4550 						/* feature unit and id */
4551 	    (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
4552 	    1,					/* wLength */
4553 	    &data,
4554 	    0,					/* attributes */
4555 	    &cr, &cb_flags, 0)) != USB_SUCCESS) {
4556 
4557 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4558 		    "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
4559 	}
4560 
4561 	freemsg(data);
4562 	mutex_enter(&uacp->usb_ac_mutex);
4563 
4564 	return (rval);
4565 }
4566 
4567 
4568 /*
4569  * usb_ac_send_as_cmd:
4570  *	Allocate message blk, send a command down to usb_as,
4571  *	wait for the reply and free the message
4572  *
4573  *	although not really needed to raise power if sending to as
4574  *	it seems better to ensure that both interfaces are at full power
4575  */
4576 static int
4577 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_ac_plumbed_t *plumb_infop,
4578     int cmd, void *arg)
4579 {
4580 	mblk_t		*mp = NULL;
4581 	struct iocblk	*iocp;
4582 	queue_t 	*lwq = plumb_infop->acp_lwq;
4583 	usb_ac_streams_info_t *streams_infop;
4584 	int		error = USB_FAILURE;
4585 
4586 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4587 	ASSERT(plumb_infop != NULL);
4588 
4589 	streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data;
4590 	ASSERT(streams_infop != NULL);
4591 
4592 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4593 	    "usb_ac_send_as_cmd: Begin lwq=0x%p, cmd=0x%x, arg=0x%p",
4594 	    lwq, cmd, arg);
4595 
4596 	if (!canputnext(lwq)) {
4597 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4598 		    "usb_ac_send_as_cmd: canputnext failed");
4599 
4600 		return (error);
4601 	}
4602 
4603 	/*
4604 	 * Allocate mblk for a particular command
4605 	 */
4606 	switch (cmd) {
4607 	case USB_AUDIO_SET_FORMAT:
4608 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4609 		    sizeof (usb_audio_formats_t));
4610 		break;
4611 	case USB_AUDIO_TEARDOWN:
4612 	case USB_AUDIO_STOP_RECORD:
4613 	case USB_AUDIO_PAUSE_PLAY:
4614 	case USB_AUDIO_SETUP:
4615 		mp = usb_ac_allocate_req_mblk(uacp, cmd, NULL, 0);
4616 		break;
4617 	case USB_AUDIO_START_RECORD:
4618 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4619 		    sizeof (audiohdl_t *));
4620 		break;
4621 	case USB_AUDIO_SET_SAMPLE_FREQ:
4622 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4623 		    sizeof (int));
4624 		break;
4625 	case USB_AUDIO_START_PLAY:
4626 		mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg,
4627 		    sizeof (usb_audio_play_req_t));
4628 		break;
4629 	default:
4630 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4631 		    "usb_ac_send_as_cmd: unknown cmd=%d", cmd);
4632 
4633 		return (error);
4634 	}
4635 
4636 	if (mp == NULL) {
4637 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4638 		    "usb_ac_send_as_cmd: can't get mblk to send cmd down");
4639 
4640 		return (error);
4641 	}
4642 
4643 	/*
4644 	 * Set wait flag and send message down; we have made sure
4645 	 * before that canputnext succeeds. Note mp will be freed down
4646 	 */
4647 	streams_infop->acs_ac_to_as_req.acr_wait_flag = 1;
4648 
4649 	mutex_exit(&uacp->usb_ac_mutex);
4650 	putnext(lwq, mp);
4651 	mutex_enter(&uacp->usb_ac_mutex);
4652 
4653 	/*
4654 	 * Wait for the response; reply will arrive through rput()
4655 	 * M_CTL and the cv_wait will be signaled there and wait flag
4656 	 * will be reset
4657 	 */
4658 	while (streams_infop->acs_ac_to_as_req.acr_wait_flag) {
4659 #ifndef DEBUG
4660 		cv_wait(&streams_infop->acs_ac_to_as_req.acr_cv,
4661 		    &uacp->usb_ac_mutex);
4662 #else
4663 		clock_t tm = ddi_get_lbolt() +
4664 					drv_usectohz(usb_ac_wait_timeout);
4665 		int rval;
4666 
4667 		rval = cv_timedwait(&streams_infop->acs_ac_to_as_req.acr_cv,
4668 		    &uacp->usb_ac_mutex, tm);
4669 
4670 		if (streams_infop->acs_ac_to_as_req.acr_wait_flag) {
4671 			if (rval == -1) {
4672 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4673 				    uacp->usb_ac_log_handle,
4674 				    "usb_ac_send_as_cmd:"
4675 				    " timeout happen before cmd complete.");
4676 			} else {
4677 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4678 				    uacp->usb_ac_log_handle,
4679 				    "usb_ac_send_as_cmd:"
4680 				    " not signaled by USB_AS_PLUMBED.");
4681 			}
4682 		}
4683 #endif
4684 	}
4685 
4686 	/* Wait is over, get the reply data */
4687 	mp = streams_infop->acs_ac_to_as_req.acr_reply_mp;
4688 	ASSERT(mp != NULL);
4689 
4690 	iocp = (struct iocblk *)mp->b_rptr;
4691 
4692 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4693 	    "usb_ac_send_as_cmd: db_type=0x%x cmd=0x%x",
4694 	    mp->b_datap->db_type, iocp->ioc_cmd);
4695 
4696 	switch (mp->b_datap->db_type) {
4697 	case M_CTL:
4698 		switch (iocp->ioc_cmd) {
4699 		case USB_AUDIO_SET_FORMAT:
4700 			/*
4701 			 * This command sets mixer format data
4702 			 * and returns alternate setting that matches
4703 			 */
4704 			ASSERT(mp->b_cont != NULL);
4705 			ASSERT((mp->b_cont->b_wptr - mp->b_cont->b_rptr) ==
4706 			    sizeof (int));
4707 			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4708 			    "alternate returned %d",
4709 			    *((int *)(mp->b_cont->b_rptr)));
4710 
4711 			streams_infop->acs_ac_to_as_req.acr_curr_format.
4712 			    fmt_alt = *((int *)(mp->b_cont->b_rptr));
4713 
4714 			/*FALLTHROUGH*/
4715 		case USB_AUDIO_SET_SAMPLE_FREQ:
4716 		case USB_AUDIO_SETUP:
4717 		case USB_AUDIO_START_PLAY:
4718 		case USB_AUDIO_PAUSE_PLAY:
4719 		case USB_AUDIO_START_RECORD:
4720 		case USB_AUDIO_STOP_RECORD:
4721 		case USB_AUDIO_TEARDOWN:
4722 			error = USB_SUCCESS;
4723 			break;
4724 		default:
4725 			break;
4726 		}
4727 		break;
4728 	case M_ERROR:
4729 	default:
4730 		error = USB_FAILURE;
4731 	}
4732 
4733 	if (mp) {
4734 		usb_ac_free_mblk(mp);
4735 		streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL;
4736 	}
4737 
4738 	return (error);
4739 }
4740 
4741 
4742 /*
4743  * usb_ac_allocate_req_mblk:
4744  *	Allocate a message block with the specified M_CTL cmd,
4745  *	The 2nd mblk contains the data for the command with a length len
4746  */
4747 static mblk_t *
4748 usb_ac_allocate_req_mblk(usb_ac_state_t *uacp, int cmd, void *buf, uint_t len)
4749 {
4750 	mblk_t	*mp, *mp2;
4751 	struct iocblk *mctlmsg;
4752 
4753 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4754 	    "usb_ac_allocate_req_mblk: cmd=0x%x, buf=0x%p, len=%d",
4755 	    cmd, buf, len);
4756 
4757 	mp = allocb_wait(sizeof (struct iocblk), BPRI_HI, STR_NOSIG, NULL);
4758 	mp->b_datap->db_type = M_CTL;
4759 	mctlmsg = (struct iocblk *)mp->b_datap->db_base;
4760 	mctlmsg->ioc_cmd = cmd;
4761 	mctlmsg->ioc_count = len;
4762 
4763 	mp->b_wptr = mp->b_wptr + sizeof (struct iocblk);
4764 
4765 	if ((len == 0) || (buf == NULL)) {
4766 
4767 		return (mp);
4768 	}
4769 
4770 	mp2 = allocb_wait(len, BPRI_HI, STR_NOSIG, NULL);
4771 	mp->b_cont = mp2;
4772 	bcopy(buf, mp->b_cont->b_datap->db_base, len);
4773 	mp->b_cont->b_wptr = mp->b_cont->b_wptr + len;
4774 
4775 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4776 	    "usb_ac_allocate_req_mblk: mp=0x%p", mp);
4777 
4778 	return (mp);
4779 }
4780 
4781 
4782 /*
4783  * usb_ac_free_mblk:
4784  *	Free the message block
4785  */
4786 static void
4787 usb_ac_free_mblk(mblk_t *mp)
4788 {
4789 	if (mp->b_cont) {
4790 		freemsg(mp->b_cont);
4791 		mp->b_cont = NULL;
4792 	}
4793 	freemsg(mp);
4794 }
4795 
4796 
4797 /*
4798  * usb_ac_serialize/release_access:
4799  */
4800 static void
4801 usb_ac_serialize_access(usb_ac_state_t	*uacp)
4802 {
4803 	(void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
4804 }
4805 
4806 static void
4807 usb_ac_release_access(usb_ac_state_t *uacp)
4808 {
4809 	usb_release_access(uacp->usb_ac_ser_acc);
4810 }
4811 
4812 
4813 static void
4814 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
4815 {
4816 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
4817 
4818 	if (usb_ac_statep->usb_ac_pm != NULL) {
4819 		mutex_enter(&usb_ac_statep->usb_ac_mutex);
4820 		usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
4821 
4822 		USB_DPRINTF_L4(PRINT_MASK_PM,
4823 		    usb_ac_statep->usb_ac_log_handle,
4824 		    "usb_ac_pm_busy_component: %d",
4825 		    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
4826 
4827 		mutex_exit(&usb_ac_statep->usb_ac_mutex);
4828 
4829 		if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
4830 		    DDI_SUCCESS) {
4831 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
4832 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
4833 
4834 			USB_DPRINTF_L2(PRINT_MASK_PM,
4835 			    usb_ac_statep->usb_ac_log_handle,
4836 			    "usb_ac_pm_busy_component failed: %d",
4837 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
4838 
4839 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
4840 		}
4841 	}
4842 }
4843 
4844 
4845 static void
4846 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
4847 {
4848 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
4849 
4850 	if (usb_ac_statep->usb_ac_pm != NULL) {
4851 		if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
4852 		    DDI_SUCCESS) {
4853 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
4854 			ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
4855 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
4856 
4857 			USB_DPRINTF_L4(PRINT_MASK_PM,
4858 			    usb_ac_statep->usb_ac_log_handle,
4859 			    "usb_ac_pm_idle_component: %d",
4860 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
4861 
4862 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
4863 		}
4864 	}
4865 }
4866