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