xref: /illumos-gate/usr/src/uts/common/io/usb/clients/audio/usb_ac/usb_ac.c (revision 458f44a49dc56cd17a39815122214e7a1b4793e3)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * AUDIO CONTROL Driver:
28  *
29  * usb_ac is a multiplexor that sits on top of usb_as and hid and is
30  * responsible for (1) providing the entry points to audio mixer framework,
31  * (2) passing control commands to and from usb_as and hid and (3) processing
32  * control messages from hid/usb_ah 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: A competing thread can't be allowed to interfere with
47  * (1) pipe, (2) streams state.
48  * So we need some kind of serialization among the asynchronous
49  * threads that can run in the driver. The serialization is mostly
50  * needed to avoid races among open/close/events/power entry points
51  * etc. Once a routine takes control, it checks if the resource (pipe or
52  * stream or dev state) is still accessible. If so, it proceeds with
53  * its job and until it completes, no other thread requiring the same
54  * resource can run.
55  *
56  * PM model in usb_ac: Raise power during attach. If a device is not at full
57  * power, raise power in the entry points. After the command is over,
58  * pm_idle_component() is called. The power is lowered in detach().
59  */
60 #include <sys/usb/usba/usbai_version.h>
61 #include <sys/usb/usba.h>
62 #include <sys/sunndi.h>
63 #include <sys/strsubr.h>
64 #include <sys/strsun.h>
65 #include <sys/ddi.h>
66 #include <sys/sunddi.h>
67 #include <sys/sunldi.h>
68 
69 #include <sys/audio/audio_driver.h>
70 
71 #include <sys/usb/clients/audio/usb_audio.h>
72 #include <sys/usb/clients/audio/usb_mixer.h>
73 #include <sys/usb/clients/audio/usb_ac/usb_ac.h>
74 
75 /* for getting the minor node info from hid */
76 #include <sys/usb/clients/hid/hidminor.h>
77 #include <sys/usb/clients/audio/usb_as/usb_as.h>
78 
79 
80 /* debug support */
81 uint_t	usb_ac_errlevel 	= USB_LOG_L4;
82 uint_t	usb_ac_errmask		= (uint_t)-1;
83 uint_t	usb_ac_instance_debug	= (uint_t)-1;
84 
85 /*
86  * wait period in seconds for the HID message processing thread
87  * used primarily to check when the stream has closed
88  */
89 uint_t usb_ac_wait_hid = 1;
90 
91 /*
92  * table for converting term types of input and output terminals
93  * to OSS port types (pretty rough mapping)
94  */
95 static const char *usb_audio_dtypes[] = {
96 	AUDIO_PORT_LINEIN,
97 	AUDIO_PORT_LINEOUT,
98 	AUDIO_PORT_SPEAKER,
99 	AUDIO_PORT_HEADPHONES,
100 	AUDIO_PORT_HANDSET,
101 	AUDIO_PORT_CD,
102 	AUDIO_PORT_MIC,
103 	AUDIO_PORT_PHONE,
104 	AUDIO_PORT_SPDIFIN,
105 	AUDIO_PORT_OTHER,
106 	NULL,
107 };
108 enum {
109 	USB_PORT_LINEIN = 0,
110 	USB_PORT_LINEOUT,
111 	USB_PORT_SPEAKER,
112 	USB_PORT_HEADPHONES,
113 	USB_PORT_HANDSET,
114 	USB_PORT_CD,
115 	USB_PORT_MIC,
116 	USB_PORT_PHONE,
117 	USB_PORT_SPDIFIN,
118 	USB_PORT_UNKNOWN
119 };
120 
121 static struct {
122 	ushort_t	term_type;
123 	uint_t	port_type;
124 } usb_ac_term_type_map[] = {
125 
126 	/* Input Terminal Types */
127 { USB_AUDIO_TERM_TYPE_MICROPHONE,		USB_PORT_MIC },
128 { USB_AUDIO_TERM_TYPE_DT_MICROPHONE,		USB_PORT_MIC },
129 { USB_AUDIO_TERM_TYPE_PERS_MICROPHONE,		USB_PORT_MIC },
130 { USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE,	USB_PORT_MIC },
131 { USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY,		USB_PORT_MIC },
132 { USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY,	USB_PORT_MIC },
133 
134 	/* Output Terminal Types */
135 { USB_AUDIO_TERM_TYPE_SPEAKER,			USB_PORT_SPEAKER },
136 { USB_AUDIO_TERM_TYPE_HEADPHONES,		USB_PORT_HEADPHONES },
137 { USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO,		USB_PORT_LINEOUT },
138 { USB_AUDIO_TERM_TYPE_DT_SPEAKER,		USB_PORT_SPEAKER },
139 { USB_AUDIO_TERM_TYPE_ROOM_SPEAKER,		USB_PORT_SPEAKER },
140 { USB_AUDIO_TERM_TYPE_COMM_SPEAKER,		USB_PORT_SPEAKER },
141 { USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER,	USB_PORT_SPEAKER },
142 
143 	/* Bi-directional Terminal Types */
144 { USB_AUDIO_TERM_TYPE_HANDSET,		USB_PORT_HANDSET },
145 
146 	/* Telephony Terminal Types */
147 { USB_AUDIO_TERM_TYPE_PHONE_LINE,	USB_PORT_PHONE},
148 { USB_AUDIO_TERM_TYPE_TELEPHONE,	USB_PORT_PHONE},
149 { USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE,	USB_PORT_PHONE },
150 
151 	/* External Terminal Types */
152 { USB_AUDIO_TERM_TYPE_SPDIF_IF,		USB_PORT_SPDIFIN },
153 	/* Embedded Function Terminal Types */
154 { USB_AUDIO_TERM_TYPE_CD_PLAYER,	USB_PORT_CD },
155 { 0, 0 }
156 };
157 
158 
159 /*
160  * Module linkage routines for the kernel
161  */
162 static int	usb_ac_attach(dev_info_t *, ddi_attach_cmd_t);
163 static int	usb_ac_detach(dev_info_t *, ddi_detach_cmd_t);
164 static int	usb_ac_power(dev_info_t *, int, int);
165 
166 static uint_t	usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
167 				uint_t);
168 
169 /* module entry points */
170 int		usb_ac_open(dev_info_t *);
171 void		usb_ac_close(dev_info_t *);
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_volume(usb_ac_state_t *, uint_t, short, int dir,
245 				int);
246 static int	usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int,
247 				int, short *);
248 static int	usb_ac_send_as_cmd(usb_ac_state_t *, usb_audio_eng_t *,
249 				int, void *);
250 static int	usb_ac_set_format(usb_ac_state_t *, usb_audio_eng_t *);
251 static int	usb_ac_do_setup(usb_ac_state_t *, usb_audio_eng_t *);
252 
253 /*  usb audio basic function entries */
254 static int	usb_ac_setup(usb_ac_state_t *, usb_audio_eng_t *);
255 static void	usb_ac_teardown(usb_ac_state_t *, usb_audio_eng_t *);
256 static int	usb_ac_start_play(usb_ac_state_t *, usb_audio_eng_t *);
257 static int	usb_ac_start_record(usb_ac_state_t *, usb_audio_eng_t *);
258 static void	usb_ac_stop_record(usb_ac_state_t *, usb_audio_eng_t *);
259 static int	usb_ac_restore_audio_state(usb_ac_state_t *, int);
260 
261 static int	usb_ac_ctrl_restore(usb_ac_state_t *);
262 /*
263  * Mux
264  */
265 static int	usb_ac_mux_walk_siblings(usb_ac_state_t *);
266 static void	usb_ac_print_reg_data(usb_ac_state_t *,
267 				usb_as_registration_t *);
268 static int	usb_ac_get_reg_data(usb_ac_state_t *, ldi_handle_t, int);
269 static int	usb_ac_setup_plumbed(usb_ac_state_t *, int, int);
270 static int	usb_ac_mixer_registration(usb_ac_state_t *);
271 static void	usb_ac_hold_siblings(usb_ac_state_t *);
272 static int	usb_ac_online_siblings(usb_ac_state_t *);
273 static void	usb_ac_rele_siblings(usb_ac_state_t *);
274 static int	usb_ac_mux_plumbing(usb_ac_state_t *);
275 static void	usb_ac_mux_plumbing_tq(void *);
276 static int	usb_ac_mux_unplumbing(usb_ac_state_t *);
277 static void	usb_ac_mux_unplumbing_tq(void *);
278 static int	usb_ac_plumb(usb_ac_plumbed_t *);
279 static void	usb_ac_unplumb(usb_ac_plumbed_t *);
280 static void	usb_ac_reader(void *);
281 static int	usb_ac_read_msg(usb_ac_plumbed_t *, mblk_t *);
282 static int	usb_ac_do_plumbing(usb_ac_state_t *);
283 static int	usb_ac_do_unplumbing(usb_ac_state_t *);
284 
285 
286 static int usb_change_phy_vol(usb_ac_state_t *, int);
287 static void usb_restore_engine(usb_ac_state_t *);
288 
289 /* anchor for soft state structures */
290 void	*usb_ac_statep;
291 
292 /*
293  * DDI Structures
294  */
295 
296 /* Device operations structure */
297 static struct dev_ops usb_ac_dev_ops = {
298 	DEVO_REV,		/* devo_rev */
299 	0,			/* devo_refcnt */
300 	NULL,			/* devo_getinfo */
301 	nulldev,		/* devo_identify - obsolete */
302 	nulldev,		/* devo_probe - not needed */
303 	usb_ac_attach,		/* devo_attach */
304 	usb_ac_detach,		/* devo_detach */
305 	nodev,			/* devo_reset */
306 	NULL,			/* devi_cb_ops */
307 	NULL,			/* devo_busb_ac_ops */
308 	usb_ac_power,		/* devo_power */
309 	ddi_quiesce_not_needed,	/* devo_quiesce */
310 };
311 
312 /* Linkage structure for loadable drivers */
313 static struct modldrv usb_ac_modldrv = {
314 	&mod_driverops,				/* drv_modops */
315 	"USB Audio Control Driver",		/* drv_linkinfo */
316 	&usb_ac_dev_ops				/* drv_dev_ops */
317 };
318 
319 /* Module linkage structure */
320 static struct modlinkage usb_ac_modlinkage = {
321 	MODREV_1,			/* ml_rev */
322 	(void *)&usb_ac_modldrv,	/* ml_linkage */
323 	NULL				/* NULL terminates the list */
324 };
325 
326 static int usb_audio_register(usb_ac_state_t *);
327 static int usb_audio_unregister(usb_ac_state_t *);
328 
329 static int usb_engine_open(void *, int, unsigned *, caddr_t *);
330 static void usb_engine_close(void *);
331 static uint64_t usb_engine_count(void *);
332 static int usb_engine_start(void *);
333 static void usb_engine_stop(void *);
334 static int usb_engine_format(void *);
335 static int usb_engine_channels(void *);
336 static int usb_engine_rate(void *);
337 static void usb_engine_sync(void *, unsigned);
338 static unsigned usb_engine_qlen(void *);
339 
340 /* engine buffer size in terms of fragments */
341 
342 audio_engine_ops_t usb_engine_ops = {
343 	AUDIO_ENGINE_VERSION,
344 	usb_engine_open,
345 	usb_engine_close,
346 	usb_engine_start,
347 	usb_engine_stop,
348 	usb_engine_count,
349 	usb_engine_format,
350 	usb_engine_channels,
351 	usb_engine_rate,
352 	usb_engine_sync,
353 	usb_engine_qlen,
354 };
355 
356 
357 
358 _NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
359 
360 /* standard entry points */
361 int
362 _init(void)
363 {
364 	int rval;
365 
366 	/* initialize the soft state */
367 	if ((rval = ddi_soft_state_init(&usb_ac_statep,
368 	    sizeof (usb_ac_state_t), 1)) != DDI_SUCCESS) {
369 		return (rval);
370 	}
371 
372 	audio_init_ops(&usb_ac_dev_ops, "usb_ac");
373 
374 	if ((rval = mod_install(&usb_ac_modlinkage)) != 0) {
375 		ddi_soft_state_fini(&usb_ac_statep);
376 		audio_fini_ops(&usb_ac_dev_ops);
377 	}
378 
379 	return (rval);
380 }
381 
382 int
383 _fini(void)
384 {
385 	int rval;
386 
387 	if ((rval = mod_remove(&usb_ac_modlinkage)) == 0) {
388 		/* Free the soft state internal structures */
389 		ddi_soft_state_fini(&usb_ac_statep);
390 		audio_fini_ops(&usb_ac_dev_ops);
391 	}
392 
393 	return (rval);
394 }
395 
396 int
397 _info(struct modinfo *modinfop)
398 {
399 	return (mod_info(&usb_ac_modlinkage, modinfop));
400 }
401 
402 extern	uint_t		nproc;
403 #define	INIT_PROCESS_CNT 3
404 
405 static int
406 usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
407 {
408 	usb_ac_state_t		*uacp = NULL;
409 	int			instance = ddi_get_instance(dip);
410 
411 	switch (cmd) {
412 		case DDI_ATTACH:
413 			break;
414 		case DDI_RESUME:
415 			usb_ac_cpr_resume(dip);
416 
417 			return (DDI_SUCCESS);
418 		default:
419 			return (DDI_FAILURE);
420 	}
421 
422 	/*
423 	 * wait  until all processes are started from main.
424 	 * USB enumerates early in boot (ie. consconfig time).
425 	 * If the plumbing takes place early, the file descriptors
426 	 * are owned by the init process and can never be closed anymore
427 	 * Consequently, hot removal is not possible and the dips
428 	 * never go away. By waiting some time, e.g. INIT_PROCESS_CNT,
429 	 * the problem is avoided.
430 	 */
431 	if (nproc < INIT_PROCESS_CNT) {
432 		USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL,
433 		    "usb_ac%d attach too early", instance);
434 
435 		return (DDI_FAILURE);
436 	}
437 
438 	/*
439 	 * Allocate soft state information.
440 	 */
441 	if (ddi_soft_state_zalloc(usb_ac_statep, instance) != DDI_SUCCESS) {
442 
443 		goto fail;
444 	}
445 
446 	/*
447 	 * get soft state space and initialize
448 	 */
449 	uacp = (usb_ac_state_t *)ddi_get_soft_state(usb_ac_statep, instance);
450 	if (uacp == NULL) {
451 
452 		goto fail;
453 	}
454 
455 	/* get log handle */
456 	uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac",
457 	    &usb_ac_errlevel,
458 	    &usb_ac_errmask, &usb_ac_instance_debug,
459 	    0);
460 
461 	uacp->usb_ac_instance = instance;
462 	uacp->usb_ac_dip = dip;
463 
464 	(void) snprintf(uacp->dstr, sizeof (uacp->dstr), "%s#%d",
465 	    ddi_driver_name(dip), instance);
466 
467 	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
468 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
469 		    "usb_client_attach failed");
470 
471 		usb_free_log_hdl(uacp->usb_ac_log_handle);
472 		ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
473 
474 		return (DDI_FAILURE);
475 	}
476 
477 	if (usb_get_dev_data(dip, &uacp->usb_ac_dev_data,
478 	    USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
479 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
480 		    "usb_get_dev_data failed");
481 
482 		usb_client_detach(dip, NULL);
483 		usb_free_log_hdl(uacp->usb_ac_log_handle);
484 		ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
485 
486 		return (DDI_FAILURE);
487 	}
488 
489 	/* initialize mutex & cv */
490 	mutex_init(&uacp->usb_ac_mutex, NULL, MUTEX_DRIVER,
491 	    uacp->usb_ac_dev_data->dev_iblock_cookie);
492 
493 	uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph;
494 
495 	/* parse all class specific descriptors */
496 	if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) {
497 
498 		goto fail;
499 	}
500 
501 	/* we no longer need the descr tree */
502 	usb_free_descr_tree(dip, uacp->usb_ac_dev_data);
503 
504 	uacp->usb_ac_ser_acc = usb_init_serialization(dip,
505 	    USB_INIT_SER_CHECK_SAME_THREAD);
506 
507 	mutex_enter(&uacp->usb_ac_mutex);
508 
509 	/* we are online */
510 	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
511 
512 	/*
513 	 * safe guard the postattach to be executed
514 	 * only two states arepossible: plumbed / unplumbed
515 	 */
516 	uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
517 	uacp->usb_ac_current_plumbed_index = -1;
518 
519 	mutex_exit(&uacp->usb_ac_mutex);
520 
521 	/* create components to power manage this device */
522 	usb_ac_create_pm_components(dip, uacp);
523 
524 	/* Register for events */
525 	if (usb_register_event_cbs(dip, &usb_ac_events, 0) != USB_SUCCESS) {
526 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
527 		    "usb_ac_attach: couldn't register for events");
528 
529 		goto fail;
530 	}
531 
532 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
533 	    "usb_ac_attach: End");
534 
535 	/* report device */
536 	ddi_report_dev(dip);
537 
538 	if (usb_ac_do_plumbing(uacp) != USB_SUCCESS)
539 		goto fail;
540 
541 	return (DDI_SUCCESS);
542 
543 fail:
544 	if (uacp) {
545 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
546 		    "attach failed");
547 
548 		/* wait for plumbing thread to finish */
549 		if (uacp->tqp != NULL) {
550 			ddi_taskq_wait(uacp->tqp);
551 			ddi_taskq_destroy(uacp->tqp);
552 			uacp->tqp = NULL;
553 		}
554 		(void) usb_ac_cleanup(dip, uacp);
555 	}
556 
557 	return (DDI_FAILURE);
558 }
559 
560 
561 static int
562 usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
563 {
564 	int instance = ddi_get_instance(dip);
565 	usb_ac_state_t	*uacp;
566 	int rval = USB_FAILURE;
567 
568 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
569 
570 	switch (cmd) {
571 	case DDI_DETACH:
572 		USB_DPRINTF_L4(PRINT_MASK_ATTA,
573 		    uacp->usb_ac_log_handle, "usb_ac_detach: detach");
574 
575 		/* wait for plumbing thread to finish */
576 		if (uacp->tqp != NULL)
577 			ddi_taskq_wait(uacp->tqp);
578 
579 		mutex_enter(&uacp->usb_ac_mutex);
580 
581 		/* do not allow detach if still busy */
582 		if (uacp->usb_ac_busy_count) {
583 			USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
584 			    "usb_ac_detach:still busy, usb_ac_busy_count = %d",
585 			    uacp->usb_ac_busy_count);
586 
587 			mutex_exit(&uacp->usb_ac_mutex);
588 			return (USB_FAILURE);
589 		}
590 		mutex_exit(&uacp->usb_ac_mutex);
591 
592 		(void) usb_audio_unregister(uacp);
593 
594 
595 
596 		/*
597 		 * unplumb to stop activity from other modules, then
598 		 * cleanup, which will also teardown audio framework state
599 		 */
600 		if (usb_ac_do_unplumbing(uacp) == USB_SUCCESS)
601 			rval = usb_ac_cleanup(dip, uacp);
602 
603 		if (rval != USB_SUCCESS) {
604 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
605 			    uacp->usb_ac_log_handle, "detach failed: %s%d",
606 			    ddi_driver_name(dip), instance);
607 		}
608 
609 		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
610 	case DDI_SUSPEND:
611 		USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
612 		    "usb_ac_detach: suspending");
613 
614 		rval = usb_ac_cpr_suspend(dip);
615 
616 		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
617 	default:
618 
619 		return (DDI_FAILURE);
620 	}
621 }
622 
623 
624 /*
625  * usb_ac_cleanup:
626  *	cleanup on attach failure and detach
627  */
628 static int
629 usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
630 {
631 	usb_ac_power_t	*uacpm;
632 	int	rval = USB_FAILURE;
633 
634 
635 	mutex_enter(&uacp->usb_ac_mutex);
636 	uacpm = uacp->usb_ac_pm;
637 
638 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
639 	    "usb_ac_cleanup:begain");
640 
641 	ASSERT(uacp->usb_ac_busy_count == 0);
642 
643 	ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED);
644 
645 	mutex_exit(&uacp->usb_ac_mutex);
646 
647 	/*
648 	 * Disable the event callbacks, after this point, event
649 	 * callbacks will never get called. Note we shouldn't hold
650 	 * the mutex while unregistering events because there may be a
651 	 * competing event callback thread. Event callbacks are done
652 	 * with ndi mutex held and this can cause a potential deadlock.
653 	 */
654 	usb_unregister_event_cbs(dip, &usb_ac_events);
655 
656 	mutex_enter(&uacp->usb_ac_mutex);
657 
658 	if (uacpm && (uacp->usb_ac_dev_state != USB_DEV_DISCONNECTED)) {
659 		if (uacpm->acpm_wakeup_enabled) {
660 			mutex_exit(&uacp->usb_ac_mutex);
661 			usb_ac_pm_busy_component(uacp);
662 			(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
663 
664 			rval = usb_handle_remote_wakeup(dip,
665 			    USB_REMOTE_WAKEUP_DISABLE);
666 			if (rval != USB_SUCCESS) {
667 				USB_DPRINTF_L2(PRINT_MASK_PM,
668 				    uacp->usb_ac_log_handle,
669 				    "usb_ac_cleanup: disable remote "
670 				    "wakeup failed, rval=%d", rval);
671 			}
672 			usb_ac_pm_idle_component(uacp);
673 		} else {
674 			mutex_exit(&uacp->usb_ac_mutex);
675 		}
676 
677 		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
678 
679 		mutex_enter(&uacp->usb_ac_mutex);
680 	}
681 
682 	if (uacpm) {
683 		kmem_free(uacpm,  sizeof (usb_ac_power_t));
684 		uacp->usb_ac_pm = NULL;
685 	}
686 
687 	usb_client_detach(dip, uacp->usb_ac_dev_data);
688 
689 	/* free descriptors */
690 	usb_ac_free_all_units(uacp);
691 
692 	mutex_exit(&uacp->usb_ac_mutex);
693 
694 	mutex_destroy(&uacp->usb_ac_mutex);
695 
696 	usb_fini_serialization(uacp->usb_ac_ser_acc);
697 
698 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
699 	    "usb_ac_cleanup: Ending");
700 
701 	usb_free_log_hdl(uacp->usb_ac_log_handle);
702 	kmem_free(uacp->usb_ac_connections, uacp->usb_ac_connections_len);
703 	kmem_free(uacp->usb_ac_connections_a, uacp->usb_ac_connections_a_len);
704 	kmem_free(uacp->usb_ac_unit_type, uacp->usb_ac_max_unit);
705 	kmem_free(uacp->usb_ac_traverse_path, uacp->usb_ac_max_unit);
706 
707 	ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
708 
709 	ddi_prop_remove_all(dip);
710 
711 	return (USB_SUCCESS);
712 }
713 
714 
715 int
716 usb_ac_open(dev_info_t *dip)
717 {
718 	int inst = ddi_get_instance(dip);
719 	usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
720 
721 	mutex_enter(&uacp->usb_ac_mutex);
722 
723 	uacp->usb_ac_busy_count++;
724 
725 	mutex_exit(&uacp->usb_ac_mutex);
726 
727 	usb_ac_pm_busy_component(uacp);
728 	(void) pm_raise_power(uacp->usb_ac_dip, 0, USB_DEV_OS_FULL_PWR);
729 
730 	return (0);
731 }
732 
733 
734 void
735 usb_ac_close(dev_info_t *dip)
736 {
737 	int inst = ddi_get_instance(dip);
738 	usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
739 
740 	mutex_enter(&uacp->usb_ac_mutex);
741 
742 	if (uacp->usb_ac_busy_count > 0)
743 		uacp->usb_ac_busy_count--;
744 
745 	mutex_exit(&uacp->usb_ac_mutex);
746 
747 	usb_ac_pm_idle_component(uacp);
748 }
749 
750 
751 /*
752  * usb_ac_read_msg:
753  *	Handle asynchronous response from opened streams
754  */
755 static int
756 usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
757 {
758 	usb_ac_state_t	*uacp = plumb_infop->acp_uacp;
759 	int error = DDI_SUCCESS;
760 	int	val;
761 	char	val1;
762 	struct iocblk *iocp;
763 
764 
765 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
766 
767 	/*
768 	 * typically an M_CTL is used between modules but in order to pass
769 	 * through the streamhead, an M_PROTO type must be used instead
770 	 */
771 	switch (mp->b_datap->db_type) {
772 	case M_PROTO:
773 	case M_ERROR:
774 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
775 		    "M_CTL/M_ERROR");
776 
777 		switch (plumb_infop->acp_driver) {
778 		case USB_AH_PLUMBED:
779 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
780 			    "message from hid, instance=%d",
781 			    ddi_get_instance(plumb_infop->acp_dip));
782 
783 			iocp = (struct iocblk *)(void *)mp->b_rptr;
784 			ASSERT(mp->b_cont != NULL);
785 
786 			if (uacp->usb_ac_registered_with_mixer) {
787 
788 				val1 = *((char *)mp->b_cont->b_rptr);
789 				val = (int)val1;
790 
791 				USB_DPRINTF_L4(PRINT_MASK_ALL,
792 				    uacp->usb_ac_log_handle, "val1=0x%x(%d),"
793 				    "val=0x%x(%d)", val1, val1, val, val);
794 
795 				switch (iocp->ioc_cmd) {
796 				/* Handle relative volume change */
797 				case USB_AUDIO_VOL_CHANGE:
798 					/* prevent unplumbing */
799 					uacp->usb_ac_busy_count++;
800 					if (uacp->usb_ac_plumbing_state ==
801 					    USB_AC_STATE_PLUMBED) {
802 						mutex_exit(&uacp->usb_ac_mutex);
803 						(void) usb_change_phy_vol(
804 						    uacp, val);
805 						mutex_enter(&uacp->
806 						    usb_ac_mutex);
807 					}
808 					uacp->usb_ac_busy_count--;
809 					/* FALLTHRU */
810 				case USB_AUDIO_MUTE:
811 				default:
812 					freemsg(mp);
813 					break;
814 				}
815 			} else {
816 				freemsg(mp);
817 			}
818 
819 			break;
820 		default:
821 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
822 			    "message from unknown module(%s)",
823 			    ddi_driver_name(plumb_infop->acp_dip));
824 			freemsg(mp);
825 		}
826 
827 		break;
828 	default:
829 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
830 		    "Unknown type=%d", mp->b_datap->db_type);
831 		freemsg(mp);
832 	}
833 
834 
835 	return (error);
836 }
837 
838 
839 /*
840  * Power Management
841  * usb_ac_power:
842  *	power entry point
843  */
844 static int
845 usb_ac_power(dev_info_t *dip, int comp, int level)
846 {
847 	_NOTE(ARGUNUSED(comp));
848 	int		instance = ddi_get_instance(dip);
849 	usb_ac_state_t	*uacp;
850 	usb_ac_power_t	*uacpm;
851 	int		rval = DDI_FAILURE;
852 
853 	uacp = ddi_get_soft_state(usb_ac_statep, instance);
854 
855 	mutex_enter(&uacp->usb_ac_mutex);
856 	uacpm = uacp->usb_ac_pm;
857 
858 	if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) {
859 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
860 		    "usb_ac_power: illegal level=%d pwr_states=%d",
861 		    level, uacpm->acpm_pwr_states);
862 
863 		goto done;
864 	}
865 
866 	switch (level) {
867 	case USB_DEV_OS_PWR_OFF:
868 		rval = usb_ac_pwrlvl0(uacp);
869 		break;
870 	case USB_DEV_OS_PWR_1:
871 		rval = usb_ac_pwrlvl1(uacp);
872 		break;
873 	case USB_DEV_OS_PWR_2:
874 		rval = usb_ac_pwrlvl2(uacp);
875 		break;
876 	case USB_DEV_OS_FULL_PWR:
877 		rval = usb_ac_pwrlvl3(uacp);
878 		break;
879 	}
880 
881 done:
882 	mutex_exit(&uacp->usb_ac_mutex);
883 
884 	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
885 }
886 
887 
888 /*
889  * functions to handle power transition for various levels
890  * These functions act as place holders to issue USB commands
891  * to the devices to change their power levels
892  * Level 0 = Device is powered off
893  * Level 3 = Device if full powered
894  * Level 1,2 = Intermediate power level of the device as implemented
895  *	by the hardware.
896  * Note that Level 0 is OS power-off and Level 3 is OS full-power.
897  */
898 static int
899 usb_ac_pwrlvl0(usb_ac_state_t *uacp)
900 {
901 	usb_ac_power_t	*uacpm;
902 	int		rval;
903 
904 	uacpm = uacp->usb_ac_pm;
905 
906 	switch (uacp->usb_ac_dev_state) {
907 	case USB_DEV_ONLINE:
908 		/* Deny the powerdown request if the device is busy */
909 		if (uacpm->acpm_pm_busy != 0) {
910 
911 			return (USB_FAILURE);
912 		}
913 
914 		/* Issue USB D3 command to the device here */
915 		rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip);
916 		ASSERT(rval == USB_SUCCESS);
917 
918 		uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN;
919 		uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF;
920 
921 		/* FALLTHRU */
922 	case USB_DEV_DISCONNECTED:
923 	case USB_DEV_SUSPENDED:
924 	case USB_DEV_PWRED_DOWN:
925 	default:
926 		return (USB_SUCCESS);
927 	}
928 }
929 
930 
931 /* ARGSUSED */
932 static int
933 usb_ac_pwrlvl1(usb_ac_state_t *uacp)
934 {
935 	int		rval;
936 
937 	/* Issue USB D2 command to the device here */
938 	rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip);
939 	ASSERT(rval == USB_SUCCESS);
940 
941 	return (USB_FAILURE);
942 }
943 
944 
945 /* ARGSUSED */
946 static int
947 usb_ac_pwrlvl2(usb_ac_state_t *uacp)
948 {
949 	int		rval;
950 
951 	rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip);
952 	ASSERT(rval == USB_SUCCESS);
953 
954 	return (USB_FAILURE);
955 }
956 
957 
958 static int
959 usb_ac_pwrlvl3(usb_ac_state_t *uacp)
960 {
961 	usb_ac_power_t	*uacpm;
962 	int		rval;
963 
964 	uacpm = uacp->usb_ac_pm;
965 
966 	switch (uacp->usb_ac_dev_state) {
967 	case USB_DEV_PWRED_DOWN:
968 		/* Issue USB D0 command to the device here */
969 		rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip);
970 		ASSERT(rval == USB_SUCCESS);
971 
972 		uacp->usb_ac_dev_state = USB_DEV_ONLINE;
973 		uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
974 		/* FALLTHRU */
975 	case USB_DEV_ONLINE:
976 		/* we are already in full power */
977 
978 		/* FALLTHRU */
979 	case USB_DEV_DISCONNECTED:
980 	case USB_DEV_SUSPENDED:
981 
982 		return (USB_SUCCESS);
983 	default:
984 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
985 		    "usb_ac_pwerlvl3: Illegal dev_state");
986 
987 		return (USB_FAILURE);
988 	}
989 }
990 
991 
992 static void
993 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
994 {
995 	usb_ac_power_t	*uacpm;
996 	uint_t		pwr_states;
997 
998 	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
999 	    "usb_ac_create_pm_components: begin");
1000 
1001 	/* Allocate the state structure */
1002 	uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP);
1003 	uacp->usb_ac_pm = uacpm;
1004 	uacpm->acpm_state = uacp;
1005 	uacpm->acpm_capabilities = 0;
1006 	uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1007 
1008 	if (usb_create_pm_components(dip, &pwr_states) ==
1009 	    USB_SUCCESS) {
1010 		if (usb_handle_remote_wakeup(dip,
1011 		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1012 			uacpm->acpm_wakeup_enabled = 1;
1013 
1014 			USB_DPRINTF_L4(PRINT_MASK_PM,
1015 			    uacp->usb_ac_log_handle,
1016 			    "remote Wakeup enabled");
1017 		}
1018 		uacpm->acpm_pwr_states = (uint8_t)pwr_states;
1019 		(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1020 	} else {
1021 		if (uacpm) {
1022 			kmem_free(uacpm,  sizeof (usb_ac_power_t));
1023 			uacp->usb_ac_pm = NULL;
1024 		}
1025 		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1026 		    "pm not enabled");
1027 	}
1028 
1029 }
1030 
1031 /*
1032  * usb_ac_get_featureID:
1033  *	find out if there is at least one feature unit that supports
1034  *	the request controls.
1035  *	Return featureID or USB_AC_ID_NONE.
1036  */
1037 static uint_t
1038 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir,
1039     uint_t channel, uint_t control)
1040 {
1041 	uint_t count = 0;
1042 
1043 	return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT,
1044 	    channel, control, USB_AC_FIND_ONE, &count, 0,
1045 	    usb_ac_feature_unit_check));
1046 }
1047 
1048 
1049 /*
1050  * usb_ac_feature_unit_check:
1051  *	check if a feature unit can support the required channel
1052  *	and control combination. Return USB_SUCCESS or USB_FAILURE.
1053  *	Called for each matching unit from usb_ac_traverse_connections.
1054  */
1055 /*ARGSUSED*/
1056 static int
1057 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
1058     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1059 {
1060 	usb_audio_feature_unit_descr1_t *feature_descrp;
1061 	int				n_channel_controls;
1062 
1063 
1064 	ASSERT(featureID < uacp->usb_ac_max_unit);
1065 
1066 	/*
1067 	 * check if this control is supported on this channel
1068 	 */
1069 	feature_descrp = (usb_audio_feature_unit_descr1_t *)
1070 	    uacp->usb_ac_units[featureID].acu_descriptor;
1071 	ASSERT(feature_descrp->bUnitID == featureID);
1072 
1073 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1074 	    "bControlSize=%d", feature_descrp->bControlSize);
1075 
1076 	if (feature_descrp->bControlSize == 0) {
1077 		featureID = USB_AC_ID_NONE;
1078 	} else {
1079 		uint_t index;
1080 
1081 		n_channel_controls = (feature_descrp->bLength -
1082 		    offsetof(usb_audio_feature_unit_descr1_t,
1083 		    bmaControls))/feature_descrp->bControlSize;
1084 
1085 		USB_DPRINTF_L3(PRINT_MASK_ALL,
1086 		    uacp->usb_ac_log_handle,
1087 		    "#controls: %d index=%d", n_channel_controls,
1088 		    feature_descrp->bControlSize * channel);
1089 
1090 		if (channel > n_channel_controls) {
1091 			featureID = USB_AC_ID_NONE;
1092 		} else {
1093 			/*
1094 			 * we only support MUTE and VOLUME
1095 			 * which are in the first byte
1096 			 */
1097 			index = feature_descrp->bControlSize *
1098 			    channel;
1099 
1100 			USB_DPRINTF_L3(PRINT_MASK_ALL,
1101 			    uacp->usb_ac_log_handle,
1102 			    "control: 0x%x",
1103 			    feature_descrp->bmaControls[index]);
1104 
1105 			if ((feature_descrp->bmaControls[index] &
1106 			    control) == 0) {
1107 				featureID = USB_AC_ID_NONE;
1108 			}
1109 		}
1110 	}
1111 
1112 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1113 	    "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
1114 	    dir, featureID);
1115 
1116 	return ((featureID != USB_AC_ID_NONE) ?
1117 	    USB_SUCCESS : USB_FAILURE);
1118 }
1119 
1120 
1121 /*
1122  * Descriptor Management
1123  *
1124  * usb_ac_handle_descriptors:
1125  *	extract interesting descriptors from the config cloud
1126  */
1127 static int
1128 usb_ac_handle_descriptors(usb_ac_state_t *uacp)
1129 {
1130 	int			len, index;
1131 	int			rval = USB_FAILURE;
1132 	usb_audio_cs_if_descr_t descr;
1133 	usb_client_dev_data_t	*dev_data = uacp->usb_ac_dev_data;
1134 	usb_alt_if_data_t	*altif_data;
1135 	usb_cvs_data_t		*cvs;
1136 
1137 
1138 	altif_data = &dev_data->dev_curr_cfg->
1139 	    cfg_if[dev_data->dev_curr_if].if_alt[0];
1140 
1141 	uacp->usb_ac_ifno	= dev_data->dev_curr_if;
1142 	uacp->usb_ac_if_descr	= altif_data->altif_descr;
1143 
1144 	/* find USB_AUDIO_CS_INTERFACE type descriptor */
1145 	for (index = 0; index < altif_data->altif_n_cvs; index++) {
1146 		cvs = &altif_data->altif_cvs[index];
1147 		if (cvs->cvs_buf == NULL) {
1148 			continue;
1149 		}
1150 		if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) {
1151 			break;
1152 		}
1153 	}
1154 
1155 	if (index == altif_data->altif_n_cvs) {
1156 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1157 		    "usb_ac_handle_descriptors:cannot find descriptor type %d",
1158 		    USB_AUDIO_CS_INTERFACE);
1159 
1160 		return (rval);
1161 	}
1162 
1163 	len = usb_parse_data(
1164 	    CS_AC_IF_HEADER_FORMAT,
1165 	    cvs->cvs_buf, cvs->cvs_buf_len,
1166 	    (void *)&descr, sizeof (usb_audio_cs_if_descr_t));
1167 
1168 	/* is this a sane header descriptor */
1169 	if (!((len >= CS_AC_IF_HEADER_SIZE) &&
1170 	    (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
1171 	    (descr.bDescriptorSubType == USB_AUDIO_HEADER))) {
1172 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1173 		    "invalid header");
1174 
1175 		return (rval);
1176 	}
1177 
1178 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1179 	    "index %d, header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
1180 	    "total=0x%x InCol=0x%x",
1181 	    index,
1182 	    descr.bDescriptorType,
1183 	    descr.bDescriptorSubType,
1184 	    descr.bcdADC,
1185 	    descr.wTotalLength,
1186 	    descr.blnCollection);
1187 
1188 	/*
1189 	 * we read descriptors by index and store them in ID array.
1190 	 * the actual parsing is done in usb_ac_add_unit_descriptor()
1191 	 */
1192 	for (index++; index < altif_data->altif_n_cvs; index++) {
1193 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1194 		    "index=%d", index);
1195 
1196 		cvs = &altif_data->altif_cvs[index];
1197 		if (cvs->cvs_buf == NULL) {
1198 			continue;
1199 		}
1200 
1201 		/* add to ID array */
1202 		usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf,
1203 		    cvs->cvs_buf_len);
1204 	}
1205 	rval = USB_SUCCESS;
1206 
1207 	usb_ac_setup_connections(uacp);
1208 
1209 	/* determine port types */
1210 	usb_ac_map_termtype_to_port(uacp, USB_AUDIO_PLAY);
1211 	usb_ac_map_termtype_to_port(uacp, USB_AUDIO_RECORD);
1212 
1213 
1214 	return (rval);
1215 }
1216 
1217 
1218 /*
1219  * usb_ac_setup_connections:
1220  *	build a matrix reflecting all connections
1221  */
1222 static void
1223 usb_ac_setup_connections(usb_ac_state_t *uacp)
1224 {
1225 	usb_ac_unit_list_t	*units = uacp->usb_ac_units;
1226 	uchar_t			*a, **p, i, unit;
1227 	size_t			a_len, p_len;
1228 
1229 	/* allocate array for unit types for quick reference */
1230 	uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit,
1231 	    KM_SLEEP);
1232 	/* allocate array for traversal path */
1233 	uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit,
1234 	    KM_SLEEP);
1235 
1236 
1237 	/* allocate the connection matrix and set it up */
1238 	a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit;
1239 	p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *);
1240 
1241 	/* trick to create a 2 dimensional array */
1242 	a = kmem_zalloc(a_len, KM_SLEEP);
1243 	p = kmem_zalloc(p_len, KM_SLEEP);
1244 	for (i = 0; i < uacp->usb_ac_max_unit; i++) {
1245 		p[i] = a + i * uacp->usb_ac_max_unit;
1246 	}
1247 	uacp->usb_ac_connections = p;
1248 	uacp->usb_ac_connections_len = p_len;
1249 	uacp->usb_ac_connections_a = a;
1250 	uacp->usb_ac_connections_a_len = a_len;
1251 
1252 	/* traverse all units and set connections */
1253 	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1254 
1255 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1256 		    "--------traversing unit=0x%x type=0x%x--------",
1257 		    unit, units[unit].acu_type);
1258 
1259 		/* store type in the first unused column */
1260 		uacp->usb_ac_unit_type[unit] = units[unit].acu_type;
1261 
1262 		/* save the Unit ID in the unit it points to */
1263 		switch (units[unit].acu_type) {
1264 		case USB_AUDIO_FEATURE_UNIT:
1265 		{
1266 			usb_audio_feature_unit_descr1_t *d =
1267 			    units[unit].acu_descriptor;
1268 
1269 			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1270 			    "USB_AUDIO_FEATURE_UNIT:sourceID=0x%x type=0x%x",
1271 			    d->bSourceID, units[d->bSourceID].acu_type);
1272 
1273 			if (d->bSourceID != 0) {
1274 				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1275 				p[unit][d->bSourceID] = B_TRUE;
1276 			}
1277 
1278 			break;
1279 		}
1280 		case USB_AUDIO_OUTPUT_TERMINAL:
1281 		{
1282 			usb_audio_output_term_descr_t *d =
1283 			    units[unit].acu_descriptor;
1284 
1285 			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1286 			    "USB_AUDIO_OUTPUT_TERMINAL:sourceID=0x%x type=0x%x",
1287 			    d->bSourceID, units[d->bSourceID].acu_type);
1288 
1289 			if (d->bSourceID != 0) {
1290 				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1291 				p[unit][d->bSourceID] = B_TRUE;
1292 			}
1293 
1294 			break;
1295 		}
1296 		case USB_AUDIO_MIXER_UNIT:
1297 		{
1298 			usb_audio_mixer_unit_descr1_t *d =
1299 			    units[unit].acu_descriptor;
1300 			int n_sourceID = d->bNrInPins;
1301 			int id;
1302 
1303 			for (id = 0; id < n_sourceID; id++) {
1304 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1305 				    uacp->usb_ac_log_handle,
1306 				    "USB_AUDIO_MIXER_UNIT:sourceID=0x%x"
1307 				    "type=0x%x c=%d",
1308 				    d->baSourceID[id],
1309 				    units[d->baSourceID[id]].acu_type,
1310 				    p[unit][d->baSourceID[id]]);
1311 
1312 				if (d->baSourceID[id] != 0) {
1313 					ASSERT(p[unit][d->baSourceID[id]] ==
1314 					    B_FALSE);
1315 					p[unit][d->baSourceID[id]] = B_TRUE;
1316 				}
1317 			}
1318 
1319 			break;
1320 		}
1321 		case USB_AUDIO_SELECTOR_UNIT:
1322 		{
1323 			usb_audio_selector_unit_descr1_t *d =
1324 			    units[unit].acu_descriptor;
1325 			int n_sourceID = d->bNrInPins;
1326 			int id;
1327 
1328 			for (id = 0; id < n_sourceID; id++) {
1329 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1330 				    uacp->usb_ac_log_handle,
1331 				    "USB_AUDIO_SELECTOR_UNIT:sourceID=0x%x"
1332 				    " type=0x%x", d->baSourceID[id],
1333 				    units[d->baSourceID[id]].acu_type);
1334 
1335 				if (d->baSourceID[id] != 0) {
1336 					ASSERT(p[unit][d->baSourceID[id]] ==
1337 					    B_FALSE);
1338 					p[unit][d->baSourceID[id]] = B_TRUE;
1339 				}
1340 			}
1341 
1342 			break;
1343 		}
1344 		case USB_AUDIO_PROCESSING_UNIT:
1345 		{
1346 			usb_audio_mixer_unit_descr1_t *d =
1347 			    units[unit].acu_descriptor;
1348 			int n_sourceID = d->bNrInPins;
1349 			int id;
1350 
1351 			for (id = 0; id < n_sourceID; id++) {
1352 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1353 				    uacp->usb_ac_log_handle,
1354 				    "USB_AUDIO_PROCESSING_UNIT:sourceID=0x%x"
1355 				    " type=0x%x", d->baSourceID[id],
1356 				    units[d->baSourceID[id]].acu_type);
1357 
1358 				if (d->baSourceID[id] != 0) {
1359 					ASSERT(p[unit][d->baSourceID[id]] ==
1360 					    B_FALSE);
1361 					p[unit][d->baSourceID[id]] = B_TRUE;
1362 				}
1363 			}
1364 
1365 			break;
1366 		}
1367 		case USB_AUDIO_EXTENSION_UNIT:
1368 		{
1369 			usb_audio_extension_unit_descr1_t *d =
1370 			    units[unit].acu_descriptor;
1371 			int n_sourceID = d->bNrInPins;
1372 			int id;
1373 
1374 			for (id = 0; id < n_sourceID; id++) {
1375 				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1376 				    uacp->usb_ac_log_handle,
1377 				    "USB_AUDIO_EXTENSION_UNIT:sourceID=0x%x"
1378 				    "type=0x%x", d->baSourceID[id],
1379 				    units[d->baSourceID[id]].acu_type);
1380 
1381 				if (d->baSourceID[id] != 0) {
1382 					ASSERT(p[unit][d->baSourceID[id]] ==
1383 					    B_TRUE);
1384 					p[unit][d->baSourceID[id]] = B_FALSE;
1385 				}
1386 			}
1387 
1388 			break;
1389 		}
1390 		case USB_AUDIO_INPUT_TERMINAL:
1391 
1392 			break;
1393 		default:
1394 			/*
1395 			 * Ignore the rest because they are not support yet
1396 			 */
1397 			break;
1398 		}
1399 	}
1400 
1401 #ifdef DEBUG
1402 	/* display topology in log buffer */
1403 {
1404 	uint_t i, j, l;
1405 	char *buf;
1406 
1407 	l = uacp->usb_ac_max_unit * 5;
1408 
1409 	buf = kmem_alloc(l, KM_SLEEP);
1410 
1411 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1412 	    "unit types:");
1413 
1414 	/* two	strings so they won't be replaced accidentily by tab */
1415 	(void) sprintf(&buf[0], "    ""    ");
1416 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1417 		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1418 	}
1419 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1420 
1421 	(void) sprintf(&buf[0], "  +-------");
1422 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1423 		(void) sprintf(&buf[5+((i-1)*3)], "---");
1424 	}
1425 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1426 
1427 	(void) sprintf(&buf[0], "    ""    ");
1428 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1429 		(void) sprintf(&buf[2 + (i*3)], "%02d ",
1430 		    uacp->usb_ac_unit_type[i]);
1431 	}
1432 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1433 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " ");
1434 
1435 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1436 	    "adjacency matrix:");
1437 	(void) sprintf(&buf[0], "    ""    ");
1438 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1439 		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1440 	}
1441 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1442 
1443 	(void) sprintf(&buf[0], "  +-------");
1444 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1445 		(void) sprintf(&buf[5+((i-1)*3)], "---");
1446 	}
1447 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1448 
1449 	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1450 		(void) sprintf(&buf[0], "%02d| "" ", i);
1451 		for (j = 1; j < uacp->usb_ac_max_unit; j++) {
1452 			(void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]);
1453 		}
1454 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1455 	}
1456 	kmem_free(buf, l);
1457 }
1458 #endif
1459 }
1460 
1461 
1462 /*
1463  * usb_ac_add_unit_descriptor:
1464  *	take the parsed descriptor in the buffer and store it in the ID unit
1465  *	array. we grow the unit array if the ID exceeds the current max
1466  */
1467 static void
1468 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
1469 	size_t buflen)
1470 {
1471 	void	*descr;
1472 	int	len;
1473 	char	*format;
1474 	size_t	size;
1475 
1476 
1477 	/* doubling the length should allow for padding */
1478 	len = 2 * buffer[0];
1479 	descr = kmem_zalloc(len, KM_SLEEP);
1480 
1481 	switch (buffer[2]) {
1482 	case USB_AUDIO_INPUT_TERMINAL:
1483 		format = CS_AC_INPUT_TERM_FORMAT;
1484 		size = CS_AC_INPUT_TERM_SIZE;
1485 
1486 		break;
1487 	case USB_AUDIO_OUTPUT_TERMINAL:
1488 		format = CS_AC_OUTPUT_TERM_FORMAT;
1489 		size = CS_AC_OUTPUT_TERM_SIZE;
1490 
1491 		break;
1492 	case USB_AUDIO_MIXER_UNIT:
1493 		format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c";
1494 		size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1;
1495 
1496 		break;
1497 	case USB_AUDIO_SELECTOR_UNIT:
1498 		format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c";
1499 		size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1;
1500 
1501 		break;
1502 	case USB_AUDIO_FEATURE_UNIT:
1503 		format = CS_AC_FEATURE_UNIT_FORMAT "255c";
1504 		size = CS_AC_FEATURE_UNIT_SIZE;
1505 
1506 		break;
1507 	case USB_AUDIO_PROCESSING_UNIT:
1508 		format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c";
1509 		size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1;
1510 
1511 		break;
1512 	case USB_AUDIO_EXTENSION_UNIT:
1513 		format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c";
1514 		size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1;
1515 
1516 		break;
1517 	default:
1518 		USB_DPRINTF_L2(PRINT_MASK_ATTA,
1519 		    uacp->usb_ac_log_handle,
1520 		    "unsupported descriptor %d", buffer[2]);
1521 
1522 		/* ignore this descriptor */
1523 		kmem_free(descr, len);
1524 
1525 		return;
1526 	}
1527 
1528 	if (usb_parse_data(format, buffer, buflen, descr, len) < size) {
1529 		/* ignore this descriptor */
1530 		kmem_free(descr, len);
1531 
1532 		return;
1533 	}
1534 
1535 	switch (buffer[2]) {
1536 	case USB_AUDIO_INPUT_TERMINAL:
1537 	{
1538 		usb_audio_input_term_descr_t *d =
1539 		    (usb_audio_input_term_descr_t *)descr;
1540 
1541 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1542 		    uacp->usb_ac_log_handle,
1543 		    "usb_ac_units[%d] ---input term: type=0x%x sub=0x%x"
1544 		    "termid=0x%x\n\t"
1545 		    "termtype=0x%x assoc=0x%x #ch=%d "
1546 		    "chconf=0x%x ich=0x%x iterm=0x%x",
1547 		    d->bTerminalID,
1548 		    d->bDescriptorType, d->bDescriptorSubType,
1549 		    d->bTerminalID, d->wTerminalType,
1550 		    d->bAssocTerminal, d->bNrChannels,
1551 		    d->wChannelConfig, d->iChannelNames,
1552 		    d->iTerminal);
1553 
1554 		usb_ac_alloc_unit(uacp, d->bTerminalID);
1555 		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1556 		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1557 		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1558 
1559 		break;
1560 	}
1561 	case USB_AUDIO_OUTPUT_TERMINAL:
1562 	{
1563 		usb_audio_output_term_descr_t *d =
1564 		    (usb_audio_output_term_descr_t *)descr;
1565 
1566 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1567 		    uacp->usb_ac_log_handle,
1568 		    "usb_ac_units[%d] ---output term: type=0x%x sub=0x%x"
1569 		    " termid=0x%x\n\t"
1570 		    "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
1571 		    d->bTerminalID,
1572 		    d->bDescriptorType, d->bDescriptorSubType,
1573 		    d->bTerminalID, d->wTerminalType,
1574 		    d->bAssocTerminal, d->bSourceID,
1575 		    d->iTerminal);
1576 
1577 		usb_ac_alloc_unit(uacp, d->bTerminalID);
1578 		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1579 		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1580 		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1581 
1582 		break;
1583 	}
1584 	case USB_AUDIO_MIXER_UNIT:
1585 	{
1586 		usb_audio_mixer_unit_descr1_t *d =
1587 		    (usb_audio_mixer_unit_descr1_t *)descr;
1588 
1589 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1590 		    uacp->usb_ac_log_handle,
1591 		    "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1592 		    " unitid=0x%x\n\t"
1593 		    "#pins=0x%x sourceid[0]=0x%x",
1594 		    d->bUnitID,
1595 		    d->bDescriptorType, d->bDescriptorSubType,
1596 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1597 		usb_ac_alloc_unit(uacp, d->bUnitID);
1598 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1599 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1600 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1601 
1602 		break;
1603 	}
1604 	case USB_AUDIO_SELECTOR_UNIT:
1605 	{
1606 		usb_audio_selector_unit_descr1_t *d =
1607 		    (usb_audio_selector_unit_descr1_t *)descr;
1608 
1609 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1610 		    uacp->usb_ac_log_handle,
1611 		    "usb_ac_units[%d] ---selector unit: type=0x%x sub=0x%x"
1612 		    " unitid=0x%x\n\t"
1613 		    "#pins=0x%x sourceid[0]=0x%x",
1614 		    d->bUnitID,
1615 		    d->bDescriptorType, d->bDescriptorSubType,
1616 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1617 		usb_ac_alloc_unit(uacp, d->bUnitID);
1618 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1619 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1620 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1621 
1622 		break;
1623 	}
1624 	case USB_AUDIO_FEATURE_UNIT:
1625 	{
1626 		usb_audio_feature_unit_descr1_t *d =
1627 		    (usb_audio_feature_unit_descr1_t *)descr;
1628 
1629 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1630 		    uacp->usb_ac_log_handle,
1631 		    "usb_ac_units[%d] ---feature unit: type=0x%x sub=0x%x"
1632 		    " unitid=0x%x\n\t"
1633 		    "sourceid=0x%x size=0x%x",
1634 		    d->bUnitID,
1635 		    d->bDescriptorType, d->bDescriptorSubType,
1636 		    d->bUnitID, d->bSourceID, d->bControlSize);
1637 
1638 		usb_ac_alloc_unit(uacp, d->bUnitID);
1639 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1640 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1641 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1642 
1643 		break;
1644 	}
1645 	case USB_AUDIO_PROCESSING_UNIT:
1646 	{
1647 		usb_audio_processing_unit_descr1_t *d =
1648 		    (usb_audio_processing_unit_descr1_t *)descr;
1649 
1650 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1651 		    uacp->usb_ac_log_handle,
1652 		    "usb_ac_units[%d] ---processing unit: type=0x%x sub=0x%x"
1653 		    " unitid=0x%x\n\t"
1654 		    "#pins=0x%x sourceid[0]=0x%x",
1655 		    d->bUnitID,
1656 		    d->bDescriptorType, d->bDescriptorSubType,
1657 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1658 		usb_ac_alloc_unit(uacp, d->bUnitID);
1659 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1660 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1661 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1662 
1663 		break;
1664 	}
1665 	case USB_AUDIO_EXTENSION_UNIT:
1666 	{
1667 		usb_audio_extension_unit_descr1_t *d =
1668 		    (usb_audio_extension_unit_descr1_t *)descr;
1669 
1670 		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1671 		    uacp->usb_ac_log_handle,
1672 		    "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1673 		    " unitid=0x%x\n\t"
1674 		    "#pins=0x%x sourceid[0]=0x%x",
1675 		    d->bUnitID,
1676 		    d->bDescriptorType, d->bDescriptorSubType,
1677 		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1678 		usb_ac_alloc_unit(uacp, d->bUnitID);
1679 		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1680 		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1681 		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1682 
1683 		break;
1684 	}
1685 	default:
1686 		break;
1687 	}
1688 }
1689 
1690 
1691 /*
1692  * usb_ac_alloc_unit:
1693  *	check if the unit ID is less than max_unit in which case no
1694  *	extra entries are needed. If more entries are needed, copy over
1695  *	the existing array into a new larger array
1696  */
1697 static void
1698 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
1699 {
1700 	usb_ac_unit_list_t *old = NULL;
1701 	uint_t	max_unit;
1702 
1703 
1704 	if (uacp->usb_ac_units) {
1705 		if (unit < uacp->usb_ac_max_unit) {
1706 			/* existing array is big enough */
1707 
1708 			return;
1709 		}
1710 		old = uacp->usb_ac_units;
1711 		max_unit = uacp->usb_ac_max_unit;
1712 	}
1713 
1714 	/* allocate two extra ones */
1715 	unit += 2;
1716 	uacp->usb_ac_max_unit = unit;
1717 	uacp->usb_ac_units = kmem_zalloc(unit *
1718 	    sizeof (usb_ac_unit_list_t), KM_SLEEP);
1719 
1720 	if (old) {
1721 		size_t len = max_unit * sizeof (usb_ac_unit_list_t);
1722 		bcopy(old, uacp->usb_ac_units, len);
1723 
1724 		kmem_free(old, len);
1725 	}
1726 }
1727 
1728 
1729 /*
1730  * usb_ac_free_all_units:
1731  *	free the entire unit list
1732  */
1733 static void
1734 usb_ac_free_all_units(usb_ac_state_t *uacp)
1735 {
1736 	uint_t	unit;
1737 	usb_ac_unit_list_t *unitp;
1738 
1739 	if (uacp->usb_ac_units == NULL) {
1740 
1741 		return;
1742 	}
1743 
1744 
1745 	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1746 		unitp = &uacp->usb_ac_units[unit];
1747 		if (unitp) {
1748 			if (unitp->acu_descriptor) {
1749 				kmem_free(unitp->acu_descriptor,
1750 				    unitp->acu_descr_length);
1751 			}
1752 		}
1753 	}
1754 
1755 	kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit *
1756 	    sizeof (usb_ac_unit_list_t));
1757 }
1758 
1759 
1760 /*
1761  * usb_ac_lookup_port_type:
1762  *	map term type to port type
1763  *	default just return LINE_IN + LINE_OUT
1764  */
1765 static int
1766 usb_ac_lookup_port_type(ushort_t termtype)
1767 {
1768 	uint_t i;
1769 
1770 	/*
1771 	 * Looking for a input/ouput terminal type to match the port
1772 	 * type, it should not be common streaming type
1773 	 */
1774 	ASSERT(termtype != USB_AUDIO_TERM_TYPE_STREAMING);
1775 
1776 	for (i = 0; ; i++) {
1777 		if (usb_ac_term_type_map[i].term_type == 0) {
1778 
1779 			break;
1780 		}
1781 
1782 		if (usb_ac_term_type_map[i].term_type == termtype) {
1783 
1784 			return (usb_ac_term_type_map[i].port_type);
1785 		}
1786 	}
1787 
1788 	return (USB_PORT_UNKNOWN);
1789 }
1790 
1791 
1792 /*
1793  * usb_ac_update_port:
1794  *	called for each terminal
1795  */
1796 /*ARGSUSED*/
1797 static int
1798 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
1799     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1800 {
1801 	if (dir & USB_AUDIO_PLAY) {
1802 		usb_audio_output_term_descr_t *d =
1803 		    (usb_audio_output_term_descr_t *)
1804 		    uacp->usb_ac_units[id].acu_descriptor;
1805 		uint_t port_type =
1806 		    usb_ac_lookup_port_type(d->wTerminalType);
1807 
1808 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1809 		    "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
1810 		    dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1811 
1812 		uacp->usb_ac_output_ports |= (1U << port_type);
1813 	} else {
1814 		usb_audio_input_term_descr_t *d =
1815 		    (usb_audio_input_term_descr_t *)
1816 		    uacp->usb_ac_units[id].acu_descriptor;
1817 		uint_t port_type =
1818 		    usb_ac_lookup_port_type(d->wTerminalType);
1819 
1820 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1821 		    "usb_ac_update_port: dir=%d wTerminalType=0x%x,  name=%s",
1822 		    dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1823 
1824 		uacp->usb_ac_input_ports |= (1U << port_type);
1825 
1826 	}
1827 
1828 	return (USB_SUCCESS);
1829 }
1830 
1831 
1832 /*
1833  * usb_ac_map_termtype_to_port:
1834  *	starting from a streaming termtype find all
1835  *	input or output terminals and OR into uacp->usb_ac_input_ports
1836  *	or uacp->usb_ac_output_ports;
1837  */
1838 static void
1839 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
1840 {
1841 	uint_t count = 0;
1842 	uint_t depth = 0;
1843 	uint_t search_type = (dir & USB_AUDIO_PLAY) ?
1844 	    USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
1845 
1846 
1847 	(void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
1848 	    0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
1849 
1850 	ASSERT(depth == 0);
1851 }
1852 
1853 
1854 /*
1855  * usb_ac_set_port:
1856  *	find a selector port (record side only) and set the
1857  *	input to the matching pin
1858  */
1859 static uint_t
1860 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
1861 {
1862 	uint_t count = 0;
1863 	uint_t id;
1864 	uint_t depth = 0;
1865 
1866 
1867 	/* we only support the selector for the record side */
1868 	if (dir & USB_AUDIO_RECORD) {
1869 		id = usb_ac_traverse_all_units(uacp, dir,
1870 		    USB_AUDIO_SELECTOR_UNIT, 0,
1871 		    0, USB_AC_FIND_ONE, &count, port, &depth,
1872 		    usb_ac_set_selector);
1873 
1874 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1875 		    "usb_ac_set_port: id=%d count=%d port=%d",
1876 		    id, count, port);
1877 
1878 		ASSERT(depth == 0);
1879 	}
1880 
1881 	return (USB_SUCCESS);
1882 }
1883 
1884 
1885 /*
1886  * usb_ac_match_port:
1887  *	given the requested port type, find a correspondig term type
1888  *	Called from usb_ac_traverse_all_units()
1889  */
1890 /*ARGSUSED*/
1891 static int
1892 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
1893     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1894 {
1895 	uint_t port_type;
1896 
1897 
1898 	if (dir & USB_AUDIO_PLAY) {
1899 		usb_audio_output_term_descr_t *d =
1900 		    (usb_audio_output_term_descr_t *)
1901 		    uacp->usb_ac_units[id].acu_descriptor;
1902 		port_type = usb_ac_lookup_port_type(d->wTerminalType);
1903 
1904 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1905 		    "usb_ac_match_port: "
1906 		    "dir=%d type=0x%x port_type=%d port=%d",
1907 		    dir, d->wTerminalType, port_type, arg1);
1908 	} else {
1909 		usb_audio_output_term_descr_t *d =
1910 		    (usb_audio_output_term_descr_t *)
1911 		    uacp->usb_ac_units[id].acu_descriptor;
1912 		port_type = usb_ac_lookup_port_type(d->wTerminalType);
1913 
1914 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1915 		    "usb_ac_match_port: "
1916 		    "dir=%d type=0x%x port_type=%d port=%d",
1917 		    dir, d->wTerminalType, port_type, arg1);
1918 	}
1919 
1920 	return (((1U << port_type) & arg1) ? USB_SUCCESS : USB_FAILURE);
1921 }
1922 
1923 
1924 /*
1925  * usb_ac_set_selector:
1926  *	Called from usb_ac_traverse_all_units()
1927  *	Find the correct pin and set selector to this pin
1928  */
1929 /*ARGSUSED*/
1930 static int
1931 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
1932     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1933 {
1934 	uint_t count = 0;
1935 	uint_t unit = USB_AC_ID_NONE;
1936 	uint_t pin;
1937 	uint_t search_target =
1938 	    (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
1939 	    USB_AUDIO_INPUT_TERMINAL;
1940 	usb_audio_selector_unit_descr1_t *d =
1941 	    (usb_audio_selector_unit_descr1_t *)
1942 	    uacp->usb_ac_units[id].acu_descriptor;
1943 	int n_sourceID = d->bNrInPins;
1944 	int rval = USB_FAILURE;
1945 
1946 
1947 	/*
1948 	 * for each pin, find a term type that matches the
1949 	 * requested port type
1950 	 */
1951 	for (pin = 0; pin < n_sourceID; pin++) {
1952 		if (d->baSourceID[pin] == 0) {
1953 
1954 			break;
1955 		}
1956 		unit = d->baSourceID[pin];
1957 
1958 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1959 		    "usb_ac_set_selector: pin=%d unit=%d", pin, unit);
1960 
1961 		if (uacp->usb_ac_unit_type[unit] == search_target) {
1962 			if (usb_ac_match_port(uacp, unit, dir, channel,
1963 			    control, arg1, depth) == USB_SUCCESS) {
1964 
1965 				break;
1966 			} else {
1967 				unit = USB_AC_ID_NONE;
1968 
1969 				continue;
1970 			}
1971 		}
1972 
1973 		/* find units connected to this unit */
1974 		unit = usb_ac_traverse_connections(uacp, unit,
1975 		    dir, search_target, channel, control,
1976 		    USB_AC_FIND_ONE, &count, arg1, depth,
1977 		    usb_ac_match_port);
1978 
1979 		if (unit != USB_AC_ID_NONE) {
1980 
1981 			break;
1982 		}
1983 	}
1984 
1985 
1986 	if (unit != USB_AC_ID_NONE) {
1987 		mblk_t		*data;
1988 		usb_cr_t	cr;
1989 		usb_cb_flags_t	cb_flags;
1990 
1991 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1992 		    "usb_ac_set_selector: found id=%d at pin %d", unit, pin);
1993 
1994 		mutex_exit(&uacp->usb_ac_mutex);
1995 
1996 		data = allocb(1, BPRI_HI);
1997 		if (!data) {
1998 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1999 			    "usb_ac_set_selector: allocate data failed");
2000 			mutex_enter(&uacp->usb_ac_mutex);
2001 
2002 			return (USB_FAILURE);
2003 		}
2004 
2005 		/* pins are 1-based */
2006 		*(data->b_rptr) = (char)++pin;
2007 
2008 		if (usb_pipe_sync_ctrl_xfer(
2009 		    uacp->usb_ac_dip,
2010 		    uacp->usb_ac_default_ph,
2011 		    USB_DEV_REQ_HOST_TO_DEV |
2012 		    USB_DEV_REQ_TYPE_CLASS |
2013 		    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
2014 		    USB_AUDIO_SET_CUR,		/* bRequest */
2015 		    0,				/* wValue */
2016 						/* feature unit and id */
2017 		    (id << 8)| uacp->usb_ac_ifno, /* wIndex */
2018 		    1,				/* wLength */
2019 		    &data,
2020 		    USB_ATTRS_NONE,
2021 		    &cr, &cb_flags,
2022 		    USB_FLAGS_SLEEP) == USB_SUCCESS) {
2023 			USB_DPRINTF_L3(PRINT_MASK_ALL,
2024 			    uacp->usb_ac_log_handle,
2025 			    "set current selection: %d", *data->b_rptr);
2026 
2027 			rval = USB_SUCCESS;
2028 		} else {
2029 			USB_DPRINTF_L2(PRINT_MASK_ALL,
2030 			    uacp->usb_ac_log_handle,
2031 			    "set current pin selection failed");
2032 		}
2033 		freemsg(data);
2034 
2035 		mutex_enter(&uacp->usb_ac_mutex);
2036 	} else {
2037 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2038 		    "usb_ac_set_selector: nothing found");
2039 	}
2040 
2041 	return (rval);
2042 }
2043 
2044 
2045 /*
2046  * usb_ac_set_control:
2047  *	apply func to all units of search_target type for both the
2048  *	requested channel and master channel
2049  */
2050 static uint_t
2051 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
2052 	uint_t channel, uint_t control, uint_t all_or_one,
2053 	uint_t *count, uint_t arg1,
2054 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2055 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2056 {
2057 	uint_t id;
2058 	uint_t depth = 0;
2059 
2060 	id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
2061 	    control, all_or_one, count, arg1, &depth, func);
2062 
2063 	if ((channel != 0) &&
2064 	    (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) ||
2065 	    (all_or_one == USB_AC_FIND_ALL)))  {
2066 		/* try master channel */
2067 		channel = 0;
2068 		id = usb_ac_traverse_all_units(uacp, dir, search_target,
2069 		    channel, control, all_or_one, count, arg1,
2070 		    &depth, func);
2071 	}
2072 
2073 	ASSERT(depth == 0);
2074 
2075 	return (id);
2076 }
2077 
2078 
2079 /*
2080  * usb_ac_traverse_all_units:
2081  *	traverse all units starting with all IT or OT depending on direction.
2082  *	If no unit is found for the particular channel, try master channel
2083  *	If a matching unit is found, apply the function passed by
2084  *	the caller
2085  */
2086 static uint_t
2087 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
2088 	uint_t search_target, uint_t channel, uint_t control,
2089 	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2090 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2091 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2092 {
2093 	uint_t unit, start_type, id;
2094 
2095 	start_type = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
2096 	    USB_AUDIO_OUTPUT_TERMINAL;
2097 
2098 	/* keep track of recursion */
2099 	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2100 		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2101 		    "Unit topology too complex, giving up");
2102 
2103 		return (USB_AC_ID_NONE);
2104 	}
2105 
2106 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2107 		/* is this an IT or OT? */
2108 		if (uacp->usb_ac_unit_type[unit] != start_type) {
2109 
2110 			continue;
2111 		}
2112 
2113 		/* start at streaming term types */
2114 		if (dir & USB_AUDIO_PLAY) {
2115 			usb_audio_input_term_descr_t *d =
2116 			    uacp->usb_ac_units[unit].acu_descriptor;
2117 			if (d->wTerminalType !=
2118 			    USB_AUDIO_TERM_TYPE_STREAMING) {
2119 
2120 				continue;
2121 			}
2122 		} else {
2123 			usb_audio_output_term_descr_t *d =
2124 			    uacp->usb_ac_units[unit].acu_descriptor;
2125 			if (d->wTerminalType !=
2126 			    USB_AUDIO_TERM_TYPE_STREAMING) {
2127 
2128 				continue;
2129 			}
2130 		}
2131 
2132 		/* find units connected to this unit */
2133 		id = usb_ac_traverse_connections(uacp, unit, dir,
2134 		    search_target, channel, control, all_or_one, count,
2135 		    arg1, depth, func);
2136 
2137 		if ((all_or_one == USB_AC_FIND_ONE) &&
2138 		    (id != USB_AC_ID_NONE)) {
2139 			unit = id;
2140 
2141 			break;
2142 		}
2143 	}
2144 
2145 	(*depth)--;
2146 
2147 	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2148 }
2149 
2150 
2151 /*
2152  * usb_ac_set_monitor_gain_control:
2153  *	search for a feature unit between output terminal (OT) and
2154  *	input terminal. We are looking for a path between
2155  *	for example a microphone and a speaker through a feature unit
2156  *	and mixer
2157  */
2158 static uint_t
2159 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
2160 	uint_t search_target, uint_t channel, uint_t control,
2161 	uint_t all_or_one, uint_t *count, uint_t arg1,
2162 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2163 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2164 {
2165 	uint_t unit, id;
2166 	uint_t depth = 0;
2167 
2168 
2169 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2170 		usb_audio_output_term_descr_t *d =
2171 		    uacp->usb_ac_units[unit].acu_descriptor;
2172 
2173 		/* is this an OT and not stream type? */
2174 		if ((uacp->usb_ac_unit_type[unit] ==
2175 		    USB_AUDIO_OUTPUT_TERMINAL) &&
2176 		    (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) {
2177 
2178 			/* find units connected to this unit */
2179 			id = usb_ac_traverse_connections(uacp, unit, dir,
2180 			    search_target, channel, control, all_or_one, count,
2181 			    arg1, &depth, func);
2182 
2183 			if ((all_or_one == USB_AC_FIND_ONE) &&
2184 			    (id != USB_AC_ID_NONE)) {
2185 
2186 				break;
2187 			}
2188 		}
2189 	}
2190 
2191 	ASSERT(depth == 0);
2192 
2193 	return (id);
2194 }
2195 
2196 
2197 /*
2198  * usb_ac_push/pop_unit
2199  *	add/remove unit ID to the traverse path
2200  */
2201 static void
2202 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
2203 {
2204 	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] =
2205 	    (uchar_t)unit;
2206 	ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
2207 }
2208 
2209 
2210 /* ARGSUSED */
2211 static void
2212 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
2213 {
2214 	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
2215 }
2216 
2217 
2218 /*
2219  * usb_ac_show_traverse_path:
2220  *	display entire path, just for debugging
2221  */
2222 static void
2223 usb_ac_show_traverse_path(usb_ac_state_t *uacp)
2224 {
2225 	int i;
2226 
2227 	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2228 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2229 		    "traverse path %d: unit=%d type=%d",
2230 		    i, uacp->usb_ac_traverse_path[i],
2231 		    uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]);
2232 	}
2233 }
2234 
2235 
2236 /*
2237  * usb_ac_check_path:
2238  *	check for a specified type in the traverse path
2239  */
2240 static int
2241 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type)
2242 {
2243 	int i;
2244 
2245 	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2246 		uint_t unit = uacp->usb_ac_traverse_path[i];
2247 
2248 		if (uacp->usb_ac_unit_type[unit] == type) {
2249 
2250 			return (USB_SUCCESS);
2251 		}
2252 	}
2253 
2254 	return (USB_FAILURE);
2255 }
2256 
2257 
2258 /*
2259  * usb_ac_traverse_connections:
2260  *	traverse all units and for each unit with the right type, call
2261  *	func. If the func returns a success and search == USB_AC_FIND_ONE,
2262  *	we are done. If all is set then we continue until we terminate
2263  *	and input or output terminal.
2264  *	For audio play, we traverse columns starting from an input terminal
2265  *	to an output terminal while for record we traverse rows from output
2266  *	terminal to input terminal.
2267  */
2268 static uint_t
2269 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
2270 	uint_t search_target, uint_t channel, uint_t control,
2271 	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2272 	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2273 		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2274 {
2275 	uint_t unit, id;
2276 	uint_t done = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2277 	    USB_AUDIO_INPUT_TERMINAL;
2278 
2279 
2280 	/* keep track of recursion depth */
2281 	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2282 		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2283 		    "Unit topology too complex, giving up");
2284 
2285 		return (USB_AC_ID_NONE);
2286 	}
2287 
2288 	usb_ac_push_unit_id(uacp, start_unit);
2289 
2290 	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2291 		uint_t entry = (dir & USB_AUDIO_PLAY) ?
2292 		    uacp->usb_ac_connections[unit][start_unit] :
2293 		    uacp->usb_ac_connections[start_unit][unit];
2294 
2295 		if (entry) {
2296 			USB_DPRINTF_L3(PRINT_MASK_ALL,
2297 			    uacp->usb_ac_log_handle,
2298 			    "start=%d unit=%d entry=%d type=%d "
2299 			    "done=%d found=%d",
2300 			    start_unit, unit, entry, search_target, done,
2301 			    uacp->usb_ac_unit_type[unit]);
2302 
2303 			/* did we find a matching type? */
2304 			if (uacp->usb_ac_unit_type[unit] == search_target) {
2305 				USB_DPRINTF_L3(PRINT_MASK_ALL,
2306 				    uacp->usb_ac_log_handle,
2307 				    "match: dir=%d unit=%d type=%d",
2308 				    dir, unit, search_target);
2309 
2310 				/* yes, no apply function to this unit */
2311 				if (func(uacp, unit, dir, channel,
2312 				    control, arg1, depth) == USB_SUCCESS) {
2313 					(*count)++;
2314 
2315 					USB_DPRINTF_L3(PRINT_MASK_ALL,
2316 					    uacp->usb_ac_log_handle,
2317 					    "func returned success, "
2318 					    "unit=%d all=%d", unit,
2319 					    all_or_one);
2320 
2321 					/* are we done? */
2322 					if (all_or_one == USB_AC_FIND_ONE) {
2323 
2324 						break;
2325 					}
2326 				}
2327 			}
2328 
2329 			/* did we find the terminating unit */
2330 			if (uacp->usb_ac_unit_type[unit] == done) {
2331 
2332 				continue;
2333 			}
2334 			id = usb_ac_traverse_connections(uacp, unit, dir,
2335 			    search_target, channel, control,
2336 			    all_or_one, count, arg1, depth, func);
2337 			if ((id != USB_AC_ID_NONE) &&
2338 			    (all_or_one == USB_AC_FIND_ONE)) {
2339 				unit = id;
2340 
2341 				break;
2342 			}
2343 		}
2344 	}
2345 
2346 	(*depth)--;
2347 	usb_ac_pop_unit_id(uacp, start_unit);
2348 
2349 	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2350 }
2351 
2352 
2353 /*
2354  * Event Management
2355  *
2356  * usb_ac_disconnect_event_cb:
2357  *	The device has been disconnected. we either wait for
2358  *	detach or a reconnect event.
2359  */
2360 static int
2361 usb_ac_disconnect_event_cb(dev_info_t *dip)
2362 {
2363 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2364 	    usb_ac_statep, ddi_get_instance(dip));
2365 
2366 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2367 	    "usb_ac_disconnect_event_cb:start");
2368 
2369 	usb_ac_serialize_access(uacp);
2370 	mutex_enter(&uacp->usb_ac_mutex);
2371 
2372 	/* setting to disconnect state will prevent replumbing */
2373 	uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2374 
2375 	if (uacp->usb_ac_busy_count) {
2376 		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2377 		    "device was disconnected while busy. "
2378 		    "Data may have been lost");
2379 	}
2380 	mutex_exit(&uacp->usb_ac_mutex);
2381 
2382 	usb_ac_release_access(uacp);
2383 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2384 	    "usb_ac_disconnect_event_cb:done");
2385 
2386 
2387 	return (USB_SUCCESS);
2388 }
2389 
2390 
2391 /*
2392  * usb_ac_cpr_suspend:
2393  */
2394 static int
2395 usb_ac_cpr_suspend(dev_info_t *dip)
2396 {
2397 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2398 	    usb_ac_statep, ddi_get_instance(dip));
2399 
2400 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2401 	    "usb_ac_cpr_suspend: Begin");
2402 
2403 	mutex_enter(&uacp->usb_ac_mutex);
2404 	uacp->usb_ac_dev_state = USB_DEV_SUSPENDED;
2405 	mutex_exit(&uacp->usb_ac_mutex);
2406 
2407 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2408 	    "usb_ac_cpr_suspend: End");
2409 
2410 	return (USB_SUCCESS);
2411 }
2412 
2413 
2414 
2415 /*
2416  * usb_ac_reconnect_event_cb:
2417  *	The device was disconnected but this instance not detached, probably
2418  *	because the device was busy.
2419  *	if the same device, continue with restoring state
2420  *	We should either be in the unplumbed state or the plumbed open
2421  *	state.
2422  */
2423 static int
2424 usb_ac_reconnect_event_cb(dev_info_t *dip)
2425 {
2426 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2427 	    usb_ac_statep, ddi_get_instance(dip));
2428 
2429 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2430 	    "usb_ac_reconnect_event_cb:begain");
2431 
2432 	mutex_enter(&uacp->usb_ac_mutex);
2433 	mutex_exit(&uacp->usb_ac_mutex);
2434 
2435 	usb_ac_serialize_access(uacp);
2436 
2437 	/* check the plumbing state */
2438 	mutex_enter(&uacp->usb_ac_mutex);
2439 	uacp->usb_ac_busy_count++;
2440 	if (uacp->usb_ac_plumbing_state ==
2441 	    USB_AC_STATE_PLUMBED) {
2442 		mutex_exit(&uacp->usb_ac_mutex);
2443 		usb_ac_restore_device_state(dip, uacp);
2444 		mutex_enter(&uacp->usb_ac_mutex);
2445 	}
2446 	uacp->usb_ac_busy_count--;
2447 
2448 	if (uacp->usb_ac_busy_count) {
2449 		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2450 		    "busy device has been reconnected");
2451 	}
2452 
2453 	mutex_exit(&uacp->usb_ac_mutex);
2454 
2455 	usb_ac_release_access(uacp);
2456 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2457 	    "usb_ac_reconnect_event_cb:done");
2458 
2459 	return (USB_SUCCESS);
2460 }
2461 
2462 
2463 /*
2464  * usb_ac_cpr_resume:
2465  *	Restore device state
2466  */
2467 static void
2468 usb_ac_cpr_resume(dev_info_t *dip)
2469 {
2470 	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2471 	    usb_ac_statep, ddi_get_instance(dip));
2472 
2473 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2474 	    "usb_ac_cpr_resume");
2475 
2476 	usb_ac_serialize_access(uacp);
2477 
2478 	usb_ac_restore_device_state(dip, uacp);
2479 
2480 	usb_ac_release_access(uacp);
2481 }
2482 
2483 
2484 /*
2485  * usb_ac_restore_device_state:
2486  *	Set original configuration of the device
2487  *	enable wrq - this starts new transactions on the control pipe
2488  */
2489 static void
2490 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp)
2491 {
2492 	usb_ac_power_t	*uacpm;
2493 	int	rval;
2494 
2495 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2496 	    "usb_ac_restore_device_state:");
2497 
2498 	usb_ac_pm_busy_component(uacp);
2499 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2500 
2501 	/* Check if we are talking to the same device */
2502 	if (usb_check_same_device(dip, uacp->usb_ac_log_handle,
2503 	    USB_LOG_L0, PRINT_MASK_ALL,
2504 	    USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
2505 		usb_ac_pm_idle_component(uacp);
2506 
2507 		/* change the device state from suspended to disconnected */
2508 		mutex_enter(&uacp->usb_ac_mutex);
2509 		uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2510 		mutex_exit(&uacp->usb_ac_mutex);
2511 
2512 		return;
2513 	}
2514 
2515 	mutex_enter(&uacp->usb_ac_mutex);
2516 	uacpm = uacp->usb_ac_pm;
2517 	if (uacpm) {
2518 		if (uacpm->acpm_wakeup_enabled) {
2519 			mutex_exit(&uacp->usb_ac_mutex);
2520 
2521 			if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip,
2522 			    USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
2523 
2524 				USB_DPRINTF_L4(PRINT_MASK_ATTA,
2525 				    uacp->usb_ac_log_handle,
2526 				    "usb_ac_restore_device_state: "
2527 				    "remote wakeup "
2528 				    "enable failed, rval=%d", rval);
2529 			}
2530 
2531 			mutex_enter(&uacp->usb_ac_mutex);
2532 		}
2533 	}
2534 
2535 	/* prevent unplumbing */
2536 	uacp->usb_ac_busy_count++;
2537 	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
2538 	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) {
2539 		(void) usb_ac_restore_audio_state(uacp, 0);
2540 	}
2541 	uacp->usb_ac_busy_count--;
2542 	mutex_exit(&uacp->usb_ac_mutex);
2543 	usb_ac_pm_idle_component(uacp);
2544 }
2545 
2546 
2547 /*
2548  * usb_ac_am_restore_state
2549  */
2550 static void
2551 usb_ac_am_restore_state(void *arg)
2552 {
2553 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
2554 
2555 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2556 	    "usb_ac_am_restore_state: Begin");
2557 
2558 	usb_ac_serialize_access(uacp);
2559 
2560 	mutex_enter(&uacp->usb_ac_mutex);
2561 
2562 	if (uacp->usb_ac_plumbing_state ==
2563 	    USB_AC_STATE_PLUMBED_RESTORING) {
2564 		mutex_exit(&uacp->usb_ac_mutex);
2565 
2566 		/*
2567 		 * allow hid and usb_as to restore themselves
2568 		 * (some handshake would have been preferable though)
2569 		 */
2570 		delay(USB_AC_RESTORE_DELAY);
2571 
2572 		usb_restore_engine(uacp);
2573 
2574 		mutex_enter(&uacp->usb_ac_mutex);
2575 		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
2576 	}
2577 
2578 	/* allow unplumbing */
2579 	uacp->usb_ac_busy_count--;
2580 	mutex_exit(&uacp->usb_ac_mutex);
2581 
2582 	usb_ac_release_access(uacp);
2583 
2584 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2585 	    "usb_ac_am_restore_state: End");
2586 }
2587 
2588 
2589 /*
2590  * usb_ac_restore_audio_state:
2591  */
2592 static int
2593 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
2594 {
2595 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
2596 
2597 
2598 	switch (uacp->usb_ac_plumbing_state) {
2599 	case USB_AC_STATE_PLUMBED:
2600 		uacp->usb_ac_plumbing_state =
2601 		    USB_AC_STATE_PLUMBED_RESTORING;
2602 
2603 		break;
2604 	case USB_AC_STATE_UNPLUMBED:
2605 
2606 		return (USB_SUCCESS);
2607 	case USB_AC_STATE_PLUMBED_RESTORING:
2608 	default:
2609 
2610 		return (USB_FAILURE);
2611 	}
2612 
2613 	/*
2614 	 * increment busy_count again, it will be decremented
2615 	 * in usb_ac_am_restore_state
2616 	 */
2617 	uacp->usb_ac_busy_count++;
2618 
2619 	if (flag & USB_FLAGS_SLEEP) {
2620 		mutex_exit(&uacp->usb_ac_mutex);
2621 		usb_ac_am_restore_state((void *)uacp);
2622 		mutex_enter(&uacp->usb_ac_mutex);
2623 	} else {
2624 		mutex_exit(&uacp->usb_ac_mutex);
2625 		if (usb_async_req(uacp->usb_ac_dip,
2626 		    usb_ac_am_restore_state,
2627 		    (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) {
2628 
2629 			mutex_enter(&uacp->usb_ac_mutex);
2630 			uacp->usb_ac_busy_count--;
2631 
2632 			return (USB_FAILURE);
2633 		}
2634 		mutex_enter(&uacp->usb_ac_mutex);
2635 	}
2636 
2637 	return (USB_SUCCESS);
2638 }
2639 
2640 
2641 /*
2642  * Mixer Callback Management
2643  * NOTE: all mixer callbacks are serialized. we cannot be closed while
2644  *	we are in the middle of a callback. There needs to be a
2645  *	teardown first. We cannot be unplumbed as long as we are
2646  *	still open.
2647  *
2648  * usb_ac_setup:
2649  *	Send setup to usb_as if the first setup
2650  *	Check power is done in usb_ac_send_as_cmd()
2651  */
2652 static int
2653 usb_ac_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2654 {
2655 	int	rval = USB_SUCCESS;
2656 
2657 
2658 	mutex_enter(&uacp->usb_ac_mutex);
2659 
2660 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2661 		mutex_exit(&uacp->usb_ac_mutex);
2662 
2663 		return (USB_FAILURE);
2664 	}
2665 	mutex_exit(&uacp->usb_ac_mutex);
2666 
2667 	usb_ac_serialize_access(uacp);
2668 
2669 
2670 	rval = usb_ac_do_setup(uacp, engine);
2671 
2672 	usb_ac_release_access(uacp);
2673 
2674 	return (rval);
2675 }
2676 
2677 
2678 /*
2679  * usb_ac_do_setup:
2680  *	Wrapper function for usb_ac_setup which can be called
2681  *	either from audio framework for usb_ac_set_format
2682  */
2683 static int
2684 usb_ac_do_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2685 {
2686 	usb_ac_streams_info_t	*streams_infop = NULL;
2687 
2688 
2689 	mutex_enter(&uacp->usb_ac_mutex);
2690 
2691 
2692 	streams_infop = (usb_ac_streams_info_t *)engine->streams;
2693 
2694 	/*
2695 	 * Handle multiple setup calls. Pass the setup call to usb_as only
2696 	 * the first time so isoc pipe will be opened only once
2697 	 */
2698 	if (streams_infop->acs_setup_teardown_count++) {
2699 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2700 		    "usb_ac_do_setup: more than one setup, cnt=%d",
2701 		    streams_infop->acs_setup_teardown_count);
2702 
2703 		mutex_exit(&uacp->usb_ac_mutex);
2704 
2705 		return (USB_SUCCESS);
2706 	}
2707 
2708 	/* Send setup command to usb_as */
2709 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SETUP, 0) !=
2710 	    USB_SUCCESS) {
2711 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2712 		    "usb_ac_do_setup: failure");
2713 
2714 		streams_infop->acs_setup_teardown_count--;
2715 
2716 		mutex_exit(&uacp->usb_ac_mutex);
2717 
2718 		return (USB_FAILURE);
2719 	}
2720 
2721 	mutex_exit(&uacp->usb_ac_mutex);
2722 
2723 	return (USB_SUCCESS);
2724 }
2725 
2726 
2727 /*
2728  * usb_ac_teardown:
2729  *	Send teardown to usb_as if the last teardown
2730  *	Check power is done in usb_ac_send_as_cmd()
2731  *	NOTE: allow teardown when disconnected
2732  */
2733 static void
2734 usb_ac_teardown(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2735 {
2736 
2737 	usb_ac_streams_info_t	*streams_infop = NULL;
2738 
2739 	usb_ac_serialize_access(uacp);
2740 
2741 
2742 	streams_infop = engine->streams;
2743 
2744 
2745 	mutex_enter(&uacp->usb_ac_mutex);
2746 
2747 
2748 
2749 	/* There should be at least one matching setup call */
2750 	ASSERT(streams_infop->acs_setup_teardown_count);
2751 
2752 	/*
2753 	 * Handle multiple setup/teardown calls. Pass the call to usb_as
2754 	 * only this is the last teardown so that isoc pipe is closed
2755 	 * only once
2756 	 */
2757 	if (--(streams_infop->acs_setup_teardown_count)) {
2758 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2759 		    "usb_ac_teardown: more than one setup/teardown, "
2760 		    "cnt=%d",
2761 		    streams_infop->acs_setup_teardown_count);
2762 
2763 		goto done;
2764 	}
2765 
2766 	/* Send teardown command to usb_as */
2767 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_TEARDOWN,
2768 	    (void *)NULL) != USB_SUCCESS) {
2769 
2770 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2771 		    "usb_ac_teardown: failure");
2772 
2773 		streams_infop->acs_setup_teardown_count++;
2774 
2775 
2776 		goto done;
2777 	}
2778 done:
2779 
2780 	mutex_exit(&uacp->usb_ac_mutex);
2781 
2782 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2783 	    "usb_ac_teardown: End");
2784 	usb_ac_release_access(uacp);
2785 }
2786 
2787 
2788 /*
2789  * usb_ac_set_monitor_gain:
2790  *	called for each output terminal which supports
2791  *	from usb_ac_traverse_connections
2792  */
2793 static int
2794 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
2795     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2796 {
2797 	usb_audio_output_term_descr_t *d =
2798 	    uacp->usb_ac_units[unit].acu_descriptor;
2799 
2800 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2801 	    "usb_ac_set_monitor_gain: ");
2802 
2803 	/* log how we got here */
2804 	usb_ac_push_unit_id(uacp, unit);
2805 	usb_ac_show_traverse_path(uacp);
2806 	usb_ac_pop_unit_id(uacp, unit);
2807 
2808 	/* we only care about the ITs connected to real hw inputs */
2809 	switch (d->wTerminalType) {
2810 	case USB_AUDIO_TERM_TYPE_STREAMING:
2811 
2812 		return (USB_FAILURE);
2813 
2814 	case USB_AUDIO_TERM_TYPE_DT_MICROPHONE:
2815 	case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE:
2816 	case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE:
2817 	case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY:
2818 	case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY:
2819 	default:
2820 
2821 		break;
2822 	}
2823 
2824 	/*
2825 	 * we can only do this if the microphone is mixed into the
2826 	 * audio output so look for a mixer first
2827 	 */
2828 	if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) ==
2829 	    USB_SUCCESS) {
2830 		int i, id;
2831 
2832 		/* now look for a feature unit */
2833 		for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0;
2834 		    i--) {
2835 			id = uacp->usb_ac_traverse_path[i];
2836 
2837 			switch (uacp->usb_ac_unit_type[id]) {
2838 			case USB_AUDIO_MIXER_UNIT:
2839 
2840 				/* the FU should be before the mixer */
2841 				return (USB_FAILURE);
2842 
2843 			case USB_AUDIO_FEATURE_UNIT:
2844 				/*
2845 				 * now set the volume
2846 				 */
2847 				if (usb_ac_set_gain(uacp, id, dir, channel,
2848 				    control, gain, depth) != USB_SUCCESS) {
2849 
2850 					/* try master channel */
2851 					if (usb_ac_set_gain(uacp, id, dir,
2852 					    0, control, gain, depth) !=
2853 					    USB_SUCCESS) {
2854 
2855 						return (USB_FAILURE);
2856 					}
2857 				}
2858 
2859 				return (USB_SUCCESS);
2860 
2861 			default:
2862 				continue;
2863 			}
2864 		}
2865 	}
2866 
2867 	return (USB_FAILURE);
2868 }
2869 
2870 
2871 /*
2872  * usb_ac_set_gain is called for each feature unit which supports
2873  * the requested controls from usb_ac_traverse_connections
2874  * we still need to check whether this unit supports the requested
2875  * control.
2876  */
2877 static int
2878 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
2879     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2880 {
2881 	short max, min, current;
2882 
2883 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2884 	    "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
2885 	    featureID, dir, channel, control, gain);
2886 
2887 	if (usb_ac_feature_unit_check(uacp, featureID,
2888 	    dir, channel, control, gain, depth) != USB_SUCCESS) {
2889 
2890 		return (USB_FAILURE);
2891 	}
2892 
2893 	if (usb_ac_get_maxmin_volume(uacp, channel,
2894 	    USB_AUDIO_GET_MAX, dir, featureID, &max) != USB_SUCCESS) {
2895 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2896 		    "usb_ac_set_gain: getting max gain failed");
2897 
2898 		return (USB_FAILURE);
2899 	}
2900 
2901 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2902 	    "usb_ac_set_gain: channel %d, max=%d", channel, max);
2903 
2904 	if (usb_ac_get_maxmin_volume(uacp, channel,
2905 	    USB_AUDIO_GET_MIN, dir, featureID, &min) != USB_SUCCESS) {
2906 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2907 		    "usb_ac_set_gain: getting min gain failed");
2908 
2909 		return (USB_FAILURE);
2910 	}
2911 
2912 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2913 	    "usb_ac_set_gain: channel=%d, min=%d", channel, min);
2914 
2915 	if (usb_ac_get_maxmin_volume(uacp, channel,
2916 	    USB_AUDIO_GET_CUR, dir, featureID, &current) != USB_SUCCESS) {
2917 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2918 		    "usb_ac_set_gain: getting cur gain failed");
2919 
2920 		return (USB_FAILURE);
2921 	}
2922 
2923 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2924 	    "usb_ac_set_gain: channel=%d, cur=%d", channel, current);
2925 
2926 	/*
2927 	 * Set the gain for a channel. The audio mixer calculates the
2928 	 * impact, if any, on the channel's gain.
2929 	 *
2930 	 *	0 <= gain <= AUDIO_MAX_GAIN
2931 	 *
2932 	 *	channel #, 0 == left, 1 == right
2933 	 */
2934 
2935 	if (gain == 0) {
2936 		gain = USB_AUDIO_VOLUME_SILENCE;
2937 	} else {
2938 		gain = max - ((max - min) * (AF_MAX_GAIN - gain))/AF_MAX_GAIN;
2939 	}
2940 
2941 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2942 	    "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
2943 	    channel, dir, max, min, gain);
2944 
2945 	if (usb_ac_set_volume(uacp, channel, gain, dir,
2946 	    featureID) != USB_SUCCESS) {
2947 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2948 		    "usb_ac_set_gain: setting volume failed");
2949 
2950 		return (USB_FAILURE);
2951 	}
2952 
2953 	/* just curious, read it back, device may round up/down */
2954 	if (usb_ac_get_maxmin_volume(uacp, channel,
2955 	    USB_AUDIO_GET_CUR, dir, featureID, &current) != USB_SUCCESS) {
2956 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2957 		    "usb_ac_set_gain: getting cur gain failed");
2958 	}
2959 
2960 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2961 	    "usb_ac_set_gain done: "
2962 	    "id=%d channel=%d, cur=%d gain=%d", featureID, channel,
2963 	    (ushort_t)current, (ushort_t)gain);
2964 
2965 	return (USB_SUCCESS);
2966 }
2967 
2968 
2969 /*
2970  * usb_ac_set_format
2971  *	This mixer callback initiates a command to be sent to
2972  *	usb_as to select an alternate with the passed characteristics
2973  *	and also to set the sample frequency.
2974  *	Note that this may be called when a playing is going on in
2975  *	the streaming interface. To handle that, first stop
2976  *	playing/recording, close the pipe by sending a teardown
2977  *	command, send the set_format command down and then reopen
2978  *	the pipe. Note : (1) audio framework will restart play/record
2979  *	after a set_format command. (2) Check power is done in
2980  *	usb_ac_send_as_cmd().
2981  */
2982 int
2983 usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2984 {
2985 	usb_ac_streams_info_t	*streams_infop = NULL;
2986 	usb_audio_formats_t	format;
2987 	int old_setup_teardown_count = 0;
2988 
2989 	mutex_enter(&uacp->usb_ac_mutex);
2990 	streams_infop = (usb_ac_streams_info_t *)engine->streams;
2991 
2992 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2993 		mutex_exit(&uacp->usb_ac_mutex);
2994 
2995 		return (USB_FAILURE);
2996 	}
2997 	mutex_exit(&uacp->usb_ac_mutex);
2998 
2999 	usb_ac_serialize_access(uacp);
3000 	mutex_enter(&uacp->usb_ac_mutex);
3001 
3002 	bzero(&format, sizeof (usb_audio_formats_t));
3003 
3004 	/* save format info */
3005 	format.fmt_n_srs	= 1;
3006 	format.fmt_srs		= (uint_t *)&(engine->fmt.sr);
3007 	format.fmt_chns		= (uchar_t)engine->fmt.ch;
3008 	format.fmt_precision	= (uchar_t)engine->fmt.prec;
3009 	format.fmt_encoding	= (uchar_t)engine->fmt.enc;
3010 
3011 	old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3012 
3013 	/* isoc pipe not open and playing is not in progress */
3014 	if (old_setup_teardown_count) {
3015 		streams_infop->acs_setup_teardown_count = 1;
3016 
3017 		mutex_exit(&uacp->usb_ac_mutex);
3018 		usb_ac_release_access(uacp);
3019 
3020 		usb_ac_stop_play(uacp, engine);
3021 		usb_ac_teardown(uacp, engine);
3022 
3023 		usb_ac_serialize_access(uacp);
3024 		mutex_enter(&uacp->usb_ac_mutex);
3025 	}
3026 
3027 	/*
3028 	 * Set format for the streaming interface with lower write queue
3029 	 * This boils down to set_alternate  interface command in
3030 	 * usb_as and the reply mp contains the currently active
3031 	 * alternate number that is stored in the as_req structure
3032 	 */
3033 	if (usb_ac_send_as_cmd(uacp, engine,
3034 	    USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
3035 		USB_DPRINTF_L2(PRINT_MASK_ALL,
3036 		    uacp->usb_ac_log_handle,
3037 		    "usb_ac_set_format: failed");
3038 		goto fail;
3039 
3040 	}
3041 	int sample =  engine->fmt.sr;
3042 
3043 	/* Set the sample rate */
3044 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
3045 	    &sample) != USB_SUCCESS) {
3046 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3047 		    "usb_ac_set_format: setting format failed");
3048 		goto fail;
3049 
3050 	}
3051 
3052 	mutex_exit(&uacp->usb_ac_mutex);
3053 
3054 	usb_ac_release_access(uacp);
3055 
3056 	/* This should block until successful */
3057 	if (old_setup_teardown_count) {
3058 		(void) usb_ac_setup(uacp, engine);
3059 	}
3060 
3061 	mutex_enter(&uacp->usb_ac_mutex);
3062 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3063 	mutex_exit(&uacp->usb_ac_mutex);
3064 
3065 	return (USB_SUCCESS);
3066 fail:
3067 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3068 	mutex_exit(&uacp->usb_ac_mutex);
3069 	usb_ac_release_access(uacp);
3070 
3071 	return (USB_FAILURE);
3072 
3073 }
3074 
3075 /*
3076  * usb_ac_start_play
3077  *	Send a start_play command down to usb_as
3078  *	Check power is done in usb_ac_send_as_cmd()
3079  */
3080 static int
3081 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3082 {
3083 	int			samples;
3084 	usb_audio_play_req_t	play_req;
3085 
3086 
3087 	mutex_enter(&uacp->usb_ac_mutex);
3088 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3089 		mutex_exit(&uacp->usb_ac_mutex);
3090 
3091 		return (USB_FAILURE);
3092 	}
3093 	mutex_exit(&uacp->usb_ac_mutex);
3094 
3095 	usb_ac_serialize_access(uacp);
3096 
3097 	mutex_enter(&uacp->usb_ac_mutex);
3098 
3099 
3100 
3101 	/* Check for continuous sample rate done in usb_as */
3102 	samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
3103 	if (samples & engine->fmt.ch) {
3104 		samples++;
3105 	}
3106 
3107 	play_req.up_samples = samples;
3108 	play_req.up_handle = uacp;
3109 
3110 	/* Send setup command to usb_as */
3111 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
3112 	    (void *)&play_req) != USB_SUCCESS) {
3113 
3114 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3115 		    "usb_ac_start_play: failure");
3116 
3117 		mutex_exit(&uacp->usb_ac_mutex);
3118 
3119 		usb_ac_release_access(uacp);
3120 
3121 		return (USB_FAILURE);
3122 	}
3123 
3124 	mutex_exit(&uacp->usb_ac_mutex);
3125 
3126 	usb_ac_release_access(uacp);
3127 
3128 	return (USB_SUCCESS);
3129 }
3130 
3131 
3132 /*
3133  * usb_ac_stop_play:
3134  *	Stop the play engine
3135  *	called from mixer framework.
3136  */
3137 void
3138 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3139 {
3140 
3141 	if (engine == NULL) {
3142 		engine = &(uacp->engines[0]);
3143 	}
3144 	mutex_enter(&uacp->usb_ac_mutex);
3145 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3146 		mutex_exit(&uacp->usb_ac_mutex);
3147 
3148 		return;
3149 	}
3150 	mutex_exit(&uacp->usb_ac_mutex);
3151 
3152 	usb_ac_serialize_access(uacp);
3153 	mutex_enter(&uacp->usb_ac_mutex);
3154 
3155 	/* Send setup command to usb_as */
3156 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
3157 	    (void *)NULL) != USB_SUCCESS) {
3158 
3159 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3160 		    "usb_ac_do_pause_play: failure");
3161 	}
3162 
3163 	mutex_exit(&uacp->usb_ac_mutex);
3164 	usb_ac_release_access(uacp);
3165 }
3166 
3167 
3168 /*
3169  * usb_ac_start_record:
3170  *	Sends a start record command down to usb_as.
3171  *	Check power is done in usb_ac_send_as_cmd()
3172  */
3173 static int
3174 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3175 {
3176 
3177 
3178 	mutex_enter(&uacp->usb_ac_mutex);
3179 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3180 		mutex_exit(&uacp->usb_ac_mutex);
3181 
3182 		return (USB_FAILURE);
3183 	}
3184 	mutex_exit(&uacp->usb_ac_mutex);
3185 
3186 	usb_ac_serialize_access(uacp);
3187 	mutex_enter(&uacp->usb_ac_mutex);
3188 
3189 
3190 	/* Send setup command to usb_as */
3191 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
3192 	    (void *)uacp) != USB_SUCCESS) {
3193 
3194 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3195 		    "usb_ac_start_record: failure");
3196 
3197 		mutex_exit(&uacp->usb_ac_mutex);
3198 
3199 		usb_ac_release_access(uacp);
3200 
3201 		return (USB_FAILURE);
3202 	}
3203 
3204 	mutex_exit(&uacp->usb_ac_mutex);
3205 	usb_ac_release_access(uacp);
3206 
3207 	return (USB_SUCCESS);
3208 }
3209 
3210 
3211 /*
3212  * usb_ac_stop_record:
3213  *	Wrapper function for usb_ac_do_stop_record and is
3214  *	called form mixer framework.
3215  */
3216 static void
3217 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3218 {
3219 
3220 	usb_ac_serialize_access(uacp);
3221 	mutex_enter(&uacp->usb_ac_mutex);
3222 
3223 	/* Send setup command to usb_as */
3224 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
3225 	    NULL) != USB_SUCCESS) {
3226 
3227 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3228 		    "usb_ac_do_stop_record: failure");
3229 	}
3230 
3231 	mutex_exit(&uacp->usb_ac_mutex);
3232 	usb_ac_release_access(uacp);
3233 }
3234 
3235 
3236 /*
3237  * Helper Functions for Mixer callbacks
3238  *
3239  * usb_ac_get_maxmin_volume:
3240  *	Send USBA command down to get the maximum or minimum gain balance
3241  *	Calculate min or max gain balance and return that. Return
3242  *	USB_FAILURE for failure cases
3243  */
3244 /* ARGSUSED */
3245 static int
3246 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
3247     int dir, int feature_unitID, short *max_or_minp)
3248 {
3249 	mblk_t		*data = NULL;
3250 	usb_cr_t	cr;
3251 	usb_cb_flags_t	cb_flags;
3252 
3253 
3254 	mutex_exit(&uacp->usb_ac_mutex);
3255 
3256 	if (usb_pipe_sync_ctrl_xfer(
3257 	    uacp->usb_ac_dip,
3258 	    uacp->usb_ac_default_ph,
3259 	    USB_DEV_REQ_DEV_TO_HOST |
3260 	    USB_DEV_REQ_TYPE_CLASS |
3261 	    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
3262 	    cmd,			/* bRequest */
3263 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3264 					/* feature unit and id */
3265 	    (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
3266 	    2,				/* wLength */
3267 	    &data,
3268 	    USB_ATTRS_NONE,
3269 	    &cr, &cb_flags,
3270 	    USB_FLAGS_SLEEP) != USB_SUCCESS) {
3271 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3272 		    "usb_ac_get_maxmin_volume: failed, "
3273 		    "cr=%d, cb=0x%x cmd=%d, data=0x%p",
3274 		    cr, cb_flags, cmd, (void *)data);
3275 
3276 		freemsg(data);
3277 		mutex_enter(&uacp->usb_ac_mutex);
3278 
3279 		return (USB_FAILURE);
3280 	}
3281 
3282 	mutex_enter(&uacp->usb_ac_mutex);
3283 	ASSERT(MBLKL(data) == 2);
3284 
3285 	*max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr;
3286 
3287 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3288 	    "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp);
3289 
3290 	freemsg(data);
3291 
3292 	return (USB_SUCCESS);
3293 }
3294 
3295 
3296 /*
3297  * usb_ac_set_volume:
3298  *	Send USBA command down to set the gain balance
3299  */
3300 /* ARGSUSED */
3301 static int
3302 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
3303     int feature_unitID)
3304 {
3305 	mblk_t		*data = NULL;
3306 	usb_cr_t	cr;
3307 	usb_cb_flags_t	cb_flags;
3308 	int		rval = USB_FAILURE;
3309 
3310 
3311 	mutex_exit(&uacp->usb_ac_mutex);
3312 
3313 	/* Construct the mblk_t from gain for sending to USBA */
3314 	data = allocb(4, BPRI_HI);
3315 	if (!data) {
3316 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3317 		    "usb_ac_set_volume: allocate data failed");
3318 		mutex_enter(&uacp->usb_ac_mutex);
3319 
3320 		return (USB_FAILURE);
3321 	}
3322 
3323 
3324 
3325 	*(data->b_wptr++) = (char)gain;
3326 	*(data->b_wptr++) = (char)(gain >> 8);
3327 
3328 	if ((rval = usb_pipe_sync_ctrl_xfer(
3329 	    uacp->usb_ac_dip,
3330 	    uacp->usb_ac_default_ph,
3331 	    USB_DEV_REQ_HOST_TO_DEV |
3332 	    USB_DEV_REQ_TYPE_CLASS |
3333 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3334 	    USB_AUDIO_SET_CUR,			/* bRequest */
3335 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3336 						/* feature unit and id */
3337 	    (feature_unitID << 8) | uacp->usb_ac_ifno,	/* wIndex */
3338 	    2,					/* wLength */
3339 	    &data, 0,
3340 	    &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
3341 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3342 		    "usb_ac_set_volume: failed, cr=%d cb=0x%x",
3343 		    cr, cb_flags);
3344 	}
3345 
3346 	freemsg(data);
3347 	mutex_enter(&uacp->usb_ac_mutex);
3348 
3349 	return (rval);
3350 }
3351 
3352 
3353 /*
3354  * usb_ac_set_mute is called for each unit that supports the
3355  * requested control from usb_ac_traverse_connections
3356  */
3357 int
3358 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
3359     uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
3360 {
3361 	mblk_t		*data;
3362 	usb_cr_t	cr;
3363 	usb_cb_flags_t	cb_flags;
3364 	int		rval = USB_FAILURE;
3365 
3366 
3367 	if (usb_ac_feature_unit_check(uacp, featureID,
3368 	    dir, channel, control, 0, depth) != USB_SUCCESS) {
3369 
3370 		return (USB_FAILURE);
3371 	}
3372 	mutex_exit(&uacp->usb_ac_mutex);
3373 
3374 	/* Construct the mblk_t for sending to USBA */
3375 	data = allocb(1, BPRI_HI);
3376 
3377 	if (!data) {
3378 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3379 		    "usb_ac_set_mute: allocate data failed");
3380 		mutex_enter(&uacp->usb_ac_mutex);
3381 
3382 		return (USB_FAILURE);
3383 	}
3384 
3385 
3386 	*(data->b_wptr++) = (char)muteval;
3387 
3388 	if ((rval = usb_pipe_sync_ctrl_xfer(
3389 	    uacp->usb_ac_dip,
3390 	    uacp->usb_ac_default_ph,
3391 	    USB_DEV_REQ_HOST_TO_DEV |
3392 	    USB_DEV_REQ_TYPE_CLASS |
3393 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3394 	    USB_AUDIO_SET_CUR,			/* bRequest */
3395 	    (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
3396 						/* feature unit and id */
3397 	    (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
3398 	    1,					/* wLength */
3399 	    &data,
3400 	    0,					/* attributes */
3401 	    &cr, &cb_flags, 0)) != USB_SUCCESS) {
3402 
3403 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3404 		    "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
3405 	}
3406 	freemsg(data);
3407 
3408 	mutex_enter(&uacp->usb_ac_mutex);
3409 
3410 	return (rval);
3411 }
3412 
3413 
3414 /*
3415  * usb_ac_send_as_cmd:
3416  *	Allocate message blk, send a command down to usb_as,
3417  *	wait for the reply and free the message
3418  *
3419  *	although not really needed to raise power if sending to as
3420  *	it seems better to ensure that both interfaces are at full power
3421  */
3422 static int
3423 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
3424     int cmd, void *arg)
3425 {
3426 	usb_ac_streams_info_t *streams_infop;
3427 	usb_ac_plumbed_t *plumb_infop;
3428 	int		rv;
3429 	int		rval;
3430 	ldi_handle_t	lh;
3431 
3432 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3433 	streams_infop = engine->streams;
3434 	plumb_infop = streams_infop->acs_plumbed;
3435 
3436 
3437 	lh = plumb_infop->acp_lh;
3438 
3439 	rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval);
3440 	if (rv != 0) {
3441 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3442 		    "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv);
3443 
3444 		return (USB_FAILURE);
3445 	}
3446 
3447 	return (USB_SUCCESS);
3448 }
3449 
3450 
3451 /*
3452  * usb_ac_serialize/release_access:
3453  */
3454 static void
3455 usb_ac_serialize_access(usb_ac_state_t	*uacp)
3456 {
3457 	(void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3458 }
3459 
3460 static void
3461 usb_ac_release_access(usb_ac_state_t *uacp)
3462 {
3463 	usb_release_access(uacp->usb_ac_ser_acc);
3464 }
3465 
3466 
3467 static void
3468 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
3469 {
3470 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3471 
3472 	if (usb_ac_statep->usb_ac_pm != NULL) {
3473 		mutex_enter(&usb_ac_statep->usb_ac_mutex);
3474 		usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
3475 
3476 		USB_DPRINTF_L4(PRINT_MASK_PM,
3477 		    usb_ac_statep->usb_ac_log_handle,
3478 		    "usb_ac_pm_busy_component: %d",
3479 		    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3480 
3481 		mutex_exit(&usb_ac_statep->usb_ac_mutex);
3482 
3483 		if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
3484 		    DDI_SUCCESS) {
3485 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3486 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3487 
3488 			USB_DPRINTF_L2(PRINT_MASK_PM,
3489 			    usb_ac_statep->usb_ac_log_handle,
3490 			    "usb_ac_pm_busy_component failed: %d",
3491 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3492 
3493 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
3494 		}
3495 	}
3496 }
3497 
3498 
3499 static void
3500 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
3501 {
3502 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3503 
3504 	if (usb_ac_statep->usb_ac_pm != NULL) {
3505 		if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
3506 		    DDI_SUCCESS) {
3507 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3508 			ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
3509 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3510 
3511 			USB_DPRINTF_L4(PRINT_MASK_PM,
3512 			    usb_ac_statep->usb_ac_log_handle,
3513 			    "usb_ac_pm_idle_component: %d",
3514 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3515 
3516 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
3517 		}
3518 	}
3519 }
3520 
3521 
3522 /*
3523  * handle read from plumbed drivers
3524  */
3525 static void
3526 usb_ac_reader(void *argp)
3527 {
3528 	usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp;
3529 	usb_ac_state_t *uacp = acp->acp_uacp;
3530 	ldi_handle_t lh;
3531 	mblk_t *mp;
3532 	int rv;
3533 	timestruc_t tv = {0};
3534 
3535 	mutex_enter(&uacp->usb_ac_mutex);
3536 	lh = acp->acp_lh;
3537 	tv.tv_sec = usb_ac_wait_hid;
3538 
3539 	while (acp->acp_flags & ACP_ENABLED) {
3540 		mp = NULL;
3541 
3542 		mutex_exit(&uacp->usb_ac_mutex);
3543 
3544 		rv = ldi_getmsg(lh, &mp, &tv);
3545 
3546 		mutex_enter(&uacp->usb_ac_mutex);
3547 
3548 		if (rv == ENODEV) {
3549 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3550 			    "Device is not availabe");
3551 			break;
3552 		}
3553 
3554 
3555 		if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0)
3556 			rv = usb_ac_read_msg(acp, mp);
3557 
3558 	}
3559 	mutex_exit(&uacp->usb_ac_mutex);
3560 }
3561 
3562 
3563 /*
3564  * setup threads to read from the other usb modules that may send unsolicited
3565  * or asynchronous messages, which is only hid currently
3566  */
3567 static int
3568 usb_ac_plumb(usb_ac_plumbed_t *acp)
3569 {
3570 	usb_ac_state_t	*uacp = acp->acp_uacp;
3571 	dev_info_t	*dip;
3572 	dev_info_t	*acp_dip;
3573 	int		acp_inst;
3574 	char		*acp_name;
3575 	char		tq_nm[128];
3576 	int		rv = USB_FAILURE;
3577 
3578 	mutex_enter(&uacp->usb_ac_mutex);
3579 
3580 	dip = uacp->usb_ac_dip;
3581 
3582 	acp_dip = acp->acp_dip;
3583 	acp_inst = ddi_get_instance(acp_dip);
3584 	acp_name = (char *)ddi_driver_name(acp_dip);
3585 
3586 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3587 	    "usb_ac_plumb:begin");
3588 
3589 	if (strcmp(acp_name, "hid") != 0) {
3590 		rv = USB_SUCCESS;
3591 		goto OUT;
3592 	}
3593 
3594 	(void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3595 	    ddi_driver_name(acp_dip), acp_inst);
3596 
3597 	acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3598 	if (acp->acp_tqp == NULL)
3599 		goto OUT;
3600 
3601 	if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp,
3602 	    DDI_SLEEP) != DDI_SUCCESS)
3603 		goto OUT;
3604 
3605 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3606 	    "usb_ac_plumb: dispatched reader");
3607 
3608 	rv = USB_SUCCESS;
3609 
3610 OUT:
3611 	mutex_exit(&uacp->usb_ac_mutex);
3612 
3613 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3614 	    "usb_ac_plumb: done, rv=%d", rv);
3615 
3616 	return (rv);
3617 }
3618 
3619 
3620 static void
3621 usb_ac_mux_plumbing_tq(void *arg)
3622 {
3623 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3624 
3625 	if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS)
3626 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3627 		    "usb_ac_mux_plumbing_tq:failed");
3628 }
3629 
3630 
3631 static int
3632 usb_ac_do_plumbing(usb_ac_state_t *uacp)
3633 {
3634 	dev_info_t *dip = uacp->usb_ac_dip;
3635 	int inst = ddi_get_instance(dip);
3636 	char tq_nm[128];
3637 	int rv = USB_FAILURE;
3638 
3639 	(void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3640 	    ddi_driver_name(dip), inst);
3641 
3642 	uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3643 	if (uacp->tqp == NULL) {
3644 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3645 		    "usb_ac_do_plumbing: ddi_taskq_create failed");
3646 		goto OUT;
3647 	}
3648 
3649 	if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp,
3650 	    DDI_SLEEP) != DDI_SUCCESS) {
3651 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3652 		    "usb_ac_do_plumbing: ddi_taskq_dispatch failed");
3653 		goto OUT;
3654 	}
3655 
3656 	rv = USB_SUCCESS;
3657 
3658 OUT:
3659 	return (rv);
3660 }
3661 
3662 
3663 
3664 static void
3665 usb_ac_mux_unplumbing_tq(void *arg)
3666 {
3667 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3668 
3669 	if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS)
3670 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3671 		    "usb_ac_mux_unplumbing:failed");
3672 }
3673 
3674 
3675 static int
3676 usb_ac_do_unplumbing(usb_ac_state_t *uacp)
3677 {
3678 	int rv = USB_FAILURE;
3679 
3680 	if (uacp->tqp == NULL)
3681 		return (USB_SUCCESS);
3682 
3683 	if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq,
3684 	    (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) {
3685 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3686 		    "usb_ac_do_unplumbing: ddi_taskq_dispatch failed");
3687 		goto OUT;
3688 	}
3689 
3690 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3691 	    "usb_ac_do_unplumbing: waiting for unplumb thread");
3692 
3693 	ddi_taskq_wait(uacp->tqp);
3694 	rv = USB_SUCCESS;
3695 
3696 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3697 	    "usb_ac_do_unplumbing: unplumb thread done");
3698 
3699 OUT:
3700 	if (uacp->tqp != NULL) {
3701 		ddi_taskq_destroy(uacp->tqp);
3702 		uacp->tqp = NULL;
3703 	}
3704 	return (rv);
3705 }
3706 
3707 
3708 /*
3709  * teardown threads to the other usb modules
3710  * and clear structures as part of unplumbing
3711  */
3712 static void
3713 usb_ac_unplumb(usb_ac_plumbed_t *acp)
3714 {
3715 	usb_ac_streams_info_t *streams_infop;
3716 	usb_ac_state_t	*uacp = acp->acp_uacp;
3717 
3718 
3719 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3720 	    "usb_ac_unplumb: begin");
3721 
3722 	if (acp->acp_tqp != NULL) {
3723 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3724 		    "usb_ac_unplumb: destroying taskq");
3725 
3726 		ddi_taskq_destroy(acp->acp_tqp);
3727 	}
3728 
3729 	mutex_enter(&uacp->usb_ac_mutex);
3730 
3731 	if (acp->acp_driver == USB_AS_PLUMBED) {
3732 		/*
3733 		 * we bzero the streams info and plumbed structure
3734 		 * since there is no guarantee that the next plumbing
3735 		 * will be identical
3736 		 */
3737 		streams_infop = (usb_ac_streams_info_t *)acp->acp_data;
3738 
3739 		/* bzero the relevant plumbing structure */
3740 		bzero(streams_infop, sizeof (usb_ac_streams_info_t));
3741 	}
3742 	bzero(acp, sizeof (usb_ac_plumbed_t));
3743 
3744 	mutex_exit(&uacp->usb_ac_mutex);
3745 
3746 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3747 	    "usb_ac_unplumb: done");
3748 }
3749 
3750 
3751 /*ARGSUSED*/
3752 static int
3753 usb_ac_mux_plumbing(usb_ac_state_t *uacp)
3754 {
3755 	dev_info_t		*dip;
3756 
3757 	/* get the usb_ac dip */
3758 	dip = uacp->usb_ac_dip;
3759 
3760 	/* Access to the global variables is synchronized */
3761 	mutex_enter(&uacp->usb_ac_mutex);
3762 
3763 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3764 	    "usb_ac_mux_plumbing:state = %d",
3765 	    uacp->usb_ac_plumbing_state);
3766 
3767 	if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) {
3768 		mutex_exit(&uacp->usb_ac_mutex);
3769 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3770 		    "usb_ac_mux_plumbing: audio streams driver"
3771 		    " already plumbed");
3772 
3773 		return (USB_SUCCESS);
3774 	}
3775 
3776 	/* usb_as and hid should be attached but double check */
3777 	if (usb_ac_online_siblings(uacp) != USB_SUCCESS) {
3778 		mutex_exit(&uacp->usb_ac_mutex);
3779 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3780 		"usb_ac_mux_plumbing:no audio streams driver plumbed");
3781 
3782 		return (USB_FAILURE);
3783 	}
3784 
3785 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3786 	    "usb_ac_mux_plumbing: raising power");
3787 	mutex_exit(&uacp->usb_ac_mutex);
3788 
3789 	/* bring the device to full power */
3790 	usb_ac_pm_busy_component(uacp);
3791 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3792 
3793 	/* avoid dips disappearing while we are plumbing */
3794 	usb_ac_hold_siblings(uacp);
3795 
3796 	mutex_enter(&uacp->usb_ac_mutex);
3797 
3798 	/*
3799 	 * walk all siblings and create the usb_ac<->usb_as and
3800 	 * usb_ac<->hid streams. return of 0 indicates no or
3801 	 * partial/failed plumbing
3802 	 */
3803 	if (usb_ac_mux_walk_siblings(uacp) == 0) {
3804 		/* pretend that we are plumbed so we can unplumb */
3805 		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3806 
3807 		mutex_exit(&uacp->usb_ac_mutex);
3808 
3809 		(void) usb_ac_mux_unplumbing(uacp);
3810 
3811 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3812 		    "usb_ac_mux_plumbing: no audio streams driver plumbed");
3813 
3814 		usb_ac_rele_siblings(uacp);
3815 
3816 		usb_ac_pm_idle_component(uacp);
3817 
3818 		return (USB_FAILURE);
3819 	}
3820 	uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3821 
3822 	/* restore state if we have already registered with the mixer */
3823 	if (uacp->usb_ac_registered_with_mixer) {
3824 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3825 		    "usb_ac_mux_plumbing:already registered with mixer,"
3826 		    "restoring state");
3827 
3828 		(void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP);
3829 
3830 	} else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) {
3831 		mutex_exit(&uacp->usb_ac_mutex);
3832 
3833 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3834 		    "usb_ac_mux_plumbing: mixer registration failed");
3835 
3836 		(void) usb_ac_mux_unplumbing(uacp);
3837 
3838 		usb_ac_rele_siblings(uacp);
3839 
3840 		usb_ac_pm_idle_component(uacp);
3841 
3842 		return (USB_FAILURE);
3843 	}
3844 
3845 	mutex_exit(&uacp->usb_ac_mutex);
3846 	usb_ac_rele_siblings(uacp);
3847 
3848 	usb_ac_pm_idle_component(uacp);
3849 
3850 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3851 	    "usb_ac_mux_plumbing:done");
3852 
3853 	return (USB_SUCCESS);
3854 }
3855 
3856 
3857 static int
3858 usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
3859 {
3860 	usb_ac_plumbed_t	*acp;
3861 	ldi_handle_t		lh;
3862 	dev_info_t		*acp_dip;
3863 	int			inst;
3864 	int			i;
3865 	dev_t			devt;
3866 	minor_t			minor;
3867 	int			maxlinked = 0;
3868 
3869 	mutex_enter(&uacp->usb_ac_mutex);
3870 
3871 
3872 	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) {
3873 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3874 		    "usb_ac_mux_unplumbing: already unplumbed!");
3875 		mutex_exit(&uacp->usb_ac_mutex);
3876 
3877 		return (USB_SUCCESS);
3878 	}
3879 
3880 	/* usb_ac might not have anything plumbed yet */
3881 	if (uacp->usb_ac_current_plumbed_index == -1) {
3882 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3883 		    "usb_ac_mux_unplumbing: nothing plumbed");
3884 		uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3885 		mutex_exit(&uacp->usb_ac_mutex);
3886 
3887 		return (USB_SUCCESS);
3888 	}
3889 
3890 	/* do not allow detach if still busy */
3891 	if (uacp->usb_ac_busy_count) {
3892 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3893 		    "usb_ac_mux_unplumbing: mux still busy (%d)",
3894 		    uacp->usb_ac_busy_count);
3895 		mutex_exit(&uacp->usb_ac_mutex);
3896 
3897 		return (USB_FAILURE);
3898 	}
3899 
3900 	uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3901 
3902 	/* close ac-as and ac-hid streams */
3903 	maxlinked = uacp->usb_ac_current_plumbed_index + 1;
3904 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3905 	    "usb_ac_mux_unplumbing: maxlinked = %d",  maxlinked);
3906 
3907 	for (i = 0; i < maxlinked; i++) {
3908 		/*
3909 		 * we must save members of usb_ac_plumbed[] before calling
3910 		 * usb_ac_unplumb() because it clears the structure
3911 		 */
3912 		acp = &uacp->usb_ac_plumbed[i];
3913 		lh = acp->acp_lh;
3914 		acp_dip = acp->acp_dip;
3915 		devt = acp->acp_devt;
3916 
3917 		if (acp_dip == NULL) {
3918 			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3919 			    "usb_ac_mux_unplumbing: [%d] - skipping",  i);
3920 			continue;
3921 		}
3922 
3923 		minor = getminor(devt);
3924 		inst = ddi_get_instance(acp_dip);
3925 
3926 		uacp->usb_ac_current_plumbed_index = i;
3927 
3928 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3929 		    "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x",  i,
3930 		    ddi_driver_name(acp_dip), inst, minor);
3931 
3932 		if (lh != NULL) {
3933 
3934 			acp->acp_flags &= ~ACP_ENABLED;
3935 
3936 			mutex_exit(&uacp->usb_ac_mutex);
3937 
3938 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3939 			    "usb_ac_mux_unplumbing:[%d] - closing", i);
3940 
3941 			/*
3942 			 * ldi_close will cause panic if ldi_getmsg
3943 			 * is not finished. ddi_taskq_destroy will wait
3944 			 * for the thread to complete.
3945 			 */
3946 			usb_ac_unplumb(acp);
3947 			(void) ldi_close(lh, FREAD|FWRITE, kcred);
3948 
3949 
3950 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3951 			    "usb_ac_mux_unplumbing: [%d] - unplumbed", i);
3952 
3953 			mutex_enter(&uacp->usb_ac_mutex);
3954 		}
3955 	}
3956 
3957 	mutex_exit(&uacp->usb_ac_mutex);
3958 
3959 	/* Wait till all activity in the default pipe has drained */
3960 	usb_ac_serialize_access(uacp);
3961 	usb_ac_release_access(uacp);
3962 
3963 	mutex_enter(&uacp->usb_ac_mutex);
3964 	uacp->usb_ac_current_plumbed_index = -1;
3965 	mutex_exit(&uacp->usb_ac_mutex);
3966 
3967 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3968 	    "usb_ac_mux_unplumbing: done");
3969 
3970 	return (USB_SUCCESS);
3971 }
3972 
3973 
3974 /*
3975  * walk all siblings and create the ac<->as and ac<->hid streams
3976  */
3977 static int
3978 usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
3979 {
3980 	dev_info_t	*pdip;
3981 	dev_info_t	*child_dip;
3982 	major_t		drv_major;
3983 	minor_t		drv_minor;
3984 	int		drv_instance;
3985 	char		*drv_name;
3986 	dev_t		drv_devt;
3987 	ldi_handle_t	drv_lh;
3988 	ldi_ident_t	li;
3989 	int		error;
3990 	int		count = 0;
3991 
3992 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3993 
3994 	pdip = ddi_get_parent(uacp->usb_ac_dip);
3995 	child_dip = ddi_get_child(pdip);
3996 
3997 	while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) {
3998 		drv_instance = ddi_get_instance(child_dip);
3999 		drv_name = (char *)ddi_driver_name(child_dip);
4000 
4001 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4002 		    "usb_ac_mux_walk_siblings: plumbing %s%d count=%d",
4003 		    drv_name, drv_instance, count);
4004 
4005 		/* ignore own dip */
4006 		if (child_dip == uacp->usb_ac_dip) {
4007 			child_dip = ddi_get_next_sibling(child_dip);
4008 			continue;
4009 		}
4010 		drv_instance = ddi_get_instance(child_dip);
4011 
4012 		/* ignore other dip other than usb_as and hid */
4013 		if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) {
4014 			uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED;
4015 			drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance);
4016 		} else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) {
4017 			uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED;
4018 			drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance);
4019 		} else {
4020 			drv_minor = drv_instance;
4021 			uacp->usb_ac_plumbed[count].acp_driver =
4022 			    UNKNOWN_PLUMBED;
4023 			child_dip = ddi_get_next_sibling(child_dip);
4024 
4025 			continue;
4026 		}
4027 
4028 		if (!i_ddi_devi_attached(child_dip)) {
4029 			child_dip = ddi_get_next_sibling(child_dip);
4030 
4031 			continue;
4032 		}
4033 
4034 		if (DEVI_IS_DEVICE_REMOVED(child_dip)) {
4035 			child_dip = ddi_get_next_sibling(child_dip);
4036 
4037 			continue;
4038 		}
4039 
4040 		drv_major = ddi_driver_major(child_dip);
4041 
4042 		uacp->usb_ac_current_plumbed_index = count;
4043 
4044 		mutex_exit(&uacp->usb_ac_mutex);
4045 
4046 		drv_devt = makedevice(drv_major, drv_minor);
4047 
4048 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4049 		    "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)",
4050 		    drv_name, drv_instance, drv_major, drv_minor);
4051 
4052 		error = ldi_ident_from_dip(uacp->usb_ac_dip, &li);
4053 		if (error == 0) {
4054 			mutex_enter(&uacp->usb_ac_mutex);
4055 			uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED;
4056 			mutex_exit(&uacp->usb_ac_mutex);
4057 
4058 			error = ldi_open_by_dev(&drv_devt, OTYP_CHR,
4059 			    FREAD|FWRITE, kcred, &drv_lh, li);
4060 			ldi_ident_release(li);
4061 		}
4062 
4063 		mutex_enter(&uacp->usb_ac_mutex);
4064 		if (error) {
4065 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4066 			    "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)"
4067 			    " failed error=%d", drv_major, drv_minor, error);
4068 
4069 			return (0);
4070 		}
4071 
4072 		uacp->usb_ac_plumbed[count].acp_uacp = uacp;
4073 		uacp->usb_ac_plumbed[count].acp_devt = drv_devt;
4074 		uacp->usb_ac_plumbed[count].acp_lh = drv_lh;
4075 		uacp->usb_ac_plumbed[count].acp_dip = child_dip;
4076 		uacp->usb_ac_plumbed[count].acp_ifno =
4077 		    usb_get_if_number(child_dip);
4078 
4079 		if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) {
4080 			/* get registration data */
4081 			if (usb_ac_get_reg_data(uacp, drv_lh, count) !=
4082 			    USB_SUCCESS) {
4083 
4084 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4085 				    uacp->usb_ac_log_handle,
4086 				    "usb_ac_mux_walk_siblings:"
4087 				    "usb_ac_get_reg_data failed on %s%d",
4088 				    drv_name, drv_instance);
4089 
4090 				uacp->usb_ac_plumbed[count].acp_dip = NULL;
4091 
4092 				return (0);
4093 			}
4094 		} else if (uacp->usb_ac_plumbed[count].acp_driver ==
4095 		    USB_AH_PLUMBED) {
4096 			int rval;
4097 
4098 			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4099 			    "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d",
4100 			    drv_name, drv_instance);
4101 
4102 			mutex_exit(&uacp->usb_ac_mutex);
4103 
4104 			/* push usb_ah module on top of hid */
4105 			error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah",
4106 			    FKIOCTL, kcred, &rval);
4107 			mutex_enter(&uacp->usb_ac_mutex);
4108 
4109 			if (error) {
4110 				USB_DPRINTF_L2(PRINT_MASK_ALL,
4111 				    uacp->usb_ac_log_handle,
4112 				    "usb_ac_mux_walk_siblings: ldi_ioctl"
4113 				    "I_PUSH failed on %s%d, error=%d",
4114 				    drv_name, drv_instance, error);
4115 
4116 				uacp->usb_ac_plumbed[count].acp_dip = NULL;
4117 
4118 				/* skip plumbing the hid driver */
4119 				child_dip = ddi_get_next_sibling(child_dip);
4120 				continue;
4121 			}
4122 		} else {
4123 			/* should not be here */
4124 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4125 			    "usb_ac_mux_walk_siblings:- unknown module %s%d",
4126 			    drv_name, drv_instance);
4127 			count--;
4128 
4129 			uacp->usb_ac_plumbed[count].acp_dip = NULL;
4130 
4131 			/* skip plumbing an unknown module */
4132 			child_dip = ddi_get_next_sibling(child_dip);
4133 			continue;
4134 		}
4135 
4136 		mutex_exit(&uacp->usb_ac_mutex);
4137 		error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]);
4138 		mutex_enter(&uacp->usb_ac_mutex);
4139 
4140 		if (error != USB_SUCCESS) {
4141 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4142 			    "usb_ac_mux_walk_siblings: usb_ac_plumb "
4143 			    "failed for %s%d", drv_name, drv_instance);
4144 
4145 			return (0);
4146 		}
4147 
4148 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4149 		    "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x",
4150 		    drv_instance, drv_minor);
4151 
4152 		child_dip = ddi_get_next_sibling(child_dip);
4153 		count++;
4154 	}
4155 
4156 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4157 	    "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux",
4158 	    count);
4159 
4160 	return (count);
4161 }
4162 
4163 
4164 /*
4165  * Register with mixer only after first plumbing.
4166  * Also do not register if earlier reg data
4167  * couldn't be received from at least one
4168  * streaming interface
4169  */
4170 
4171 static int
4172 usb_ac_mixer_registration(usb_ac_state_t *uacp)
4173 {
4174 	usb_as_registration_t *asreg;
4175 	int		n;
4176 
4177 	if (uacp->usb_ac_registered_with_mixer) {
4178 		return (USB_SUCCESS);
4179 	}
4180 
4181 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4182 		if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4183 			break;
4184 		}
4185 	}
4186 
4187 	/* Haven't found a streaming interface; fail mixer registration */
4188 	if (n > USB_AC_MAX_AS_PLUMBED) {
4189 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4190 		"usb_ac_mixer_registration:- no streaming interface found");
4191 
4192 		return (USB_FAILURE);
4193 	}
4194 
4195 	/*
4196 	 * Fill out streaming interface specific stuff
4197 	 * Note that we handle only one playing and one recording
4198 	 * streaming interface at the most
4199 	 */
4200 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4201 		int ch, chs, id;
4202 
4203 		if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) {
4204 			continue;
4205 		}
4206 
4207 		asreg = &(uacp->usb_ac_streams[n].acs_streams_reg);
4208 		if (asreg->reg_valid == 0) {
4209 			continue;
4210 		}
4211 
4212 
4213 		chs = asreg->reg_formats[0].fmt_chns;
4214 
4215 		/* check if any channel supports vol. control for this fmt */
4216 		for (ch = 0; ch <= chs; ch++) {
4217 			if ((id = usb_ac_get_featureID(uacp,
4218 			    asreg->reg_mode, ch,
4219 			    USB_AUDIO_VOLUME_CONTROL)) != -1) {
4220 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4221 				    uacp->usb_ac_log_handle,
4222 				    "usb_ac_mixer_registration:n= [%d]"
4223 				    "- dir=%d featureID=%d",
4224 				    n, asreg->reg_mode, id);
4225 
4226 				break;
4227 			}
4228 		}
4229 
4230 		uacp->usb_ac_streams[n].acs_default_gain =
4231 		    (id == USB_AC_ID_NONE) ?  (AF_MAX_GAIN): (AF_MAX_GAIN*3/4);
4232 
4233 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4234 		    "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d"
4235 		    "default_gain=%d id=%d",
4236 		    n, asreg->reg_mode, chs,
4237 		    uacp->usb_ac_streams[n].acs_default_gain, id);
4238 
4239 	}
4240 
4241 	/* the rest */
4242 
4243 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4244 	    "usb_ac_mixer_registration: calling usb_audio_register");
4245 
4246 	mutex_exit(&uacp->usb_ac_mutex);
4247 
4248 	if (usb_audio_register(uacp) != USB_SUCCESS) {
4249 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4250 		    "usb_ac_mixer_registration: usb_audio_register failed");
4251 
4252 		mutex_enter(&uacp->usb_ac_mutex);
4253 
4254 		return (USB_FAILURE);
4255 	}
4256 
4257 	mutex_enter(&uacp->usb_ac_mutex);
4258 
4259 	uacp->usb_ac_registered_with_mixer = 1;
4260 
4261 	return (USB_SUCCESS);
4262 }
4263 
4264 
4265 /*
4266  * Get registriations data when driver attach
4267  */
4268 static int
4269 usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
4270 {
4271 	int n, error, rval;
4272 	usb_as_registration_t *streams_reg;
4273 
4274 
4275 	ASSERT(uacp->usb_ac_registered_with_mixer == 0);
4276 
4277 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4278 		/*
4279 		 * We haven't received registration data
4280 		 * from n-th streaming interface in the array
4281 		 */
4282 		if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4283 			break;
4284 		}
4285 	}
4286 
4287 	if (n >= USB_AC_MAX_AS_PLUMBED) {
4288 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4289 		"More than 2 streaming interfaces (play "
4290 		"and/or record) currently not supported");
4291 
4292 		return (USB_FAILURE);
4293 	}
4294 
4295 	/* take the stream reg struct with the same index */
4296 	streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg;
4297 
4298 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4299 	"usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d",
4300 	    (void *)streams_reg, n);
4301 
4302 	mutex_exit(&uacp->usb_ac_mutex);
4303 
4304 	if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION,
4305 	    (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) {
4306 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4307 		    "usb_ac_get_reg_data: ldi_ioctl failed for"
4308 		    "mixer registration error=%d", error);
4309 
4310 		mutex_enter(&uacp->usb_ac_mutex);
4311 
4312 		return (USB_FAILURE);
4313 	} else {
4314 		mutex_enter(&uacp->usb_ac_mutex);
4315 
4316 		rval = usb_ac_setup_plumbed(uacp, index, n);
4317 
4318 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4319 		"usb_ac_get_reg_data:usb_ac_streams[%d]: "
4320 		    "received_reg_data=%d type=%s",  index,
4321 		    uacp->usb_ac_streams[n].acs_rcvd_reg_data,
4322 		    ((streams_reg->reg_mode == USB_AUDIO_PLAY) ?
4323 		    "play" : "record"));
4324 
4325 		usb_ac_print_reg_data(uacp, streams_reg);
4326 
4327 		return (rval);
4328 	}
4329 }
4330 
4331 
4332 /*
4333  * setup plumbed and stream info structure
4334  */
4335 static int
4336 usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx)
4337 {
4338 	uacp->usb_ac_plumbed[plb_idx].acp_data =
4339 	    &uacp->usb_ac_streams[str_idx];
4340 	uacp->usb_ac_streams[str_idx].acs_plumbed =
4341 	    &uacp->usb_ac_plumbed[plb_idx];
4342 	uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1;
4343 
4344 
4345 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4346 	    "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ",
4347 	    plb_idx, str_idx);
4348 
4349 	return (USB_SUCCESS);
4350 }
4351 
4352 
4353 /*
4354  * function to dump registration data
4355  */
4356 static void
4357 usb_ac_print_reg_data(usb_ac_state_t *uacp,
4358     usb_as_registration_t *reg)
4359 {
4360 	int n;
4361 
4362 	for (n = 0; n < reg->reg_n_formats; n++) {
4363 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4364 		    "format%d: alt=%d chns=%d prec=%d enc=%d", n,
4365 		    reg->reg_formats[n].fmt_alt,
4366 		    reg->reg_formats[n].fmt_chns,
4367 		    reg->reg_formats[n].fmt_precision,
4368 		    reg->reg_formats[n].fmt_encoding);
4369 	}
4370 
4371 	for (n = 0; n < USB_AS_N_FORMATS; n++) {
4372 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4373 		    "reg_formats[%d] ptr=0x%p", n,
4374 		    (void *)&reg->reg_formats[n]);
4375 	}
4376 
4377 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4378 	    "usb_ac_print_reg_data: End");
4379 }
4380 
4381 
4382 static int
4383 usb_ac_online_siblings(usb_ac_state_t *uacp)
4384 {
4385 	dev_info_t	*pdip, *child_dip;
4386 	int		rval = USB_SUCCESS;
4387 
4388 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4389 
4390 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4391 	    "usb_ac_online_siblings:start");
4392 
4393 	pdip = ddi_get_parent(uacp->usb_ac_dip);
4394 
4395 	child_dip = ddi_get_child(pdip);
4396 	while (child_dip != NULL) {
4397 
4398 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4399 		    "usb_ac_online_siblings: onlining %s%d ref=%d",
4400 		    ddi_driver_name(child_dip),
4401 		    ddi_get_instance(child_dip),
4402 		    DEVI(child_dip)->devi_ref);
4403 
4404 		/* Online the child_dip of usb_as and hid,  if not already */
4405 		if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) ||
4406 		    (strcmp(ddi_driver_name(child_dip), "hid") == 0)) {
4407 
4408 			mutex_exit(&uacp->usb_ac_mutex);
4409 			if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
4410 			    NDI_SUCCESS) {
4411 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4412 				    uacp->usb_ac_log_handle,
4413 				    "usb_ac_online_siblings:failed to online"
4414 				    "device %s%d", ddi_driver_name(child_dip),
4415 				    ddi_get_instance(child_dip));
4416 
4417 				/* only onlining usb_as is fatal */
4418 				if (strcmp(ddi_driver_name(child_dip),
4419 				    "usb_as") == 0) {
4420 					mutex_enter(&uacp->usb_ac_mutex);
4421 					rval = USB_FAILURE;
4422 					break;
4423 				}
4424 			}
4425 			mutex_enter(&uacp->usb_ac_mutex);
4426 		}
4427 		child_dip = ddi_get_next_sibling(child_dip);
4428 	}
4429 
4430 	return (rval);
4431 }
4432 
4433 
4434 /*
4435  * hold all audio children before or after plumbing
4436  * online usb_as and hid, if not already
4437  */
4438 static void
4439 usb_ac_hold_siblings(usb_ac_state_t *uacp)
4440 {
4441 	int		circ;
4442 	dev_info_t	*pdip, *child_dip;
4443 
4444 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4445 	    "usb_ac_hold_siblings:start");
4446 
4447 	/* hold all siblings and ourselves */
4448 	pdip = ddi_get_parent(uacp->usb_ac_dip);
4449 
4450 	/* hold the children */
4451 	ndi_devi_enter(pdip, &circ);
4452 	child_dip = ddi_get_child(pdip);
4453 	while (child_dip != NULL) {
4454 		ndi_hold_devi(child_dip);
4455 
4456 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4457 		    "usb_ac_hold_siblings: held %s%d ref=%d",
4458 		    ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4459 		    DEVI(child_dip)->devi_ref);
4460 
4461 		child_dip = ddi_get_next_sibling(child_dip);
4462 	}
4463 	ndi_devi_exit(pdip, circ);
4464 }
4465 
4466 
4467 /*
4468  * release all audio children before or after plumbing
4469  */
4470 static void
4471 usb_ac_rele_siblings(usb_ac_state_t *uacp)
4472 {
4473 	int		circ;
4474 	dev_info_t	*pdip, *child_dip;
4475 
4476 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4477 	    "usb_ac_rele_siblings: start");
4478 
4479 	/* release all siblings and ourselves */
4480 	pdip = ddi_get_parent(uacp->usb_ac_dip);
4481 	ndi_devi_enter(pdip, &circ);
4482 	child_dip = ddi_get_child(pdip);
4483 	while (child_dip != NULL) {
4484 		ndi_rele_devi(child_dip);
4485 
4486 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4487 		    "usb_ac_rele_siblings: released %s%d ref=%d",
4488 		    ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4489 		    DEVI(child_dip)->devi_ref);
4490 
4491 		child_dip = ddi_get_next_sibling(child_dip);
4492 	}
4493 	ndi_devi_exit(pdip, circ);
4494 }
4495 static void
4496 usb_restore_engine(usb_ac_state_t *statep)
4497 {
4498 	usb_audio_eng_t *engp;
4499 	int i;
4500 
4501 	for (i = 0; i < USB_AC_ENG_MAX; i++) {
4502 
4503 		mutex_enter(&statep->usb_ac_mutex);
4504 		engp = &statep->engines[i];
4505 		mutex_exit(&statep->usb_ac_mutex);
4506 
4507 		if (engp->af_engp == NULL)
4508 			continue;
4509 		if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
4510 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
4511 			    statep->usb_ac_log_handle,
4512 			    "usb_restore_engine:set format fail, i=%d", i);
4513 			return;
4514 		}
4515 		if (engp->started) {
4516 			(void) usb_engine_start(engp);
4517 		}
4518 
4519 	}
4520 
4521 	(void) usb_ac_ctrl_restore(statep);
4522 }
4523 
4524 
4525 /*
4526  * get the maximum format specification the device supports
4527  */
4528 static void
4529 usb_ac_max_fmt(usb_as_registration_t *reg_data,
4530     usb_audio_format_t *fmtp)
4531 {
4532 
4533 	uint_t ch = 0, sr = 0, prec = 0, enc = 0;
4534 	int i;
4535 
4536 	usb_audio_formats_t *reg_formats = reg_data->reg_formats;
4537 
4538 	/* format priority: channels, sample rate, precision, encoding */
4539 	for (i = 0; i < reg_data->reg_n_formats; i++) {
4540 		uint_t val, fmt_sr;
4541 		int n, keep;
4542 
4543 		val = reg_formats[i].fmt_chns;
4544 		if (val < ch)
4545 			continue;
4546 		if (val > ch)
4547 			keep = 1;
4548 
4549 		for (n = 0, fmt_sr = 0; n < reg_formats[i].fmt_n_srs; n++) {
4550 			if (fmt_sr < reg_formats[i].fmt_srs[n]) {
4551 				fmt_sr = reg_formats[i].fmt_srs[n];
4552 			}
4553 		}
4554 		if (!keep && fmt_sr < sr)
4555 			continue;
4556 		if (fmt_sr > sr)
4557 			keep = 1;
4558 
4559 		val = reg_formats[i].fmt_precision;
4560 		if (!keep && (val < prec))
4561 			continue;
4562 		if (val > prec)
4563 			keep = 1;
4564 
4565 		val = reg_formats[i].fmt_encoding;
4566 		if (!keep && (val < enc))
4567 			continue;
4568 
4569 		ch   = reg_formats[i].fmt_chns;
4570 		sr   = fmt_sr;
4571 		prec = reg_formats[i].fmt_precision;
4572 		enc  = reg_formats[i].fmt_encoding;
4573 	}
4574 
4575 	fmtp->ch   = ch;
4576 	fmtp->sr   = sr;
4577 	fmtp->prec = prec;
4578 	fmtp->enc  = enc;
4579 }
4580 
4581 
4582 static void
4583 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
4584 {
4585 	if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
4586 		return;
4587 
4588 	audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
4589 	audio_engine_free(engp->af_engp);
4590 
4591 	mutex_enter(&engp->lock);
4592 	engp->af_engp = NULL;
4593 	engp->streams = NULL;
4594 	mutex_exit(&engp->lock);
4595 
4596 	mutex_destroy(&engp->lock);
4597 	cv_destroy(&engp->usb_audio_cv);
4598 }
4599 
4600 
4601 static int
4602 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t  *asinfo)
4603 {
4604 	audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
4605 	usb_audio_eng_t *engp;
4606 	audio_engine_t *af_engp;
4607 	int rv = USB_FAILURE;
4608 	int dir = asinfo->acs_streams_reg.reg_mode;
4609 	uint_t defgain;
4610 
4611 	if (asinfo->acs_rcvd_reg_data == 0) {
4612 
4613 		return (USB_SUCCESS);
4614 	}
4615 	if (dir == USB_AUDIO_PLAY) {
4616 		engp = &(uacp->engines[0]);
4617 	} else {
4618 		engp = &(uacp->engines[1]);
4619 	}
4620 
4621 	cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL);
4622 
4623 	mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
4624 
4625 	mutex_enter(&engp->lock);
4626 
4627 	engp->af_eflags =
4628 	    (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
4629 	engp->statep = uacp;
4630 
4631 	/* Set the format for the engine */
4632 	usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
4633 
4634 	/* init the default gain */
4635 	defgain = asinfo->acs_default_gain;
4636 	if (engp->fmt.ch == 2) {
4637 		engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
4638 	} else {
4639 		engp->af_defgain = defgain;
4640 	}
4641 	engp->streams = asinfo;
4642 
4643 	mutex_exit(&engp->lock);
4644 
4645 	af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
4646 	if (af_engp == NULL) {
4647 
4648 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4649 		    "audio_engine_alloc failed");
4650 		goto OUT;
4651 	}
4652 	ASSERT(engp->af_engp == 0);
4653 
4654 	mutex_enter(&engp->lock);
4655 	engp->af_engp = af_engp;
4656 	mutex_exit(&engp->lock);
4657 
4658 	audio_engine_set_private(af_engp, engp);
4659 	audio_dev_add_engine(af_devp, af_engp);
4660 
4661 	/*
4662 	 * Set the format for this engine
4663 	 */
4664 	if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
4665 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4666 		    "set format failed, dir = %d", dir);
4667 		goto OUT;
4668 	}
4669 	rv = USB_SUCCESS;
4670 
4671 OUT:
4672 	if (rv != USB_SUCCESS)
4673 		usb_ac_rem_eng(uacp, engp);
4674 
4675 	return (rv);
4676 }
4677 
4678 
4679 static int
4680 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
4681 {
4682 	usb_audio_ctrl_t *ctrlp;
4683 	int rv = USB_SUCCESS;
4684 	USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4685 	    "usb_ac_ctrl_set_defaults:begin");
4686 
4687 	for (int i = 0; i < CTL_NUM; i++) {
4688 		ctrlp = statep->controls[i];
4689 		if (!ctrlp) {
4690 			continue;
4691 		}
4692 		if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4693 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
4694 			    statep->usb_ac_log_handle,
4695 			    "usb_ac_ctrl_set_defaults:control write failed");
4696 			rv = USB_FAILURE;
4697 		}
4698 
4699 	}
4700 	USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4701 	    "usb_ac_ctrl_set_defaults:end");
4702 	return (rv);
4703 }
4704 
4705 
4706 static int
4707 usb_ac_ctrl_restore(usb_ac_state_t *statep)
4708 {
4709 	usb_audio_ctrl_t *ctrlp;
4710 	int rv = USB_SUCCESS;
4711 
4712 	for (int i = 0; i < CTL_NUM; i++) {
4713 		ctrlp = statep->controls[i];
4714 		if (ctrlp) {
4715 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
4716 			    statep->usb_ac_log_handle,
4717 			    "usb_ac_ctrl_restore:i = %d", i);
4718 			if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4719 				rv = USB_FAILURE;
4720 			}
4721 		}
4722 	}
4723 	return (rv);
4724 }
4725 
4726 
4727 
4728 
4729 /*
4730  * moves data between driver buffer and framework/shim buffer
4731  */
4732 static void
4733 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
4734 {
4735 	size_t cpsz = sz;
4736 	caddr_t *src, *dst;
4737 
4738 	if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
4739 		src = &engp->bufpos;
4740 		dst = (caddr_t *)&buf;
4741 	} else {
4742 		src = (caddr_t *)&buf;
4743 		dst = &engp->bufpos;
4744 	}
4745 
4746 	/*
4747 	 * Wrap.  If sz is exactly the remainder of the buffer
4748 	 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
4749 	 * the second memcpy() should have no effect, with bufpos updated
4750 	 * to the head of the buffer.
4751 	 */
4752 	if (engp->bufpos + sz >= engp->bufendp) {
4753 		cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
4754 		(void) memcpy(*dst, *src, cpsz);
4755 
4756 
4757 		buf = (caddr_t)buf + cpsz;
4758 		engp->bufpos = engp->bufp;
4759 		cpsz = sz - cpsz;
4760 	}
4761 
4762 	if (cpsz) {
4763 		(void) memcpy(*dst, *src, cpsz);
4764 
4765 
4766 		engp->bufpos += cpsz;
4767 	}
4768 	engp->bufio_count++;
4769 }
4770 
4771 
4772 /*
4773  * control read callback
4774  */
4775 static int
4776 usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
4777 {
4778 	usb_audio_ctrl_t *ctrlp = arg;
4779 
4780 	mutex_enter(&ctrlp->ctrl_mutex);
4781 	*cvalp = ctrlp->cval;
4782 	mutex_exit(&ctrlp->ctrl_mutex);
4783 
4784 	return (0);
4785 }
4786 
4787 
4788 /*
4789  * stereo level control callback
4790  */
4791 static int
4792 usb_audio_write_stero_rec(void *arg, uint64_t cval)
4793 {
4794 	usb_audio_ctrl_t *ctrlp = arg;
4795 	usb_ac_state_t *statep = ctrlp->statep;
4796 	int rv = EIO;
4797 	int left, right;
4798 	uint_t count = 0;
4799 
4800 
4801 	left = AUDIO_CTRL_STEREO_LEFT(cval);
4802 	right = AUDIO_CTRL_STEREO_RIGHT(cval);
4803 
4804 	if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4805 	    right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4806 
4807 		return (EINVAL);
4808 	}
4809 
4810 	mutex_enter(&ctrlp->ctrl_mutex);
4811 	ctrlp->cval = cval;
4812 	mutex_exit(&ctrlp->ctrl_mutex);
4813 
4814 	mutex_enter(&statep->usb_ac_mutex);
4815 	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4816 	    USB_AUDIO_FEATURE_UNIT, 1,
4817 	    USB_AUDIO_VOLUME_CONTROL,
4818 	    USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4819 
4820 	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4821 	    USB_AUDIO_FEATURE_UNIT, 2,
4822 	    USB_AUDIO_VOLUME_CONTROL,
4823 	    USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4824 	rv = 0;
4825 
4826 done:
4827 	mutex_exit(&statep->usb_ac_mutex);
4828 	return (rv);
4829 }
4830 
4831 static int
4832 usb_audio_write_ster_vol(void *arg, uint64_t cval)
4833 {
4834 	usb_audio_ctrl_t *ctrlp = arg;
4835 	usb_ac_state_t *statep = ctrlp->statep;
4836 	int rv = EIO;
4837 	int left, right;
4838 	uint_t count = 0;
4839 
4840 	left = AUDIO_CTRL_STEREO_LEFT(cval);
4841 	right = AUDIO_CTRL_STEREO_RIGHT(cval);
4842 
4843 	if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4844 	    right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4845 		return (EINVAL);
4846 	}
4847 
4848 	mutex_enter(&ctrlp->ctrl_mutex);
4849 	ctrlp->cval = cval;
4850 	mutex_exit(&ctrlp->ctrl_mutex);
4851 
4852 
4853 	mutex_enter(&statep->usb_ac_mutex);
4854 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4855 	    USB_AUDIO_FEATURE_UNIT, 1,
4856 	    USB_AUDIO_VOLUME_CONTROL,
4857 	    USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4858 
4859 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4860 	    USB_AUDIO_FEATURE_UNIT, 2,
4861 	    USB_AUDIO_VOLUME_CONTROL,
4862 	    USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4863 	rv = 0;
4864 
4865 OUT:
4866 	mutex_exit(&statep->usb_ac_mutex);
4867 	return (rv);
4868 }
4869 
4870 
4871 /*
4872  * mono level control callback
4873  */
4874 static int
4875 usb_audio_write_mono_vol(void *arg, uint64_t cval)
4876 {
4877 	usb_audio_ctrl_t *ctrlp = arg;
4878 	usb_ac_state_t *statep = ctrlp->statep;
4879 	int rv = EIO;
4880 	int gain;
4881 
4882 	uint_t count = 0;
4883 
4884 	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4885 		return (EINVAL);
4886 	}
4887 
4888 	mutex_enter(&ctrlp->ctrl_mutex);
4889 	ctrlp->cval = cval;
4890 	mutex_exit(&ctrlp->ctrl_mutex);
4891 
4892 	gain = (int)(cval);
4893 
4894 	mutex_enter(&statep->usb_ac_mutex);
4895 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4896 	    USB_AUDIO_FEATURE_UNIT, 1,
4897 	    USB_AUDIO_VOLUME_CONTROL,
4898 	    USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4899 
4900 	rv = 0;
4901 OUT:
4902 	mutex_exit(&statep->usb_ac_mutex);
4903 
4904 	return (rv);
4905 }
4906 
4907 
4908 /*
4909  * mono level control callback
4910  */
4911 static int
4912 usb_audio_write_monitor_gain(void *arg, uint64_t cval)
4913 {
4914 	usb_audio_ctrl_t *ctrlp = arg;
4915 	usb_ac_state_t *statep = ctrlp->statep;
4916 	int rv = EIO;
4917 	int gain;
4918 	uint_t count = 0;
4919 
4920 	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4921 
4922 		return (EINVAL);
4923 	}
4924 
4925 	mutex_enter(&ctrlp->ctrl_mutex);
4926 	ctrlp->cval = cval;
4927 	mutex_exit(&ctrlp->ctrl_mutex);
4928 
4929 	gain = (int)(cval);
4930 
4931 	mutex_enter(&statep->usb_ac_mutex);
4932 	(void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
4933 	    USB_AUDIO_INPUT_TERMINAL, 1,
4934 	    USB_AUDIO_VOLUME_CONTROL,
4935 	    USB_AC_FIND_ALL, &count, gain,
4936 	    usb_ac_set_monitor_gain);
4937 
4938 	rv = 0;
4939 OUT:
4940 	mutex_exit(&statep->usb_ac_mutex);
4941 	return (rv);
4942 }
4943 
4944 static int
4945 usb_audio_write_mono_rec(void *arg, uint64_t cval)
4946 {
4947 	usb_audio_ctrl_t *ctrlp = arg;
4948 	usb_ac_state_t *statep = ctrlp->statep;
4949 	int rv = EIO;
4950 	int gain;
4951 
4952 	uint_t count = 0;
4953 
4954 	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4955 
4956 		return (EINVAL);
4957 	}
4958 
4959 	mutex_enter(&ctrlp->ctrl_mutex);
4960 	ctrlp->cval = cval;
4961 	mutex_exit(&ctrlp->ctrl_mutex);
4962 
4963 	gain = (int)(cval);
4964 
4965 	mutex_enter(&statep->usb_ac_mutex);
4966 	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4967 	    USB_AUDIO_FEATURE_UNIT, 1,
4968 	    USB_AUDIO_VOLUME_CONTROL,
4969 	    USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4970 
4971 	rv = 0;
4972 
4973 	mutex_exit(&statep->usb_ac_mutex);
4974 	return (rv);
4975 }
4976 
4977 static int
4978 usb_audio_write_mic_boost(void *arg, uint64_t cval)
4979 {
4980 	usb_audio_ctrl_t *ctrlp = arg;
4981 
4982 	mutex_enter(&ctrlp->ctrl_mutex);
4983 	ctrlp->cval = cval;
4984 	mutex_exit(&ctrlp->ctrl_mutex);
4985 	/* do nothing here */
4986 	return (0);
4987 }
4988 
4989 static int
4990 usb_audio_write_rec_src(void *arg, uint64_t cval)
4991 {
4992 	usb_audio_ctrl_t *ctrlp = arg;
4993 	usb_ac_state_t *statep = ctrlp->statep;
4994 	int rv = 0;
4995 
4996 	if (cval & ~(statep->usb_ac_input_ports))
4997 		return (EINVAL);
4998 
4999 	mutex_enter(&ctrlp->ctrl_mutex);
5000 	ctrlp->cval = cval;
5001 	mutex_exit(&ctrlp->ctrl_mutex);
5002 
5003 	mutex_enter(&statep->usb_ac_mutex);
5004 	if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
5005 
5006 		USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
5007 		    "usb_audio_write_rec_src: failed");
5008 		rv = EINVAL;
5009 	}
5010 	mutex_exit(&statep->usb_ac_mutex);
5011 	rv = 0;
5012 
5013 OUT:
5014 	return (rv);
5015 
5016 }
5017 
5018 
5019 int
5020 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
5021 {
5022 	short	muteval;
5023 	int	rval;
5024 
5025 	uint_t count;
5026 	muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
5027 	count = 0;
5028 	/* only support AUDIO_PLAY */
5029 
5030 	mutex_enter(&statep->usb_ac_mutex);
5031 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
5032 	    USB_AUDIO_FEATURE_UNIT, 0,
5033 	    USB_AUDIO_MUTE_CONTROL,
5034 	    USB_AC_FIND_ALL, &count, muteval,
5035 	    usb_ac_set_mute);
5036 	mutex_exit(&statep->usb_ac_mutex);
5037 
5038 	rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
5039 
5040 	return (rval);
5041 }
5042 
5043 
5044 /*
5045  * port selection control callback
5046  */
5047 /*
5048  * audio control registration related routines
5049  */
5050 
5051 static usb_audio_ctrl_t *
5052 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
5053 {
5054 	audio_ctrl_desc_t	desc;
5055 	audio_ctrl_wr_t		fn;
5056 	usb_audio_ctrl_t	*pc;
5057 
5058 	pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
5059 
5060 	mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
5061 
5062 	bzero(&desc, sizeof (desc));
5063 
5064 	switch (num) {
5065 	case CTL_VOLUME_MONO:
5066 		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5067 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5068 		desc.acd_minvalue = 0;
5069 		desc.acd_maxvalue = AF_MAX_GAIN;
5070 		desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5071 		    | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5072 		fn = usb_audio_write_mono_vol;
5073 		break;
5074 
5075 	case CTL_VOLUME_STERO:
5076 		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5077 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5078 		desc.acd_minvalue = 0;
5079 		desc.acd_maxvalue = AF_MAX_GAIN;
5080 		desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5081 		    | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5082 		fn = usb_audio_write_ster_vol;
5083 
5084 		break;
5085 
5086 	case CTL_REC_MONO:
5087 		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5088 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5089 		desc.acd_minvalue = 0;
5090 		desc.acd_maxvalue = AF_MAX_GAIN;
5091 		desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5092 		    | AUDIO_CTRL_FLAG_RW;
5093 		fn = usb_audio_write_mono_rec;
5094 		break;
5095 	case CTL_REC_STERO:
5096 
5097 		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5098 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5099 		desc.acd_minvalue = 0;
5100 		desc.acd_maxvalue = AF_MAX_GAIN;
5101 		desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5102 		    | AUDIO_CTRL_FLAG_RW;
5103 		fn = usb_audio_write_stero_rec;
5104 		break;
5105 
5106 	case CTL_MONITOR_GAIN:
5107 
5108 		desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
5109 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5110 		desc.acd_minvalue = 0;
5111 		desc.acd_maxvalue = AF_MAX_GAIN;
5112 		desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
5113 		    |AUDIO_CTRL_FLAG_RW;
5114 		fn = usb_audio_write_monitor_gain;
5115 		break;
5116 
5117 	case CTL_MIC_BOOST:
5118 
5119 		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
5120 		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
5121 		desc.acd_minvalue = 0;
5122 		desc.acd_maxvalue = 1;
5123 		desc.acd_flags = AUDIO_CTRL_FLAG_RW;
5124 		fn = usb_audio_write_mic_boost;
5125 		break;
5126 	case CTL_REC_SRC:
5127 
5128 		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
5129 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
5130 		desc.acd_minvalue = statep->usb_ac_input_ports;
5131 		desc.acd_maxvalue = statep->usb_ac_input_ports;
5132 		desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
5133 		for (int i = 0; usb_audio_dtypes[i]; i++) {
5134 			desc.acd_enum[i] = usb_audio_dtypes[i];
5135 		}
5136 
5137 		fn = usb_audio_write_rec_src;
5138 		break;
5139 
5140 
5141 
5142 	default:
5143 
5144 		break;
5145 	}
5146 
5147 	mutex_enter(&pc->ctrl_mutex);
5148 
5149 	pc->statep = statep;
5150 	pc->cval = val;
5151 	pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
5152 	    usb_audio_ctrl_read, fn, pc);
5153 
5154 	mutex_exit(&pc->ctrl_mutex);
5155 
5156 	mutex_enter(&statep->usb_ac_mutex);
5157 	statep->controls[num] = pc;
5158 	mutex_exit(&statep->usb_ac_mutex);
5159 
5160 
5161 	return (pc);
5162 }
5163 
5164 
5165 static void
5166 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
5167 {
5168 	kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
5169 }
5170 
5171 static void
5172 usb_ac_rem_controls(usb_ac_state_t *statep)
5173 {
5174 	usb_audio_ctrl_t *ctrlp;
5175 
5176 	for (int i = 0; i < CTL_NUM; i++) {
5177 		ctrlp = statep->controls[i];
5178 		if (ctrlp) {
5179 			if (ctrlp->af_ctrlp != NULL)
5180 				audio_dev_del_control(ctrlp->af_ctrlp);
5181 
5182 			usb_audio_ctrl_free(ctrlp);
5183 			mutex_enter(&statep->usb_ac_mutex);
5184 			statep->controls[i] = NULL;
5185 			mutex_exit(&statep->usb_ac_mutex);
5186 		}
5187 	}
5188 
5189 }
5190 
5191 
5192 static int
5193 usb_ac_add_controls(usb_ac_state_t *statep)
5194 {
5195 	int rv = USB_FAILURE;
5196 	usb_audio_format_t *format;
5197 
5198 
5199 	if (statep->engines[0].af_engp) {
5200 		/* Init controls for play format */
5201 		format = &(statep->engines[0].fmt);
5202 		if (format->ch == 2) {
5203 			(void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
5204 			    statep->engines[0].af_defgain);
5205 		} else {
5206 			(void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
5207 			    statep->engines[0].af_defgain);
5208 		}
5209 
5210 	}
5211 
5212 	/* Init controls for rec format */
5213 	if (statep->engines[1].af_engp) {
5214 		format = &(statep->engines[1].fmt);
5215 		if (format->ch == 2) {
5216 			(void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
5217 			    statep->engines[1].af_defgain);
5218 		} else {
5219 			(void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
5220 			    statep->engines[1].af_defgain);
5221 		}
5222 
5223 		/* Add monitor control */
5224 		{
5225 			(void) usb_audio_ctrl_alloc(statep,
5226 			    CTL_MONITOR_GAIN, 0);
5227 		}
5228 
5229 		/* Add ports control */
5230 		{
5231 			(void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
5232 			    statep->usb_ac_input_ports);
5233 		}
5234 
5235 	}
5236 
5237 
5238 	rv = USB_SUCCESS;
5239 
5240 OUT:
5241 	if (rv != USB_SUCCESS)
5242 		usb_ac_rem_controls(statep);
5243 	return (rv);
5244 }
5245 
5246 
5247 
5248 
5249 
5250 /*ARGSUSED*/
5251 static int
5252 usb_audio_unregister(usb_ac_state_t *statep)
5253 {
5254 	int i;
5255 
5256 	if (statep == NULL)
5257 		return (USB_SUCCESS);
5258 
5259 	if (statep->usb_ac_audio_dev == NULL)
5260 		return (USB_SUCCESS);
5261 
5262 	if ((statep->flags & AF_REGISTERED) &&
5263 	    audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
5264 		return (USB_FAILURE);
5265 	}
5266 	mutex_enter(&statep->usb_ac_mutex);
5267 	statep->flags &= ~AF_REGISTERED;
5268 	mutex_exit(&statep->usb_ac_mutex);
5269 
5270 	for (i = 0; i < USB_AC_ENG_MAX; i++)
5271 		usb_ac_rem_eng(statep, &statep->engines[i]);
5272 
5273 	usb_ac_rem_controls(statep);
5274 
5275 	audio_dev_free(statep->usb_ac_audio_dev);
5276 
5277 	mutex_enter(&statep->usb_ac_mutex);
5278 	statep->usb_ac_audio_dev = NULL;
5279 	mutex_exit(&statep->usb_ac_mutex);
5280 
5281 	return (USB_SUCCESS);
5282 }
5283 
5284 
5285 static int
5286 usb_audio_register(usb_ac_state_t *statep) {
5287 	audio_dev_t *af_devp;
5288 	int rv = USB_FAILURE;
5289 	int n;
5290 
5291 	af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
5292 	audio_dev_set_description(af_devp,  "USB Audio");
5293 	audio_dev_set_version(af_devp, "1.0");
5294 
5295 	mutex_enter(&statep->usb_ac_mutex);
5296 	statep->usb_ac_audio_dev = af_devp;
5297 	mutex_exit(&statep->usb_ac_mutex);
5298 
5299 
5300 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
5301 		if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
5302 		    != USB_SUCCESS) {
5303 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
5304 			    statep->usb_ac_log_handle,
5305 			    "usb_audio_register: add engine n =%d failed", n);
5306 			goto OUT;
5307 		}
5308 	}
5309 
5310 
5311 	if (usb_ac_add_controls(statep) != USB_SUCCESS) {
5312 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5313 		    "usb_audio_register: add controls failed");
5314 		goto OUT;
5315 	}
5316 
5317 	if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
5318 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5319 		    "usb_audio_register: set defaults failed");
5320 		goto OUT;
5321 	}
5322 
5323 	if (audio_dev_register(af_devp) != DDI_SUCCESS) {
5324 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5325 		    "audio_dev_register() failed");
5326 		goto OUT;
5327 	}
5328 	mutex_enter(&statep->usb_ac_mutex);
5329 	statep->flags |= AF_REGISTERED;
5330 	mutex_exit(&statep->usb_ac_mutex);
5331 
5332 	rv = USB_SUCCESS;
5333 
5334 OUT:
5335 	if (rv != USB_SUCCESS) {
5336 		(void) usb_audio_unregister(statep);
5337 	}
5338 	return (rv);
5339 }
5340 
5341 
5342 int
5343 usb_ac_get_audio(void *handle, void *buf, int samples)
5344 {
5345 	usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5346 	usb_audio_eng_t *engp = &(statep->engines[0]);
5347 	unsigned reqframes = samples >> engp->frsmshift;
5348 	unsigned frames;
5349 	unsigned i;
5350 	size_t sz;
5351 	caddr_t bp = buf;
5352 
5353 	mutex_enter(&engp->lock);
5354 	if (!engp->started) {
5355 		mutex_exit(&engp->lock);
5356 
5357 		return (0);
5358 	}
5359 	engp->busy = B_TRUE;
5360 	mutex_exit(&engp->lock);
5361 
5362 	/* break requests from the driver into fragment sized chunks */
5363 	for (i = 0; i < reqframes; i += frames) {
5364 
5365 		mutex_enter(&engp->lock);
5366 		frames = reqframes - i;
5367 		if (frames > engp->fragfr)
5368 			frames = engp->fragfr;
5369 
5370 		sz = (frames << engp->frsmshift) << engp->smszshift;
5371 
5372 		/* must move data before updating framework */
5373 		usb_eng_bufio(engp, bp, sz);
5374 		engp->frames += frames;
5375 		bp += sz;
5376 
5377 		mutex_exit(&engp->lock);
5378 	}
5379 
5380 	mutex_enter(&engp->lock);
5381 	engp->io_count++;
5382 	engp->busy = B_FALSE;
5383 	cv_signal(&engp->usb_audio_cv);
5384 	mutex_exit(&engp->lock);
5385 
5386 	return (samples);
5387 }
5388 
5389 
5390 
5391 void
5392 usb_ac_send_audio(void *handle, void *buf, int samples)
5393 {
5394 	usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5395 	usb_audio_eng_t *engp = &(statep->engines[1]);
5396 	unsigned reqframes = samples >> engp->frsmshift;
5397 	unsigned frames;
5398 	unsigned i;
5399 	size_t sz;
5400 	caddr_t bp = buf;
5401 
5402 	mutex_enter(&engp->lock);
5403 
5404 	if (!engp->started) {
5405 
5406 		mutex_exit(&engp->lock);
5407 		return;
5408 	}
5409 	engp->busy = B_TRUE;
5410 	mutex_exit(&engp->lock);
5411 
5412 	/* break requests from the driver into fragment sized chunks */
5413 	for (i = 0; i < reqframes; i += frames) {
5414 		mutex_enter(&engp->lock);
5415 
5416 		frames = reqframes - i;
5417 		if (frames > engp->fragfr)
5418 			frames = engp->fragfr;
5419 
5420 		sz = (frames << engp->frsmshift) << engp->smszshift;
5421 
5422 		/* must move data before updating framework */
5423 		usb_eng_bufio(engp, bp, sz);
5424 		engp->frames += frames;
5425 		bp += sz;
5426 
5427 		mutex_exit(&engp->lock);
5428 	}
5429 
5430 	mutex_enter(&engp->lock);
5431 	engp->io_count++;
5432 	engp->busy = B_FALSE;
5433 	cv_signal(&engp->usb_audio_cv);
5434 	mutex_exit(&engp->lock);
5435 }
5436 
5437 
5438 /*
5439  * **************************************************************************
5440  * audio framework engine callbacks
5441  */
5442 static int
5443 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
5444 {
5445 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5446 	usb_ac_state_t *statep = engp->statep;
5447 	int rv = EIO;
5448 
5449 	_NOTE(ARGUNUSED(flag));
5450 
5451 	if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
5452 
5453 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5454 		    "usb_ac_open() failed");
5455 		return (EIO);
5456 	}
5457 
5458 	mutex_enter(&engp->lock);
5459 
5460 	engp->intrate =  150;
5461 	engp->sampsz = engp->fmt.prec / 8;
5462 	engp->framesz = engp->sampsz * engp->fmt.ch;
5463 
5464 	engp->frsmshift = engp->fmt.ch / 2;
5465 	engp->smszshift = engp->sampsz / 2;
5466 
5467 	/*
5468 	 * In order to match the requested number of samples per interrupt
5469 	 * from SADA drivers when computing the fragment size,
5470 	 * we need to first truncate the floating point result from
5471 	 *	sample rate * channels / intr rate
5472 	 * then adjust up to an even number, before multiplying it
5473 	 * with the sample size
5474 	 */
5475 	engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
5476 	if (engp->fragsz & 1)
5477 		engp->fragsz++;
5478 	engp->fragsz *= engp->sampsz;
5479 	engp->fragfr = engp->fragsz / engp->framesz;
5480 
5481 	engp->nfrags = 10;
5482 	engp->bufsz = engp->fragsz * engp->nfrags;
5483 
5484 	engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
5485 	engp->bufpos = engp->bufp;
5486 	engp->bufendp = engp->bufp + engp->bufsz;
5487 	engp->frames = 0;
5488 	engp->io_count = 0;
5489 	engp->bufio_count = 0;
5490 	engp->started = B_FALSE;
5491 	engp->busy = B_FALSE;
5492 
5493 	*nframesp = engp->nfrags * engp->fragfr;
5494 	*bufp = engp->bufp;
5495 
5496 	mutex_exit(&engp->lock);
5497 
5498 	if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
5499 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5500 		    "device setup failed");
5501 		goto OUT;
5502 	}
5503 
5504 
5505 
5506 	mutex_enter(&statep->usb_ac_mutex);
5507 	statep->flags |= AD_SETUP;
5508 	mutex_exit(&statep->usb_ac_mutex);
5509 
5510 	rv = 0;
5511 
5512 
5513 OUT:
5514 	if (rv != 0)
5515 		usb_engine_close(arg);
5516 
5517 	return (rv);
5518 }
5519 
5520 
5521 static void
5522 usb_engine_close(void *arg)
5523 {
5524 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5525 	usb_ac_state_t *statep = engp->statep;
5526 
5527 	mutex_enter(&engp->lock);
5528 	while (engp->busy) {
5529 		cv_wait(&engp->usb_audio_cv, &engp->lock);
5530 	}
5531 
5532 	mutex_exit(&engp->lock);
5533 
5534 	if (statep->flags & AD_SETUP) {
5535 		usb_ac_teardown(statep, engp);
5536 		mutex_enter(&statep->usb_ac_mutex);
5537 		statep->flags &= ~AD_SETUP;
5538 		mutex_exit(&statep->usb_ac_mutex);
5539 	}
5540 	mutex_enter(&engp->lock);
5541 
5542 	if (engp->bufp != NULL) {
5543 		kmem_free(engp->bufp, engp->bufsz);
5544 		engp->bufp = NULL;
5545 		engp->bufpos = NULL;
5546 		engp->bufendp = NULL;
5547 	}
5548 
5549 	mutex_exit(&engp->lock);
5550 
5551 	usb_ac_close(statep->usb_ac_dip);
5552 }
5553 
5554 
5555 
5556 static int
5557 usb_engine_start(void *arg)
5558 {
5559 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5560 	int rv = 0;
5561 	int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
5562 
5563 	mutex_enter(&engp->lock);
5564 	engp->started = B_TRUE;
5565 	mutex_exit(&engp->lock);
5566 
5567 	usb_ac_state_t *statep = engp->statep;
5568 
5569 	start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5570 	    usb_ac_start_play : usb_ac_start_record;
5571 
5572 	if ((*start)(statep, engp) != USB_SUCCESS) {
5573 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5574 		    "failed to start %d engine", engp->af_eflags);
5575 		rv = EIO;
5576 	}
5577 
5578 
5579 	return (rv);
5580 }
5581 
5582 
5583 static void
5584 usb_engine_stop(void *arg)
5585 {
5586 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5587 
5588 	mutex_enter(&engp->lock);
5589 	engp->started = B_FALSE;
5590 	mutex_exit(&engp->lock);
5591 
5592 	usb_ac_state_t *statep = engp->statep;
5593 	void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
5594 
5595 	stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5596 	    usb_ac_stop_play : usb_ac_stop_record;
5597 
5598 	(*stop)(statep, engp);
5599 }
5600 
5601 
5602 static uint64_t
5603 usb_engine_count(void *arg)
5604 {
5605 	usb_audio_eng_t	*engp = arg;
5606 	uint64_t	val;
5607 
5608 	mutex_enter(&engp->lock);
5609 	val = engp->frames;
5610 	mutex_exit(&engp->lock);
5611 
5612 	return (val);
5613 }
5614 
5615 
5616 static int
5617 usb_engine_format(void *arg)
5618 {
5619 	usb_audio_eng_t *engp = arg;
5620 
5621 	switch (engp->fmt.enc) {
5622 		case USB_AUDIO_FORMAT_TYPE1_MULAW:
5623 			return (AUDIO_FORMAT_ULAW);
5624 		case USB_AUDIO_FORMAT_TYPE1_ALAW:
5625 			return (AUDIO_FORMAT_ALAW);
5626 		case USB_AUDIO_FORMAT_TYPE1_PCM8:
5627 			return (AUDIO_FORMAT_U8);
5628 
5629 		case USB_AUDIO_FORMAT_TYPE1_PCM:
5630 			break;
5631 		default:
5632 			return (AUDIO_FORMAT_NONE);
5633 	}
5634 
5635 	switch (engp->fmt.prec) {
5636 		case USB_AUDIO_PRECISION_8:
5637 			return (AUDIO_FORMAT_S8);
5638 		case USB_AUDIO_PRECISION_16:
5639 			return (AUDIO_FORMAT_S16_LE);
5640 		case USB_AUDIO_PRECISION_24:
5641 			return (AUDIO_FORMAT_S24_LE);
5642 		case USB_AUDIO_PRECISION_32:
5643 			return (AUDIO_FORMAT_S32_LE);
5644 		default:
5645 			break;
5646 	}
5647 	return (AUDIO_FORMAT_NONE);
5648 
5649 
5650 }
5651 
5652 static int
5653 usb_engine_channels(void *arg)
5654 {
5655 	usb_audio_eng_t *engp = arg;
5656 
5657 	return (engp->fmt.ch);
5658 }
5659 
5660 
5661 static int
5662 usb_engine_rate(void *arg)
5663 {
5664 	usb_audio_eng_t *engp = arg;
5665 
5666 	return (engp->fmt.sr);
5667 }
5668 
5669 
5670 /*ARGSUSED*/
5671 static void
5672 usb_engine_sync(void *arg, unsigned nframes)
5673 {
5674 	/* Do nothing */
5675 }
5676 
5677 
5678 static unsigned
5679 usb_engine_qlen(void *arg)
5680 {
5681 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5682 
5683 	return (engp->fragfr);
5684 }
5685 
5686 /*
5687  * **************************************************************************
5688  * interfaces used by USB audio
5689  */
5690 
5691 /*ARGSUSED*/
5692 static int
5693 usb_change_phy_vol(usb_ac_state_t *statep, int value)
5694 {
5695 	usb_audio_ctrl_t *ctrlp;
5696 	uint64_t cval = 0;
5697 	int64_t left, right, delta = 0;
5698 
5699 	ctrlp = statep->controls[CTL_VOLUME_STERO];
5700 
5701 	ASSERT(value != 0);
5702 
5703 	delta = (value < 0)?-1:1;
5704 
5705 	left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
5706 	right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
5707 
5708 	if (left > AF_MAX_GAIN)
5709 		left = AF_MAX_GAIN;
5710 	if (right > AF_MAX_GAIN)
5711 		right = AF_MAX_GAIN;
5712 
5713 	if (left < AF_MIN_GAIN)
5714 		left = AF_MIN_GAIN;
5715 	if (right < AF_MIN_GAIN)
5716 		right = AF_MIN_GAIN;
5717 
5718 	cval = AUDIO_CTRL_STEREO_VAL(left, right);
5719 
5720 	if (audio_control_write(ctrlp->af_ctrlp, cval)) {
5721 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5722 		    "updateing control  to value 0x%llx by driver failed",
5723 		    (long long unsigned)cval);
5724 		return (USB_FAILURE);
5725 	}
5726 	return (USB_SUCCESS);
5727 }
5728