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_sr		= (uint_t)engine->fmt.sr;
3006 	format.fmt_chns	= (uchar_t)engine->fmt.ch;
3007 	format.fmt_precision	= (uchar_t)engine->fmt.prec;
3008 	format.fmt_encoding	= (uchar_t)engine->fmt.enc;
3009 
3010 	old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3011 
3012 	/* isoc pipe not open and playing is not in progress */
3013 	if (old_setup_teardown_count) {
3014 		streams_infop->acs_setup_teardown_count = 1;
3015 
3016 		mutex_exit(&uacp->usb_ac_mutex);
3017 		usb_ac_release_access(uacp);
3018 
3019 		usb_ac_stop_play(uacp, engine);
3020 		usb_ac_teardown(uacp, engine);
3021 
3022 		usb_ac_serialize_access(uacp);
3023 		mutex_enter(&uacp->usb_ac_mutex);
3024 	}
3025 
3026 	/*
3027 	 * Set format for the streaming interface with lower write queue
3028 	 * This boils down to set_alternate  interface command in
3029 	 * usb_as and the reply mp contains the currently active
3030 	 * alternate number that is stored in the as_req structure
3031 	 */
3032 	if (usb_ac_send_as_cmd(uacp, engine,
3033 	    USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
3034 		USB_DPRINTF_L2(PRINT_MASK_ALL,
3035 		    uacp->usb_ac_log_handle,
3036 		    "usb_ac_set_format: failed");
3037 		goto fail;
3038 
3039 	}
3040 	int sample =  engine->fmt.sr;
3041 
3042 	/* Set the sample rate */
3043 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
3044 	    &sample) != USB_SUCCESS) {
3045 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3046 		    "usb_ac_set_format: setting format failed");
3047 		goto fail;
3048 
3049 	}
3050 
3051 	mutex_exit(&uacp->usb_ac_mutex);
3052 
3053 	usb_ac_release_access(uacp);
3054 
3055 	/* This should block until successful */
3056 	if (old_setup_teardown_count) {
3057 		(void) usb_ac_setup(uacp, engine);
3058 	}
3059 
3060 	mutex_enter(&uacp->usb_ac_mutex);
3061 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3062 	mutex_exit(&uacp->usb_ac_mutex);
3063 
3064 	return (USB_SUCCESS);
3065 fail:
3066 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3067 	mutex_exit(&uacp->usb_ac_mutex);
3068 	usb_ac_release_access(uacp);
3069 
3070 	return (USB_FAILURE);
3071 
3072 }
3073 
3074 /*
3075  * usb_ac_start_play
3076  *	Send a start_play command down to usb_as
3077  *	Check power is done in usb_ac_send_as_cmd()
3078  */
3079 static int
3080 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3081 {
3082 	int			samples;
3083 	usb_audio_play_req_t	play_req;
3084 
3085 
3086 	mutex_enter(&uacp->usb_ac_mutex);
3087 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3088 		mutex_exit(&uacp->usb_ac_mutex);
3089 
3090 		return (USB_FAILURE);
3091 	}
3092 	mutex_exit(&uacp->usb_ac_mutex);
3093 
3094 	usb_ac_serialize_access(uacp);
3095 
3096 	mutex_enter(&uacp->usb_ac_mutex);
3097 
3098 
3099 
3100 	/* Check for continuous sample rate done in usb_as */
3101 	samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
3102 	if (samples & engine->fmt.ch) {
3103 		samples++;
3104 	}
3105 
3106 	play_req.up_samples = samples;
3107 	play_req.up_handle = uacp;
3108 
3109 	/* Send setup command to usb_as */
3110 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
3111 	    (void *)&play_req) != USB_SUCCESS) {
3112 
3113 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3114 		    "usb_ac_start_play: failure");
3115 
3116 		mutex_exit(&uacp->usb_ac_mutex);
3117 
3118 		usb_ac_release_access(uacp);
3119 
3120 		return (USB_FAILURE);
3121 	}
3122 
3123 	mutex_exit(&uacp->usb_ac_mutex);
3124 
3125 	usb_ac_release_access(uacp);
3126 
3127 	return (USB_SUCCESS);
3128 }
3129 
3130 
3131 /*
3132  * usb_ac_stop_play:
3133  *	Stop the play engine
3134  *	called from mixer framework.
3135  */
3136 void
3137 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3138 {
3139 
3140 	if (engine == NULL) {
3141 		engine = &(uacp->engines[0]);
3142 	}
3143 	mutex_enter(&uacp->usb_ac_mutex);
3144 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3145 		mutex_exit(&uacp->usb_ac_mutex);
3146 
3147 		return;
3148 	}
3149 	mutex_exit(&uacp->usb_ac_mutex);
3150 
3151 	usb_ac_serialize_access(uacp);
3152 	mutex_enter(&uacp->usb_ac_mutex);
3153 
3154 	/* Send setup command to usb_as */
3155 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
3156 	    (void *)NULL) != USB_SUCCESS) {
3157 
3158 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3159 		    "usb_ac_do_pause_play: failure");
3160 	}
3161 
3162 	mutex_exit(&uacp->usb_ac_mutex);
3163 	usb_ac_release_access(uacp);
3164 }
3165 
3166 
3167 /*
3168  * usb_ac_start_record:
3169  *	Sends a start record command down to usb_as.
3170  *	Check power is done in usb_ac_send_as_cmd()
3171  */
3172 static int
3173 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3174 {
3175 
3176 
3177 	mutex_enter(&uacp->usb_ac_mutex);
3178 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3179 		mutex_exit(&uacp->usb_ac_mutex);
3180 
3181 		return (USB_FAILURE);
3182 	}
3183 	mutex_exit(&uacp->usb_ac_mutex);
3184 
3185 	usb_ac_serialize_access(uacp);
3186 	mutex_enter(&uacp->usb_ac_mutex);
3187 
3188 
3189 	/* Send setup command to usb_as */
3190 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
3191 	    (void *)uacp) != USB_SUCCESS) {
3192 
3193 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3194 		    "usb_ac_start_record: failure");
3195 
3196 		mutex_exit(&uacp->usb_ac_mutex);
3197 
3198 		usb_ac_release_access(uacp);
3199 
3200 		return (USB_FAILURE);
3201 	}
3202 
3203 	mutex_exit(&uacp->usb_ac_mutex);
3204 	usb_ac_release_access(uacp);
3205 
3206 	return (USB_SUCCESS);
3207 }
3208 
3209 
3210 /*
3211  * usb_ac_stop_record:
3212  *	Wrapper function for usb_ac_do_stop_record and is
3213  *	called form mixer framework.
3214  */
3215 static void
3216 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3217 {
3218 
3219 	usb_ac_serialize_access(uacp);
3220 	mutex_enter(&uacp->usb_ac_mutex);
3221 
3222 	/* Send setup command to usb_as */
3223 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
3224 	    NULL) != USB_SUCCESS) {
3225 
3226 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3227 		    "usb_ac_do_stop_record: failure");
3228 	}
3229 
3230 	mutex_exit(&uacp->usb_ac_mutex);
3231 	usb_ac_release_access(uacp);
3232 }
3233 
3234 
3235 /*
3236  * Helper Functions for Mixer callbacks
3237  *
3238  * usb_ac_get_maxmin_volume:
3239  *	Send USBA command down to get the maximum or minimum gain balance
3240  *	Calculate min or max gain balance and return that. Return
3241  *	USB_FAILURE for failure cases
3242  */
3243 /* ARGSUSED */
3244 static int
3245 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
3246     int dir, int feature_unitID, short *max_or_minp)
3247 {
3248 	mblk_t		*data = NULL;
3249 	usb_cr_t	cr;
3250 	usb_cb_flags_t	cb_flags;
3251 
3252 
3253 	mutex_exit(&uacp->usb_ac_mutex);
3254 
3255 	if (usb_pipe_sync_ctrl_xfer(
3256 	    uacp->usb_ac_dip,
3257 	    uacp->usb_ac_default_ph,
3258 	    USB_DEV_REQ_DEV_TO_HOST |
3259 	    USB_DEV_REQ_TYPE_CLASS |
3260 	    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
3261 	    cmd,			/* bRequest */
3262 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3263 					/* feature unit and id */
3264 	    (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
3265 	    2,				/* wLength */
3266 	    &data,
3267 	    USB_ATTRS_NONE,
3268 	    &cr, &cb_flags,
3269 	    USB_FLAGS_SLEEP) != USB_SUCCESS) {
3270 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3271 		    "usb_ac_get_maxmin_volume: failed, "
3272 		    "cr=%d, cb=0x%x cmd=%d, data=0x%p",
3273 		    cr, cb_flags, cmd, (void *)data);
3274 
3275 		freemsg(data);
3276 		mutex_enter(&uacp->usb_ac_mutex);
3277 
3278 		return (USB_FAILURE);
3279 	}
3280 
3281 	mutex_enter(&uacp->usb_ac_mutex);
3282 	ASSERT(MBLKL(data) == 2);
3283 
3284 	*max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr;
3285 
3286 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3287 	    "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp);
3288 
3289 	freemsg(data);
3290 
3291 	return (USB_SUCCESS);
3292 }
3293 
3294 
3295 /*
3296  * usb_ac_set_volume:
3297  *	Send USBA command down to set the gain balance
3298  */
3299 /* ARGSUSED */
3300 static int
3301 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
3302     int feature_unitID)
3303 {
3304 	mblk_t		*data = NULL;
3305 	usb_cr_t	cr;
3306 	usb_cb_flags_t	cb_flags;
3307 	int		rval = USB_FAILURE;
3308 
3309 
3310 	mutex_exit(&uacp->usb_ac_mutex);
3311 
3312 	/* Construct the mblk_t from gain for sending to USBA */
3313 	data = allocb(4, BPRI_HI);
3314 	if (!data) {
3315 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3316 		    "usb_ac_set_volume: allocate data failed");
3317 		mutex_enter(&uacp->usb_ac_mutex);
3318 
3319 		return (USB_FAILURE);
3320 	}
3321 
3322 
3323 
3324 	*(data->b_wptr++) = (char)gain;
3325 	*(data->b_wptr++) = (char)(gain >> 8);
3326 
3327 	if ((rval = usb_pipe_sync_ctrl_xfer(
3328 	    uacp->usb_ac_dip,
3329 	    uacp->usb_ac_default_ph,
3330 	    USB_DEV_REQ_HOST_TO_DEV |
3331 	    USB_DEV_REQ_TYPE_CLASS |
3332 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3333 	    USB_AUDIO_SET_CUR,			/* bRequest */
3334 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3335 						/* feature unit and id */
3336 	    (feature_unitID << 8) | uacp->usb_ac_ifno,	/* wIndex */
3337 	    2,					/* wLength */
3338 	    &data, 0,
3339 	    &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
3340 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3341 		    "usb_ac_set_volume: failed, cr=%d cb=0x%x",
3342 		    cr, cb_flags);
3343 	}
3344 
3345 	freemsg(data);
3346 	mutex_enter(&uacp->usb_ac_mutex);
3347 
3348 	return (rval);
3349 }
3350 
3351 
3352 /*
3353  * usb_ac_set_mute is called for each unit that supports the
3354  * requested control from usb_ac_traverse_connections
3355  */
3356 int
3357 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
3358     uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
3359 {
3360 	mblk_t		*data;
3361 	usb_cr_t	cr;
3362 	usb_cb_flags_t	cb_flags;
3363 	int		rval = USB_FAILURE;
3364 
3365 
3366 	if (usb_ac_feature_unit_check(uacp, featureID,
3367 	    dir, channel, control, 0, depth) != USB_SUCCESS) {
3368 
3369 		return (USB_FAILURE);
3370 	}
3371 	mutex_exit(&uacp->usb_ac_mutex);
3372 
3373 	/* Construct the mblk_t for sending to USBA */
3374 	data = allocb(1, BPRI_HI);
3375 
3376 	if (!data) {
3377 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3378 		    "usb_ac_set_mute: allocate data failed");
3379 		mutex_enter(&uacp->usb_ac_mutex);
3380 
3381 		return (USB_FAILURE);
3382 	}
3383 
3384 
3385 	*(data->b_wptr++) = (char)muteval;
3386 
3387 	if ((rval = usb_pipe_sync_ctrl_xfer(
3388 	    uacp->usb_ac_dip,
3389 	    uacp->usb_ac_default_ph,
3390 	    USB_DEV_REQ_HOST_TO_DEV |
3391 	    USB_DEV_REQ_TYPE_CLASS |
3392 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3393 	    USB_AUDIO_SET_CUR,			/* bRequest */
3394 	    (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
3395 						/* feature unit and id */
3396 	    (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
3397 	    1,					/* wLength */
3398 	    &data,
3399 	    0,					/* attributes */
3400 	    &cr, &cb_flags, 0)) != USB_SUCCESS) {
3401 
3402 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3403 		    "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
3404 	}
3405 	freemsg(data);
3406 
3407 	mutex_enter(&uacp->usb_ac_mutex);
3408 
3409 	return (rval);
3410 }
3411 
3412 
3413 /*
3414  * usb_ac_send_as_cmd:
3415  *	Allocate message blk, send a command down to usb_as,
3416  *	wait for the reply and free the message
3417  *
3418  *	although not really needed to raise power if sending to as
3419  *	it seems better to ensure that both interfaces are at full power
3420  */
3421 static int
3422 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
3423     int cmd, void *arg)
3424 {
3425 	usb_ac_streams_info_t *streams_infop;
3426 	usb_ac_plumbed_t *plumb_infop;
3427 	int		rv;
3428 	int		rval;
3429 	ldi_handle_t	lh;
3430 
3431 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3432 	streams_infop = engine->streams;
3433 	plumb_infop = streams_infop->acs_plumbed;
3434 
3435 
3436 	lh = plumb_infop->acp_lh;
3437 
3438 	rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval);
3439 	if (rv != 0) {
3440 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3441 		    "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv);
3442 
3443 		return (USB_FAILURE);
3444 	}
3445 
3446 	return (USB_SUCCESS);
3447 }
3448 
3449 
3450 /*
3451  * usb_ac_serialize/release_access:
3452  */
3453 static void
3454 usb_ac_serialize_access(usb_ac_state_t	*uacp)
3455 {
3456 	(void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3457 }
3458 
3459 static void
3460 usb_ac_release_access(usb_ac_state_t *uacp)
3461 {
3462 	usb_release_access(uacp->usb_ac_ser_acc);
3463 }
3464 
3465 
3466 static void
3467 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
3468 {
3469 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3470 
3471 	if (usb_ac_statep->usb_ac_pm != NULL) {
3472 		mutex_enter(&usb_ac_statep->usb_ac_mutex);
3473 		usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
3474 
3475 		USB_DPRINTF_L4(PRINT_MASK_PM,
3476 		    usb_ac_statep->usb_ac_log_handle,
3477 		    "usb_ac_pm_busy_component: %d",
3478 		    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3479 
3480 		mutex_exit(&usb_ac_statep->usb_ac_mutex);
3481 
3482 		if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
3483 		    DDI_SUCCESS) {
3484 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3485 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3486 
3487 			USB_DPRINTF_L2(PRINT_MASK_PM,
3488 			    usb_ac_statep->usb_ac_log_handle,
3489 			    "usb_ac_pm_busy_component failed: %d",
3490 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3491 
3492 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
3493 		}
3494 	}
3495 }
3496 
3497 
3498 static void
3499 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
3500 {
3501 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3502 
3503 	if (usb_ac_statep->usb_ac_pm != NULL) {
3504 		if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
3505 		    DDI_SUCCESS) {
3506 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3507 			ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
3508 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3509 
3510 			USB_DPRINTF_L4(PRINT_MASK_PM,
3511 			    usb_ac_statep->usb_ac_log_handle,
3512 			    "usb_ac_pm_idle_component: %d",
3513 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3514 
3515 			mutex_exit(&usb_ac_statep->usb_ac_mutex);
3516 		}
3517 	}
3518 }
3519 
3520 
3521 /*
3522  * handle read from plumbed drivers
3523  */
3524 static void
3525 usb_ac_reader(void *argp)
3526 {
3527 	usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp;
3528 	usb_ac_state_t *uacp = acp->acp_uacp;
3529 	ldi_handle_t lh;
3530 	mblk_t *mp;
3531 	int rv;
3532 	timestruc_t tv = {0};
3533 
3534 	mutex_enter(&uacp->usb_ac_mutex);
3535 	lh = acp->acp_lh;
3536 	tv.tv_sec = usb_ac_wait_hid;
3537 
3538 	while (acp->acp_flags & ACP_ENABLED) {
3539 		mp = NULL;
3540 
3541 		mutex_exit(&uacp->usb_ac_mutex);
3542 
3543 		rv = ldi_getmsg(lh, &mp, &tv);
3544 
3545 		mutex_enter(&uacp->usb_ac_mutex);
3546 
3547 		if (rv == ENODEV) {
3548 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3549 			    "Device is not availabe");
3550 			break;
3551 		}
3552 
3553 
3554 		if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0)
3555 			rv = usb_ac_read_msg(acp, mp);
3556 
3557 	}
3558 	mutex_exit(&uacp->usb_ac_mutex);
3559 }
3560 
3561 
3562 /*
3563  * setup threads to read from the other usb modules that may send unsolicited
3564  * or asynchronous messages, which is only hid currently
3565  */
3566 static int
3567 usb_ac_plumb(usb_ac_plumbed_t *acp)
3568 {
3569 	usb_ac_state_t	*uacp = acp->acp_uacp;
3570 	dev_info_t	*dip;
3571 	dev_info_t	*acp_dip;
3572 	int		acp_inst;
3573 	char		*acp_name;
3574 	char		tq_nm[128];
3575 	int		rv = USB_FAILURE;
3576 
3577 	mutex_enter(&uacp->usb_ac_mutex);
3578 
3579 	dip = uacp->usb_ac_dip;
3580 
3581 	acp_dip = acp->acp_dip;
3582 	acp_inst = ddi_get_instance(acp_dip);
3583 	acp_name = (char *)ddi_driver_name(acp_dip);
3584 
3585 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3586 	    "usb_ac_plumb:begin");
3587 
3588 	if (strcmp(acp_name, "hid") != 0) {
3589 		rv = USB_SUCCESS;
3590 		goto OUT;
3591 	}
3592 
3593 	(void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3594 	    ddi_driver_name(acp_dip), acp_inst);
3595 
3596 	acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3597 	if (acp->acp_tqp == NULL)
3598 		goto OUT;
3599 
3600 	if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp,
3601 	    DDI_SLEEP) != DDI_SUCCESS)
3602 		goto OUT;
3603 
3604 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3605 	    "usb_ac_plumb: dispatched reader");
3606 
3607 	rv = USB_SUCCESS;
3608 
3609 OUT:
3610 	mutex_exit(&uacp->usb_ac_mutex);
3611 
3612 	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3613 	    "usb_ac_plumb: done, rv=%d", rv);
3614 
3615 	return (rv);
3616 }
3617 
3618 
3619 static void
3620 usb_ac_mux_plumbing_tq(void *arg)
3621 {
3622 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3623 
3624 	if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS)
3625 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3626 		    "usb_ac_mux_plumbing_tq:failed");
3627 }
3628 
3629 
3630 static int
3631 usb_ac_do_plumbing(usb_ac_state_t *uacp)
3632 {
3633 	dev_info_t *dip = uacp->usb_ac_dip;
3634 	int inst = ddi_get_instance(dip);
3635 	char tq_nm[128];
3636 	int rv = USB_FAILURE;
3637 
3638 	(void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3639 	    ddi_driver_name(dip), inst);
3640 
3641 	uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3642 	if (uacp->tqp == NULL) {
3643 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3644 		    "usb_ac_do_plumbing: ddi_taskq_create failed");
3645 		goto OUT;
3646 	}
3647 
3648 	if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp,
3649 	    DDI_SLEEP) != DDI_SUCCESS) {
3650 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3651 		    "usb_ac_do_plumbing: ddi_taskq_dispatch failed");
3652 		goto OUT;
3653 	}
3654 
3655 	rv = USB_SUCCESS;
3656 
3657 OUT:
3658 	return (rv);
3659 }
3660 
3661 
3662 
3663 static void
3664 usb_ac_mux_unplumbing_tq(void *arg)
3665 {
3666 	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3667 
3668 	if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS)
3669 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3670 		    "usb_ac_mux_unplumbing:failed");
3671 }
3672 
3673 
3674 static int
3675 usb_ac_do_unplumbing(usb_ac_state_t *uacp)
3676 {
3677 	int rv = USB_FAILURE;
3678 
3679 	if (uacp->tqp == NULL)
3680 		return (USB_SUCCESS);
3681 
3682 	if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq,
3683 	    (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) {
3684 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3685 		    "usb_ac_do_unplumbing: ddi_taskq_dispatch failed");
3686 		goto OUT;
3687 	}
3688 
3689 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3690 	    "usb_ac_do_unplumbing: waiting for unplumb thread");
3691 
3692 	ddi_taskq_wait(uacp->tqp);
3693 	rv = USB_SUCCESS;
3694 
3695 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3696 	    "usb_ac_do_unplumbing: unplumb thread done");
3697 
3698 OUT:
3699 	if (uacp->tqp != NULL) {
3700 		ddi_taskq_destroy(uacp->tqp);
3701 		uacp->tqp = NULL;
3702 	}
3703 	return (rv);
3704 }
3705 
3706 
3707 /*
3708  * teardown threads to the other usb modules
3709  * and clear structures as part of unplumbing
3710  */
3711 static void
3712 usb_ac_unplumb(usb_ac_plumbed_t *acp)
3713 {
3714 	usb_ac_streams_info_t *streams_infop;
3715 	usb_ac_state_t	*uacp = acp->acp_uacp;
3716 
3717 
3718 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3719 	    "usb_ac_unplumb: begin");
3720 
3721 	if (acp->acp_tqp != NULL) {
3722 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3723 		    "usb_ac_unplumb: destroying taskq");
3724 
3725 		ddi_taskq_destroy(acp->acp_tqp);
3726 	}
3727 
3728 	mutex_enter(&uacp->usb_ac_mutex);
3729 
3730 	if (acp->acp_driver == USB_AS_PLUMBED) {
3731 		/*
3732 		 * we bzero the streams info and plumbed structure
3733 		 * since there is no guarantee that the next plumbing
3734 		 * will be identical
3735 		 */
3736 		streams_infop = (usb_ac_streams_info_t *)acp->acp_data;
3737 
3738 		/* bzero the relevant plumbing structure */
3739 		bzero(streams_infop, sizeof (usb_ac_streams_info_t));
3740 	}
3741 	bzero(acp, sizeof (usb_ac_plumbed_t));
3742 
3743 	mutex_exit(&uacp->usb_ac_mutex);
3744 
3745 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3746 	    "usb_ac_unplumb: done");
3747 }
3748 
3749 
3750 /*ARGSUSED*/
3751 static int
3752 usb_ac_mux_plumbing(usb_ac_state_t *uacp)
3753 {
3754 	dev_info_t		*dip;
3755 
3756 	/* get the usb_ac dip */
3757 	dip = uacp->usb_ac_dip;
3758 
3759 	/* Access to the global variables is synchronized */
3760 	mutex_enter(&uacp->usb_ac_mutex);
3761 
3762 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3763 	    "usb_ac_mux_plumbing:state = %d",
3764 	    uacp->usb_ac_plumbing_state);
3765 
3766 	if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) {
3767 		mutex_exit(&uacp->usb_ac_mutex);
3768 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3769 		    "usb_ac_mux_plumbing: audio streams driver"
3770 		    " already plumbed");
3771 
3772 		return (USB_SUCCESS);
3773 	}
3774 
3775 	/* usb_as and hid should be attached but double check */
3776 	if (usb_ac_online_siblings(uacp) != USB_SUCCESS) {
3777 		mutex_exit(&uacp->usb_ac_mutex);
3778 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3779 		"usb_ac_mux_plumbing:no audio streams driver plumbed");
3780 
3781 		return (USB_FAILURE);
3782 	}
3783 
3784 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3785 	    "usb_ac_mux_plumbing: raising power");
3786 	mutex_exit(&uacp->usb_ac_mutex);
3787 
3788 	/* bring the device to full power */
3789 	usb_ac_pm_busy_component(uacp);
3790 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3791 
3792 	/* avoid dips disappearing while we are plumbing */
3793 	usb_ac_hold_siblings(uacp);
3794 
3795 	mutex_enter(&uacp->usb_ac_mutex);
3796 
3797 	/*
3798 	 * walk all siblings and create the usb_ac<->usb_as and
3799 	 * usb_ac<->hid streams. return of 0 indicates no or
3800 	 * partial/failed plumbing
3801 	 */
3802 	if (usb_ac_mux_walk_siblings(uacp) == 0) {
3803 		/* pretend that we are plumbed so we can unplumb */
3804 		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3805 
3806 		mutex_exit(&uacp->usb_ac_mutex);
3807 
3808 		(void) usb_ac_mux_unplumbing(uacp);
3809 
3810 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3811 		    "usb_ac_mux_plumbing: no audio streams driver plumbed");
3812 
3813 		usb_ac_rele_siblings(uacp);
3814 
3815 		usb_ac_pm_idle_component(uacp);
3816 
3817 		return (USB_FAILURE);
3818 	}
3819 	uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3820 
3821 	/* restore state if we have already registered with the mixer */
3822 	if (uacp->usb_ac_registered_with_mixer) {
3823 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3824 		    "usb_ac_mux_plumbing:already registered with mixer,"
3825 		    "restoring state");
3826 
3827 		(void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP);
3828 
3829 	} else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) {
3830 		mutex_exit(&uacp->usb_ac_mutex);
3831 
3832 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3833 		    "usb_ac_mux_plumbing: mixer registration failed");
3834 
3835 		(void) usb_ac_mux_unplumbing(uacp);
3836 
3837 		usb_ac_rele_siblings(uacp);
3838 
3839 		usb_ac_pm_idle_component(uacp);
3840 
3841 		return (USB_FAILURE);
3842 	}
3843 
3844 	mutex_exit(&uacp->usb_ac_mutex);
3845 	usb_ac_rele_siblings(uacp);
3846 
3847 	usb_ac_pm_idle_component(uacp);
3848 
3849 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3850 	    "usb_ac_mux_plumbing:done");
3851 
3852 	return (USB_SUCCESS);
3853 }
3854 
3855 
3856 static int
3857 usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
3858 {
3859 	usb_ac_plumbed_t	*acp;
3860 	ldi_handle_t		lh;
3861 	dev_info_t		*acp_dip;
3862 	int			inst;
3863 	int			i;
3864 	dev_t			devt;
3865 	minor_t			minor;
3866 	int			maxlinked = 0;
3867 
3868 	mutex_enter(&uacp->usb_ac_mutex);
3869 
3870 
3871 	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) {
3872 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3873 		    "usb_ac_mux_unplumbing: already unplumbed!");
3874 		mutex_exit(&uacp->usb_ac_mutex);
3875 
3876 		return (USB_SUCCESS);
3877 	}
3878 
3879 	/* usb_ac might not have anything plumbed yet */
3880 	if (uacp->usb_ac_current_plumbed_index == -1) {
3881 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3882 		    "usb_ac_mux_unplumbing: nothing plumbed");
3883 		uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3884 		mutex_exit(&uacp->usb_ac_mutex);
3885 
3886 		return (USB_SUCCESS);
3887 	}
3888 
3889 	/* do not allow detach if still busy */
3890 	if (uacp->usb_ac_busy_count) {
3891 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3892 		    "usb_ac_mux_unplumbing: mux still busy (%d)",
3893 		    uacp->usb_ac_busy_count);
3894 		mutex_exit(&uacp->usb_ac_mutex);
3895 
3896 		return (USB_FAILURE);
3897 	}
3898 
3899 	uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3900 
3901 	/* close ac-as and ac-hid streams */
3902 	maxlinked = uacp->usb_ac_current_plumbed_index + 1;
3903 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3904 	    "usb_ac_mux_unplumbing: maxlinked = %d",  maxlinked);
3905 
3906 	for (i = 0; i < maxlinked; i++) {
3907 		/*
3908 		 * we must save members of usb_ac_plumbed[] before calling
3909 		 * usb_ac_unplumb() because it clears the structure
3910 		 */
3911 		acp = &uacp->usb_ac_plumbed[i];
3912 		lh = acp->acp_lh;
3913 		acp_dip = acp->acp_dip;
3914 		devt = acp->acp_devt;
3915 
3916 		if (acp_dip == NULL) {
3917 			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3918 			    "usb_ac_mux_unplumbing: [%d] - skipping",  i);
3919 			continue;
3920 		}
3921 
3922 		minor = getminor(devt);
3923 		inst = ddi_get_instance(acp_dip);
3924 
3925 		uacp->usb_ac_current_plumbed_index = i;
3926 
3927 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3928 		    "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x",  i,
3929 		    ddi_driver_name(acp_dip), inst, minor);
3930 
3931 		if (lh != NULL) {
3932 
3933 			acp->acp_flags &= ~ACP_ENABLED;
3934 
3935 			mutex_exit(&uacp->usb_ac_mutex);
3936 
3937 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3938 			    "usb_ac_mux_unplumbing:[%d] - closing", i);
3939 
3940 			/*
3941 			 * ldi_close will cause panic if ldi_getmsg
3942 			 * is not finished. ddi_taskq_destroy will wait
3943 			 * for the thread to complete.
3944 			 */
3945 			usb_ac_unplumb(acp);
3946 			(void) ldi_close(lh, FREAD|FWRITE, kcred);
3947 
3948 
3949 			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3950 			    "usb_ac_mux_unplumbing: [%d] - unplumbed", i);
3951 
3952 			mutex_enter(&uacp->usb_ac_mutex);
3953 		}
3954 	}
3955 
3956 	mutex_exit(&uacp->usb_ac_mutex);
3957 
3958 	/* Wait till all activity in the default pipe has drained */
3959 	usb_ac_serialize_access(uacp);
3960 	usb_ac_release_access(uacp);
3961 
3962 	mutex_enter(&uacp->usb_ac_mutex);
3963 	uacp->usb_ac_current_plumbed_index = -1;
3964 	mutex_exit(&uacp->usb_ac_mutex);
3965 
3966 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3967 	    "usb_ac_mux_unplumbing: done");
3968 
3969 	return (USB_SUCCESS);
3970 }
3971 
3972 
3973 /*
3974  * walk all siblings and create the ac<->as and ac<->hid streams
3975  */
3976 static int
3977 usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
3978 {
3979 	dev_info_t	*pdip;
3980 	dev_info_t	*child_dip;
3981 	major_t		drv_major;
3982 	minor_t		drv_minor;
3983 	int		drv_instance;
3984 	char		*drv_name;
3985 	dev_t		drv_devt;
3986 	ldi_handle_t	drv_lh;
3987 	ldi_ident_t	li;
3988 	int		error;
3989 	int		count = 0;
3990 
3991 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3992 
3993 	pdip = ddi_get_parent(uacp->usb_ac_dip);
3994 	child_dip = ddi_get_child(pdip);
3995 
3996 	while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) {
3997 		drv_instance = ddi_get_instance(child_dip);
3998 		drv_name = (char *)ddi_driver_name(child_dip);
3999 
4000 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4001 		    "usb_ac_mux_walk_siblings: plumbing %s%d count=%d",
4002 		    drv_name, drv_instance, count);
4003 
4004 		/* ignore own dip */
4005 		if (child_dip == uacp->usb_ac_dip) {
4006 			child_dip = ddi_get_next_sibling(child_dip);
4007 			continue;
4008 		}
4009 		drv_instance = ddi_get_instance(child_dip);
4010 
4011 		/* ignore other dip other than usb_as and hid */
4012 		if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) {
4013 			uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED;
4014 			drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance);
4015 		} else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) {
4016 			uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED;
4017 			drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance);
4018 		} else {
4019 			drv_minor = drv_instance;
4020 			uacp->usb_ac_plumbed[count].acp_driver =
4021 			    UNKNOWN_PLUMBED;
4022 			child_dip = ddi_get_next_sibling(child_dip);
4023 
4024 			continue;
4025 		}
4026 
4027 		if (!i_ddi_devi_attached(child_dip)) {
4028 			child_dip = ddi_get_next_sibling(child_dip);
4029 
4030 			continue;
4031 		}
4032 
4033 		if (DEVI_IS_DEVICE_REMOVED(child_dip)) {
4034 			child_dip = ddi_get_next_sibling(child_dip);
4035 
4036 			continue;
4037 		}
4038 
4039 		drv_major = ddi_driver_major(child_dip);
4040 
4041 		uacp->usb_ac_current_plumbed_index = count;
4042 
4043 		mutex_exit(&uacp->usb_ac_mutex);
4044 
4045 		drv_devt = makedevice(drv_major, drv_minor);
4046 
4047 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4048 		    "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)",
4049 		    drv_name, drv_instance, drv_major, drv_minor);
4050 
4051 		error = ldi_ident_from_dip(uacp->usb_ac_dip, &li);
4052 		if (error == 0) {
4053 			mutex_enter(&uacp->usb_ac_mutex);
4054 			uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED;
4055 			mutex_exit(&uacp->usb_ac_mutex);
4056 
4057 			error = ldi_open_by_dev(&drv_devt, OTYP_CHR,
4058 			    FREAD|FWRITE, kcred, &drv_lh, li);
4059 			ldi_ident_release(li);
4060 		}
4061 
4062 		mutex_enter(&uacp->usb_ac_mutex);
4063 		if (error) {
4064 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4065 			    "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)"
4066 			    " failed error=%d", drv_major, drv_minor, error);
4067 
4068 			return (0);
4069 		}
4070 
4071 		uacp->usb_ac_plumbed[count].acp_uacp = uacp;
4072 		uacp->usb_ac_plumbed[count].acp_devt = drv_devt;
4073 		uacp->usb_ac_plumbed[count].acp_lh = drv_lh;
4074 		uacp->usb_ac_plumbed[count].acp_dip = child_dip;
4075 		uacp->usb_ac_plumbed[count].acp_ifno =
4076 		    usb_get_if_number(child_dip);
4077 
4078 		if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) {
4079 			/* get registration data */
4080 			if (usb_ac_get_reg_data(uacp, drv_lh, count) !=
4081 			    USB_SUCCESS) {
4082 
4083 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4084 				    uacp->usb_ac_log_handle,
4085 				    "usb_ac_mux_walk_siblings:"
4086 				    "usb_ac_get_reg_data failed on %s%d",
4087 				    drv_name, drv_instance);
4088 
4089 				uacp->usb_ac_plumbed[count].acp_dip = NULL;
4090 
4091 				return (0);
4092 			}
4093 		} else if (uacp->usb_ac_plumbed[count].acp_driver ==
4094 		    USB_AH_PLUMBED) {
4095 			int rval;
4096 
4097 			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4098 			    "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d",
4099 			    drv_name, drv_instance);
4100 
4101 			mutex_exit(&uacp->usb_ac_mutex);
4102 
4103 			/* push usb_ah module on top of hid */
4104 			error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah",
4105 			    FKIOCTL, kcred, &rval);
4106 			mutex_enter(&uacp->usb_ac_mutex);
4107 
4108 			if (error) {
4109 				USB_DPRINTF_L2(PRINT_MASK_ALL,
4110 				    uacp->usb_ac_log_handle,
4111 				    "usb_ac_mux_walk_siblings: ldi_ioctl"
4112 				    "I_PUSH failed on %s%d, error=%d",
4113 				    drv_name, drv_instance, error);
4114 
4115 				uacp->usb_ac_plumbed[count].acp_dip = NULL;
4116 
4117 				/* skip plumbing the hid driver */
4118 				child_dip = ddi_get_next_sibling(child_dip);
4119 				continue;
4120 			}
4121 		} else {
4122 			/* should not be here */
4123 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4124 			    "usb_ac_mux_walk_siblings:- unknown module %s%d",
4125 			    drv_name, drv_instance);
4126 			count--;
4127 
4128 			uacp->usb_ac_plumbed[count].acp_dip = NULL;
4129 
4130 			/* skip plumbing an unknown module */
4131 			child_dip = ddi_get_next_sibling(child_dip);
4132 			continue;
4133 		}
4134 
4135 		mutex_exit(&uacp->usb_ac_mutex);
4136 		error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]);
4137 		mutex_enter(&uacp->usb_ac_mutex);
4138 
4139 		if (error != USB_SUCCESS) {
4140 			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4141 			    "usb_ac_mux_walk_siblings: usb_ac_plumb "
4142 			    "failed for %s%d", drv_name, drv_instance);
4143 
4144 			return (0);
4145 		}
4146 
4147 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4148 		    "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x",
4149 		    drv_instance, drv_minor);
4150 
4151 		child_dip = ddi_get_next_sibling(child_dip);
4152 		count++;
4153 	}
4154 
4155 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4156 	    "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux",
4157 	    count);
4158 
4159 	return (count);
4160 }
4161 
4162 
4163 /*
4164  * Register with mixer only after first plumbing.
4165  * Also do not register if earlier reg data
4166  * couldn't be received from at least one
4167  * streaming interface
4168  */
4169 
4170 static int
4171 usb_ac_mixer_registration(usb_ac_state_t *uacp)
4172 {
4173 	usb_as_registration_t *asreg;
4174 	int		n;
4175 
4176 	if (uacp->usb_ac_registered_with_mixer) {
4177 		return (USB_SUCCESS);
4178 	}
4179 
4180 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4181 		if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4182 			break;
4183 		}
4184 	}
4185 
4186 	/* Haven't found a streaming interface; fail mixer registration */
4187 	if (n > USB_AC_MAX_AS_PLUMBED) {
4188 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4189 		"usb_ac_mixer_registration:- no streaming interface found");
4190 
4191 		return (USB_FAILURE);
4192 	}
4193 
4194 	/*
4195 	 * Fill out streaming interface specific stuff
4196 	 * Note that we handle only one playing and one recording
4197 	 * streaming interface at the most
4198 	 */
4199 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4200 		int ch, chs, id;
4201 
4202 		if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) {
4203 			continue;
4204 		}
4205 
4206 		asreg = &(uacp->usb_ac_streams[n].acs_streams_reg);
4207 		if (asreg->reg_valid == 0) {
4208 			continue;
4209 		}
4210 
4211 
4212 		chs = asreg->reg_formats[0].fmt_chns;
4213 
4214 		/* check if any channel supports vol. control for this fmt */
4215 		for (ch = 0; ch <= chs; ch++) {
4216 			if ((id = usb_ac_get_featureID(uacp,
4217 			    asreg->reg_mode, ch,
4218 			    USB_AUDIO_VOLUME_CONTROL)) != -1) {
4219 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4220 				    uacp->usb_ac_log_handle,
4221 				    "usb_ac_mixer_registration:n= [%d]"
4222 				    "- dir=%d featureID=%d",
4223 				    n, asreg->reg_mode, id);
4224 
4225 				break;
4226 			}
4227 		}
4228 
4229 		uacp->usb_ac_streams[n].acs_default_gain =
4230 		    (id == USB_AC_ID_NONE) ?  (AF_MAX_GAIN): (AF_MAX_GAIN*3/4);
4231 
4232 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4233 		    "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d"
4234 		    "default_gain=%d id=%d",
4235 		    n, asreg->reg_mode, chs,
4236 		    uacp->usb_ac_streams[n].acs_default_gain, id);
4237 
4238 	}
4239 
4240 	/* the rest */
4241 
4242 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4243 	    "usb_ac_mixer_registration: calling usb_audio_register");
4244 
4245 	mutex_exit(&uacp->usb_ac_mutex);
4246 
4247 	if (usb_audio_register(uacp) != USB_SUCCESS) {
4248 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4249 		    "usb_ac_mixer_registration: usb_audio_register failed");
4250 
4251 		mutex_enter(&uacp->usb_ac_mutex);
4252 
4253 		return (USB_FAILURE);
4254 	}
4255 
4256 	mutex_enter(&uacp->usb_ac_mutex);
4257 
4258 	uacp->usb_ac_registered_with_mixer = 1;
4259 
4260 	return (USB_SUCCESS);
4261 }
4262 
4263 
4264 /*
4265  * Get registriations data when driver attach
4266  */
4267 static int
4268 usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
4269 {
4270 	int n, error, rval;
4271 	usb_as_registration_t *streams_reg;
4272 
4273 
4274 	ASSERT(uacp->usb_ac_registered_with_mixer == 0);
4275 
4276 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4277 		/*
4278 		 * We haven't received registration data
4279 		 * from n-th streaming interface in the array
4280 		 */
4281 		if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4282 			break;
4283 		}
4284 	}
4285 
4286 	if (n >= USB_AC_MAX_AS_PLUMBED) {
4287 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4288 		"More than 2 streaming interfaces (play "
4289 		"and/or record) currently not supported");
4290 
4291 		return (USB_FAILURE);
4292 	}
4293 
4294 	/* take the stream reg struct with the same index */
4295 	streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg;
4296 
4297 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4298 	"usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d",
4299 	    (void *)streams_reg, n);
4300 
4301 	mutex_exit(&uacp->usb_ac_mutex);
4302 
4303 	if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION,
4304 	    (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) {
4305 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4306 		    "usb_ac_get_reg_data: ldi_ioctl failed for"
4307 		    "mixer registration error=%d", error);
4308 
4309 		mutex_enter(&uacp->usb_ac_mutex);
4310 
4311 		return (USB_FAILURE);
4312 	} else {
4313 		mutex_enter(&uacp->usb_ac_mutex);
4314 
4315 		rval = usb_ac_setup_plumbed(uacp, index, n);
4316 
4317 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4318 		"usb_ac_get_reg_data:usb_ac_streams[%d]: "
4319 		    "received_reg_data=%d type=%s",  index,
4320 		    uacp->usb_ac_streams[n].acs_rcvd_reg_data,
4321 		    ((streams_reg->reg_mode == USB_AUDIO_PLAY) ?
4322 		    "play" : "record"));
4323 
4324 		usb_ac_print_reg_data(uacp, streams_reg);
4325 
4326 		return (rval);
4327 	}
4328 }
4329 
4330 
4331 /*
4332  * setup plumbed and stream info structure
4333  */
4334 static int
4335 usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx)
4336 {
4337 	uacp->usb_ac_plumbed[plb_idx].acp_data =
4338 	    &uacp->usb_ac_streams[str_idx];
4339 	uacp->usb_ac_streams[str_idx].acs_plumbed =
4340 	    &uacp->usb_ac_plumbed[plb_idx];
4341 	uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1;
4342 
4343 
4344 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4345 	    "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ",
4346 	    plb_idx, str_idx);
4347 
4348 	return (USB_SUCCESS);
4349 }
4350 
4351 
4352 /*
4353  * function to dump registration data
4354  */
4355 static void
4356 usb_ac_print_reg_data(usb_ac_state_t *uacp,
4357     usb_as_registration_t *reg)
4358 {
4359 	int n;
4360 
4361 	for (n = 0; n < reg->reg_n_formats; n++) {
4362 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4363 		    "format%d: alt=%d chns=%d prec=%d enc=%d", n,
4364 		    reg->reg_formats[n].fmt_alt,
4365 		    reg->reg_formats[n].fmt_chns,
4366 		    reg->reg_formats[n].fmt_precision,
4367 		    reg->reg_formats[n].fmt_encoding);
4368 	}
4369 
4370 	for (n = 0; n < USB_AS_N_FORMATS; n++) {
4371 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4372 		    "reg_formats[%d] ptr=0x%p", n,
4373 		    (void *)&reg->reg_formats[n]);
4374 	}
4375 
4376 	for (n = 0; n < USB_AS_N_CHANNELS; n++) {
4377 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4378 		    "reg_channels[%d]=%d", n, reg->reg_channels[n]);
4379 	}
4380 
4381 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4382 	    "usb_ac_print_reg_data: End");
4383 }
4384 
4385 
4386 static int
4387 usb_ac_online_siblings(usb_ac_state_t *uacp)
4388 {
4389 	dev_info_t	*pdip, *child_dip;
4390 	int		rval = USB_SUCCESS;
4391 
4392 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4393 
4394 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4395 	    "usb_ac_online_siblings:start");
4396 
4397 	pdip = ddi_get_parent(uacp->usb_ac_dip);
4398 
4399 	child_dip = ddi_get_child(pdip);
4400 	while (child_dip != NULL) {
4401 
4402 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4403 		    "usb_ac_online_siblings: onlining %s%d ref=%d",
4404 		    ddi_driver_name(child_dip),
4405 		    ddi_get_instance(child_dip),
4406 		    DEVI(child_dip)->devi_ref);
4407 
4408 		/* Online the child_dip of usb_as and hid,  if not already */
4409 		if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) ||
4410 		    (strcmp(ddi_driver_name(child_dip), "hid") == 0)) {
4411 
4412 			mutex_exit(&uacp->usb_ac_mutex);
4413 			if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
4414 			    NDI_SUCCESS) {
4415 				USB_DPRINTF_L3(PRINT_MASK_ALL,
4416 				    uacp->usb_ac_log_handle,
4417 				    "usb_ac_online_siblings:failed to online"
4418 				    "device %s%d", ddi_driver_name(child_dip),
4419 				    ddi_get_instance(child_dip));
4420 
4421 				/* only onlining usb_as is fatal */
4422 				if (strcmp(ddi_driver_name(child_dip),
4423 				    "usb_as") == 0) {
4424 					mutex_enter(&uacp->usb_ac_mutex);
4425 					rval = USB_FAILURE;
4426 					break;
4427 				}
4428 			}
4429 			mutex_enter(&uacp->usb_ac_mutex);
4430 		}
4431 		child_dip = ddi_get_next_sibling(child_dip);
4432 	}
4433 
4434 	return (rval);
4435 }
4436 
4437 
4438 /*
4439  * hold all audio children before or after plumbing
4440  * online usb_as and hid, if not already
4441  */
4442 static void
4443 usb_ac_hold_siblings(usb_ac_state_t *uacp)
4444 {
4445 	int		circ;
4446 	dev_info_t	*pdip, *child_dip;
4447 
4448 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4449 	    "usb_ac_hold_siblings:start");
4450 
4451 	/* hold all siblings and ourselves */
4452 	pdip = ddi_get_parent(uacp->usb_ac_dip);
4453 
4454 	/* hold the children */
4455 	ndi_devi_enter(pdip, &circ);
4456 	child_dip = ddi_get_child(pdip);
4457 	while (child_dip != NULL) {
4458 		ndi_hold_devi(child_dip);
4459 
4460 		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4461 		    "usb_ac_hold_siblings: held %s%d ref=%d",
4462 		    ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4463 		    DEVI(child_dip)->devi_ref);
4464 
4465 		child_dip = ddi_get_next_sibling(child_dip);
4466 	}
4467 	ndi_devi_exit(pdip, circ);
4468 }
4469 
4470 
4471 /*
4472  * release all audio children before or after plumbing
4473  */
4474 static void
4475 usb_ac_rele_siblings(usb_ac_state_t *uacp)
4476 {
4477 	int		circ;
4478 	dev_info_t	*pdip, *child_dip;
4479 
4480 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4481 	    "usb_ac_rele_siblings: start");
4482 
4483 	/* release all siblings and ourselves */
4484 	pdip = ddi_get_parent(uacp->usb_ac_dip);
4485 	ndi_devi_enter(pdip, &circ);
4486 	child_dip = ddi_get_child(pdip);
4487 	while (child_dip != NULL) {
4488 		ndi_rele_devi(child_dip);
4489 
4490 		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4491 		    "usb_ac_rele_siblings: released %s%d ref=%d",
4492 		    ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4493 		    DEVI(child_dip)->devi_ref);
4494 
4495 		child_dip = ddi_get_next_sibling(child_dip);
4496 	}
4497 	ndi_devi_exit(pdip, circ);
4498 }
4499 static void
4500 usb_restore_engine(usb_ac_state_t *statep)
4501 {
4502 	usb_audio_eng_t *engp;
4503 	int i;
4504 
4505 	for (i = 0; i < USB_AC_ENG_MAX; i++) {
4506 
4507 		mutex_enter(&statep->usb_ac_mutex);
4508 		engp = &statep->engines[i];
4509 		mutex_exit(&statep->usb_ac_mutex);
4510 
4511 		if (engp->af_engp == NULL)
4512 			continue;
4513 		if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
4514 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
4515 			    statep->usb_ac_log_handle,
4516 			    "usb_restore_engine:set format fail, i=%d", i);
4517 			return;
4518 		}
4519 		if (engp->started) {
4520 			(void) usb_engine_start(engp);
4521 		}
4522 
4523 	}
4524 
4525 	(void) usb_ac_ctrl_restore(statep);
4526 }
4527 
4528 
4529 /*
4530  * get the maximum format specification the device supports
4531  */
4532 static void
4533 usb_ac_max_fmt(usb_as_registration_t *reg_data,
4534     usb_audio_format_t *fmtp)
4535 {
4536 
4537 	uint_t *srs, *chs;
4538 	uint_t sr, ch, prec, enc, val;
4539 	int i;
4540 
4541 	usb_audio_formats_t *reg_formats = reg_data->reg_formats;
4542 	srs = reg_data->reg_srs;
4543 	chs = reg_data->reg_channels;
4544 
4545 	for (i = 0, sr = 0; srs[i]; i++) {
4546 		val = srs[i];
4547 		if (val > sr)
4548 			sr = val;
4549 	}
4550 
4551 	for (i = 0, ch = 0; chs[i]; i++) {
4552 		val = chs[i];
4553 		if (val > ch)
4554 			ch = val;
4555 	}
4556 
4557 	for (i = 0, prec = 0, enc = 0; i < reg_data->reg_n_formats; i++) {
4558 		val = reg_formats[i].fmt_precision;
4559 		if (val > prec)
4560 			prec = val;
4561 
4562 		val = reg_formats[i].fmt_encoding;
4563 		if (val > enc)
4564 			enc = val;
4565 	}
4566 
4567 	fmtp->sr = sr;
4568 	fmtp->ch =  ch;
4569 	fmtp->prec = prec;
4570 	fmtp->enc =  enc;
4571 }
4572 
4573 
4574 static void
4575 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
4576 {
4577 	if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
4578 		return;
4579 
4580 	audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
4581 	audio_engine_free(engp->af_engp);
4582 
4583 	mutex_enter(&engp->lock);
4584 	engp->af_engp = NULL;
4585 	engp->streams = NULL;
4586 	mutex_exit(&engp->lock);
4587 
4588 	mutex_destroy(&engp->lock);
4589 	cv_destroy(&engp->usb_audio_cv);
4590 }
4591 
4592 
4593 static int
4594 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t  *asinfo)
4595 {
4596 	audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
4597 	usb_audio_eng_t *engp;
4598 	audio_engine_t *af_engp;
4599 	int rv = USB_FAILURE;
4600 	int dir = asinfo->acs_streams_reg.reg_mode;
4601 	uint_t defgain;
4602 
4603 	if (asinfo->acs_rcvd_reg_data == 0) {
4604 
4605 		return (USB_SUCCESS);
4606 	}
4607 	if (dir == USB_AUDIO_PLAY) {
4608 		engp = &(uacp->engines[0]);
4609 	} else {
4610 		engp = &(uacp->engines[1]);
4611 	}
4612 
4613 	cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL);
4614 
4615 	mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
4616 
4617 	mutex_enter(&engp->lock);
4618 
4619 	engp->af_eflags =
4620 	    (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
4621 	engp->statep = uacp;
4622 
4623 	/* Set the format for the engine */
4624 	usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
4625 
4626 	/* init the default gain */
4627 	defgain = asinfo->acs_default_gain;
4628 	if (engp->fmt.ch == 2) {
4629 		engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
4630 	} else {
4631 		engp->af_defgain = defgain;
4632 	}
4633 	engp->streams = asinfo;
4634 
4635 	mutex_exit(&engp->lock);
4636 
4637 	af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
4638 	if (af_engp == NULL) {
4639 
4640 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4641 		    "audio_engine_alloc failed");
4642 		goto OUT;
4643 	}
4644 	ASSERT(engp->af_engp == 0);
4645 
4646 	mutex_enter(&engp->lock);
4647 	engp->af_engp = af_engp;
4648 	mutex_exit(&engp->lock);
4649 
4650 	audio_engine_set_private(af_engp, engp);
4651 	audio_dev_add_engine(af_devp, af_engp);
4652 
4653 	/*
4654 	 * Set the format for this engine
4655 	 */
4656 	if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
4657 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4658 		    "set format failed, dir = %d", dir);
4659 		goto OUT;
4660 	}
4661 	rv = USB_SUCCESS;
4662 
4663 OUT:
4664 	if (rv != USB_SUCCESS)
4665 		usb_ac_rem_eng(uacp, engp);
4666 
4667 	return (rv);
4668 }
4669 
4670 
4671 static int
4672 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
4673 {
4674 	usb_audio_ctrl_t *ctrlp;
4675 	int rv = USB_SUCCESS;
4676 	USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4677 	    "usb_ac_ctrl_set_defaults:begin");
4678 
4679 	for (int i = 0; i < CTL_NUM; i++) {
4680 		ctrlp = statep->controls[i];
4681 		if (!ctrlp) {
4682 			continue;
4683 		}
4684 		if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4685 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
4686 			    statep->usb_ac_log_handle,
4687 			    "usb_ac_ctrl_set_defaults:control write failed");
4688 			rv = USB_FAILURE;
4689 		}
4690 
4691 	}
4692 	USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4693 	    "usb_ac_ctrl_set_defaults:end");
4694 	return (rv);
4695 }
4696 
4697 
4698 static int
4699 usb_ac_ctrl_restore(usb_ac_state_t *statep)
4700 {
4701 	usb_audio_ctrl_t *ctrlp;
4702 	int rv = USB_SUCCESS;
4703 
4704 	for (int i = 0; i < CTL_NUM; i++) {
4705 		ctrlp = statep->controls[i];
4706 		if (ctrlp) {
4707 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
4708 			    statep->usb_ac_log_handle,
4709 			    "usb_ac_ctrl_restore:i = %d", i);
4710 			if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4711 				rv = USB_FAILURE;
4712 			}
4713 		}
4714 	}
4715 	return (rv);
4716 }
4717 
4718 
4719 
4720 
4721 /*
4722  * moves data between driver buffer and framework/shim buffer
4723  */
4724 static void
4725 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
4726 {
4727 	size_t cpsz = sz;
4728 	caddr_t *src, *dst;
4729 
4730 	if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
4731 		src = &engp->bufpos;
4732 		dst = (caddr_t *)&buf;
4733 	} else {
4734 		src = (caddr_t *)&buf;
4735 		dst = &engp->bufpos;
4736 	}
4737 
4738 	/*
4739 	 * Wrap.  If sz is exactly the remainder of the buffer
4740 	 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
4741 	 * the second memcpy() should have no effect, with bufpos updated
4742 	 * to the head of the buffer.
4743 	 */
4744 	if (engp->bufpos + sz >= engp->bufendp) {
4745 		cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
4746 		(void) memcpy(*dst, *src, cpsz);
4747 
4748 
4749 		buf = (caddr_t)buf + cpsz;
4750 		engp->bufpos = engp->bufp;
4751 		cpsz = sz - cpsz;
4752 	}
4753 
4754 	if (cpsz) {
4755 		(void) memcpy(*dst, *src, cpsz);
4756 
4757 
4758 		engp->bufpos += cpsz;
4759 	}
4760 	engp->bufio_count++;
4761 }
4762 
4763 
4764 /*
4765  * control read callback
4766  */
4767 static int
4768 usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
4769 {
4770 	usb_audio_ctrl_t *ctrlp = arg;
4771 
4772 	mutex_enter(&ctrlp->ctrl_mutex);
4773 	*cvalp = ctrlp->cval;
4774 	mutex_exit(&ctrlp->ctrl_mutex);
4775 
4776 	return (0);
4777 }
4778 
4779 
4780 /*
4781  * stereo level control callback
4782  */
4783 static int
4784 usb_audio_write_stero_rec(void *arg, uint64_t cval)
4785 {
4786 	usb_audio_ctrl_t *ctrlp = arg;
4787 	usb_ac_state_t *statep = ctrlp->statep;
4788 	int rv = EIO;
4789 	int left, right;
4790 	uint_t count = 0;
4791 
4792 
4793 	left = AUDIO_CTRL_STEREO_LEFT(cval);
4794 	right = AUDIO_CTRL_STEREO_RIGHT(cval);
4795 
4796 	if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4797 	    right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4798 
4799 		return (EINVAL);
4800 	}
4801 
4802 	mutex_enter(&ctrlp->ctrl_mutex);
4803 	ctrlp->cval = cval;
4804 	mutex_exit(&ctrlp->ctrl_mutex);
4805 
4806 	mutex_enter(&statep->usb_ac_mutex);
4807 	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4808 	    USB_AUDIO_FEATURE_UNIT, 1,
4809 	    USB_AUDIO_VOLUME_CONTROL,
4810 	    USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4811 
4812 	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4813 	    USB_AUDIO_FEATURE_UNIT, 2,
4814 	    USB_AUDIO_VOLUME_CONTROL,
4815 	    USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4816 	rv = 0;
4817 
4818 done:
4819 	mutex_exit(&statep->usb_ac_mutex);
4820 	return (rv);
4821 }
4822 
4823 static int
4824 usb_audio_write_ster_vol(void *arg, uint64_t cval)
4825 {
4826 	usb_audio_ctrl_t *ctrlp = arg;
4827 	usb_ac_state_t *statep = ctrlp->statep;
4828 	int rv = EIO;
4829 	int left, right;
4830 	uint_t count = 0;
4831 
4832 	left = AUDIO_CTRL_STEREO_LEFT(cval);
4833 	right = AUDIO_CTRL_STEREO_RIGHT(cval);
4834 
4835 	if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4836 	    right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4837 		return (EINVAL);
4838 	}
4839 
4840 	mutex_enter(&ctrlp->ctrl_mutex);
4841 	ctrlp->cval = cval;
4842 	mutex_exit(&ctrlp->ctrl_mutex);
4843 
4844 
4845 	mutex_enter(&statep->usb_ac_mutex);
4846 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4847 	    USB_AUDIO_FEATURE_UNIT, 1,
4848 	    USB_AUDIO_VOLUME_CONTROL,
4849 	    USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4850 
4851 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4852 	    USB_AUDIO_FEATURE_UNIT, 2,
4853 	    USB_AUDIO_VOLUME_CONTROL,
4854 	    USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4855 	rv = 0;
4856 
4857 OUT:
4858 	mutex_exit(&statep->usb_ac_mutex);
4859 	return (rv);
4860 }
4861 
4862 
4863 /*
4864  * mono level control callback
4865  */
4866 static int
4867 usb_audio_write_mono_vol(void *arg, uint64_t cval)
4868 {
4869 	usb_audio_ctrl_t *ctrlp = arg;
4870 	usb_ac_state_t *statep = ctrlp->statep;
4871 	int rv = EIO;
4872 	int gain;
4873 
4874 	uint_t count = 0;
4875 
4876 	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4877 		return (EINVAL);
4878 	}
4879 
4880 	mutex_enter(&ctrlp->ctrl_mutex);
4881 	ctrlp->cval = cval;
4882 	mutex_exit(&ctrlp->ctrl_mutex);
4883 
4884 	gain = (int)(cval);
4885 
4886 	mutex_enter(&statep->usb_ac_mutex);
4887 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4888 	    USB_AUDIO_FEATURE_UNIT, 1,
4889 	    USB_AUDIO_VOLUME_CONTROL,
4890 	    USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4891 
4892 	rv = 0;
4893 OUT:
4894 	mutex_exit(&statep->usb_ac_mutex);
4895 
4896 	return (rv);
4897 }
4898 
4899 
4900 /*
4901  * mono level control callback
4902  */
4903 static int
4904 usb_audio_write_monitor_gain(void *arg, uint64_t cval)
4905 {
4906 	usb_audio_ctrl_t *ctrlp = arg;
4907 	usb_ac_state_t *statep = ctrlp->statep;
4908 	int rv = EIO;
4909 	int gain;
4910 	uint_t count = 0;
4911 
4912 	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4913 
4914 		return (EINVAL);
4915 	}
4916 
4917 	mutex_enter(&ctrlp->ctrl_mutex);
4918 	ctrlp->cval = cval;
4919 	mutex_exit(&ctrlp->ctrl_mutex);
4920 
4921 	gain = (int)(cval);
4922 
4923 	mutex_enter(&statep->usb_ac_mutex);
4924 	(void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
4925 	    USB_AUDIO_INPUT_TERMINAL, 1,
4926 	    USB_AUDIO_VOLUME_CONTROL,
4927 	    USB_AC_FIND_ALL, &count, gain,
4928 	    usb_ac_set_monitor_gain);
4929 
4930 	rv = 0;
4931 OUT:
4932 	mutex_exit(&statep->usb_ac_mutex);
4933 	return (rv);
4934 }
4935 
4936 static int
4937 usb_audio_write_mono_rec(void *arg, uint64_t cval)
4938 {
4939 	usb_audio_ctrl_t *ctrlp = arg;
4940 	usb_ac_state_t *statep = ctrlp->statep;
4941 	int rv = EIO;
4942 	int gain;
4943 
4944 	uint_t count = 0;
4945 
4946 	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4947 
4948 		return (EINVAL);
4949 	}
4950 
4951 	mutex_enter(&ctrlp->ctrl_mutex);
4952 	ctrlp->cval = cval;
4953 	mutex_exit(&ctrlp->ctrl_mutex);
4954 
4955 	gain = (int)(cval);
4956 
4957 	mutex_enter(&statep->usb_ac_mutex);
4958 	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4959 	    USB_AUDIO_FEATURE_UNIT, 1,
4960 	    USB_AUDIO_VOLUME_CONTROL,
4961 	    USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4962 
4963 	rv = 0;
4964 
4965 	mutex_exit(&statep->usb_ac_mutex);
4966 	return (rv);
4967 }
4968 
4969 static int
4970 usb_audio_write_mic_boost(void *arg, uint64_t cval)
4971 {
4972 	usb_audio_ctrl_t *ctrlp = arg;
4973 
4974 	mutex_enter(&ctrlp->ctrl_mutex);
4975 	ctrlp->cval = cval;
4976 	mutex_exit(&ctrlp->ctrl_mutex);
4977 	/* do nothing here */
4978 	return (0);
4979 }
4980 
4981 static int
4982 usb_audio_write_rec_src(void *arg, uint64_t cval)
4983 {
4984 	usb_audio_ctrl_t *ctrlp = arg;
4985 	usb_ac_state_t *statep = ctrlp->statep;
4986 	int rv = 0;
4987 
4988 	if (cval & ~(statep->usb_ac_input_ports))
4989 		return (EINVAL);
4990 
4991 	mutex_enter(&ctrlp->ctrl_mutex);
4992 	ctrlp->cval = cval;
4993 	mutex_exit(&ctrlp->ctrl_mutex);
4994 
4995 	mutex_enter(&statep->usb_ac_mutex);
4996 	if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
4997 
4998 		USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
4999 		    "usb_audio_write_rec_src: failed");
5000 		rv = EINVAL;
5001 	}
5002 	mutex_exit(&statep->usb_ac_mutex);
5003 	rv = 0;
5004 
5005 OUT:
5006 	return (rv);
5007 
5008 }
5009 
5010 
5011 int
5012 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
5013 {
5014 	short	muteval;
5015 	int	rval;
5016 
5017 	uint_t count;
5018 	muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
5019 	count = 0;
5020 	/* only support AUDIO_PLAY */
5021 
5022 	mutex_enter(&statep->usb_ac_mutex);
5023 	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
5024 	    USB_AUDIO_FEATURE_UNIT, 0,
5025 	    USB_AUDIO_MUTE_CONTROL,
5026 	    USB_AC_FIND_ALL, &count, muteval,
5027 	    usb_ac_set_mute);
5028 	mutex_exit(&statep->usb_ac_mutex);
5029 
5030 	rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
5031 
5032 	return (rval);
5033 }
5034 
5035 
5036 /*
5037  * port selection control callback
5038  */
5039 /*
5040  * audio control registration related routines
5041  */
5042 
5043 static usb_audio_ctrl_t *
5044 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
5045 {
5046 	audio_ctrl_desc_t	desc;
5047 	audio_ctrl_wr_t		fn;
5048 	usb_audio_ctrl_t	*pc;
5049 
5050 	pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
5051 
5052 	mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
5053 
5054 	bzero(&desc, sizeof (desc));
5055 
5056 	switch (num) {
5057 	case CTL_VOLUME_MONO:
5058 		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5059 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5060 		desc.acd_minvalue = 0;
5061 		desc.acd_maxvalue = AF_MAX_GAIN;
5062 		desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5063 		    | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5064 		fn = usb_audio_write_mono_vol;
5065 		break;
5066 
5067 	case CTL_VOLUME_STERO:
5068 		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5069 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5070 		desc.acd_minvalue = 0;
5071 		desc.acd_maxvalue = AF_MAX_GAIN;
5072 		desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5073 		    | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5074 		fn = usb_audio_write_ster_vol;
5075 
5076 		break;
5077 
5078 	case CTL_REC_MONO:
5079 		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5080 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5081 		desc.acd_minvalue = 0;
5082 		desc.acd_maxvalue = AF_MAX_GAIN;
5083 		desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5084 		    | AUDIO_CTRL_FLAG_RW;
5085 		fn = usb_audio_write_mono_rec;
5086 		break;
5087 	case CTL_REC_STERO:
5088 
5089 		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5090 		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5091 		desc.acd_minvalue = 0;
5092 		desc.acd_maxvalue = AF_MAX_GAIN;
5093 		desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5094 		    | AUDIO_CTRL_FLAG_RW;
5095 		fn = usb_audio_write_stero_rec;
5096 		break;
5097 
5098 	case CTL_MONITOR_GAIN:
5099 
5100 		desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
5101 		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5102 		desc.acd_minvalue = 0;
5103 		desc.acd_maxvalue = AF_MAX_GAIN;
5104 		desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
5105 		    |AUDIO_CTRL_FLAG_RW;
5106 		fn = usb_audio_write_monitor_gain;
5107 		break;
5108 
5109 	case CTL_MIC_BOOST:
5110 
5111 		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
5112 		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
5113 		desc.acd_minvalue = 0;
5114 		desc.acd_maxvalue = 1;
5115 		desc.acd_flags = AUDIO_CTRL_FLAG_RW;
5116 		fn = usb_audio_write_mic_boost;
5117 		break;
5118 	case CTL_REC_SRC:
5119 
5120 		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
5121 		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
5122 		desc.acd_minvalue = statep->usb_ac_input_ports;
5123 		desc.acd_maxvalue = statep->usb_ac_input_ports;
5124 		desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
5125 		for (int i = 0; usb_audio_dtypes[i]; i++) {
5126 			desc.acd_enum[i] = usb_audio_dtypes[i];
5127 		}
5128 
5129 		fn = usb_audio_write_rec_src;
5130 		break;
5131 
5132 
5133 
5134 	default:
5135 
5136 		break;
5137 	}
5138 
5139 	mutex_enter(&pc->ctrl_mutex);
5140 
5141 	pc->statep = statep;
5142 	pc->cval = val;
5143 	pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
5144 	    usb_audio_ctrl_read, fn, pc);
5145 
5146 	mutex_exit(&pc->ctrl_mutex);
5147 
5148 	mutex_enter(&statep->usb_ac_mutex);
5149 	statep->controls[num] = pc;
5150 	mutex_exit(&statep->usb_ac_mutex);
5151 
5152 
5153 	return (pc);
5154 }
5155 
5156 
5157 static void
5158 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
5159 {
5160 	kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
5161 }
5162 
5163 static void
5164 usb_ac_rem_controls(usb_ac_state_t *statep)
5165 {
5166 	usb_audio_ctrl_t *ctrlp;
5167 
5168 	for (int i = 0; i < CTL_NUM; i++) {
5169 		ctrlp = statep->controls[i];
5170 		if (ctrlp) {
5171 			if (ctrlp->af_ctrlp != NULL)
5172 				audio_dev_del_control(ctrlp->af_ctrlp);
5173 
5174 			usb_audio_ctrl_free(ctrlp);
5175 			mutex_enter(&statep->usb_ac_mutex);
5176 			statep->controls[i] = NULL;
5177 			mutex_exit(&statep->usb_ac_mutex);
5178 		}
5179 	}
5180 
5181 }
5182 
5183 
5184 static int
5185 usb_ac_add_controls(usb_ac_state_t *statep)
5186 {
5187 	int rv = USB_FAILURE;
5188 	usb_audio_format_t *format;
5189 
5190 
5191 	if (statep->engines[0].af_engp) {
5192 		/* Init controls for play format */
5193 		format = &(statep->engines[0].fmt);
5194 		if (format->ch == 2) {
5195 			(void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
5196 			    statep->engines[0].af_defgain);
5197 		} else {
5198 			(void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
5199 			    statep->engines[0].af_defgain);
5200 		}
5201 
5202 	}
5203 
5204 	/* Init controls for rec format */
5205 	if (statep->engines[1].af_engp) {
5206 		format = &(statep->engines[1].fmt);
5207 		if (format->ch == 2) {
5208 			(void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
5209 			    statep->engines[1].af_defgain);
5210 		} else {
5211 			(void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
5212 			    statep->engines[1].af_defgain);
5213 		}
5214 
5215 		/* Add monitor control */
5216 		{
5217 			(void) usb_audio_ctrl_alloc(statep,
5218 			    CTL_MONITOR_GAIN, 0);
5219 		}
5220 
5221 		/* Add ports control */
5222 		{
5223 			(void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
5224 			    statep->usb_ac_input_ports);
5225 		}
5226 
5227 	}
5228 
5229 
5230 	rv = USB_SUCCESS;
5231 
5232 OUT:
5233 	if (rv != USB_SUCCESS)
5234 		usb_ac_rem_controls(statep);
5235 	return (rv);
5236 }
5237 
5238 
5239 
5240 
5241 
5242 /*ARGSUSED*/
5243 static int
5244 usb_audio_unregister(usb_ac_state_t *statep)
5245 {
5246 	int i;
5247 
5248 	if (statep == NULL)
5249 		return (USB_SUCCESS);
5250 
5251 	if (statep->usb_ac_audio_dev == NULL)
5252 		return (USB_SUCCESS);
5253 
5254 	if ((statep->flags & AF_REGISTERED) &&
5255 	    audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
5256 		return (USB_FAILURE);
5257 	}
5258 	mutex_enter(&statep->usb_ac_mutex);
5259 	statep->flags &= ~AF_REGISTERED;
5260 	mutex_exit(&statep->usb_ac_mutex);
5261 
5262 	for (i = 0; i < USB_AC_ENG_MAX; i++)
5263 		usb_ac_rem_eng(statep, &statep->engines[i]);
5264 
5265 	usb_ac_rem_controls(statep);
5266 
5267 	audio_dev_free(statep->usb_ac_audio_dev);
5268 
5269 	mutex_enter(&statep->usb_ac_mutex);
5270 	statep->usb_ac_audio_dev = NULL;
5271 	mutex_exit(&statep->usb_ac_mutex);
5272 
5273 	return (USB_SUCCESS);
5274 }
5275 
5276 
5277 static int
5278 usb_audio_register(usb_ac_state_t *statep) {
5279 	audio_dev_t *af_devp;
5280 	int rv = USB_FAILURE;
5281 	int n;
5282 
5283 	af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
5284 	audio_dev_set_description(af_devp,  "USB Audio");
5285 	audio_dev_set_version(af_devp, "1.0");
5286 
5287 	mutex_enter(&statep->usb_ac_mutex);
5288 	statep->usb_ac_audio_dev = af_devp;
5289 	mutex_exit(&statep->usb_ac_mutex);
5290 
5291 
5292 	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
5293 		if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
5294 		    != USB_SUCCESS) {
5295 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
5296 			    statep->usb_ac_log_handle,
5297 			    "usb_audio_register: add engine n =%d failed", n);
5298 			goto OUT;
5299 		}
5300 	}
5301 
5302 
5303 	if (usb_ac_add_controls(statep) != USB_SUCCESS) {
5304 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5305 		    "usb_audio_register: add controls failed");
5306 		goto OUT;
5307 	}
5308 
5309 	if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
5310 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5311 		    "usb_audio_register: set defaults failed");
5312 		goto OUT;
5313 	}
5314 
5315 	if (audio_dev_register(af_devp) != DDI_SUCCESS) {
5316 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5317 		    "audio_dev_register() failed");
5318 		goto OUT;
5319 	}
5320 	mutex_enter(&statep->usb_ac_mutex);
5321 	statep->flags |= AF_REGISTERED;
5322 	mutex_exit(&statep->usb_ac_mutex);
5323 
5324 	rv = USB_SUCCESS;
5325 
5326 OUT:
5327 	if (rv != USB_SUCCESS) {
5328 		(void) usb_audio_unregister(statep);
5329 	}
5330 	return (rv);
5331 }
5332 
5333 
5334 int
5335 usb_ac_get_audio(void *handle, void *buf, int samples)
5336 {
5337 	usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5338 	usb_audio_eng_t *engp = &(statep->engines[0]);
5339 	unsigned reqframes = samples >> engp->frsmshift;
5340 	unsigned frames;
5341 	unsigned i;
5342 	size_t sz;
5343 	caddr_t bp = buf;
5344 
5345 	mutex_enter(&engp->lock);
5346 	if (!engp->started) {
5347 		mutex_exit(&engp->lock);
5348 
5349 		return (0);
5350 	}
5351 	engp->busy = B_TRUE;
5352 	mutex_exit(&engp->lock);
5353 
5354 	/* break requests from the driver into fragment sized chunks */
5355 	for (i = 0; i < reqframes; i += frames) {
5356 
5357 		mutex_enter(&engp->lock);
5358 		frames = reqframes - i;
5359 		if (frames > engp->fragfr)
5360 			frames = engp->fragfr;
5361 
5362 		sz = (frames << engp->frsmshift) << engp->smszshift;
5363 
5364 		/* must move data before updating framework */
5365 		usb_eng_bufio(engp, bp, sz);
5366 		engp->frames += frames;
5367 		bp += sz;
5368 
5369 		mutex_exit(&engp->lock);
5370 	}
5371 
5372 	mutex_enter(&engp->lock);
5373 	engp->io_count++;
5374 	engp->busy = B_FALSE;
5375 	cv_signal(&engp->usb_audio_cv);
5376 	mutex_exit(&engp->lock);
5377 
5378 	return (samples);
5379 }
5380 
5381 
5382 
5383 void
5384 usb_ac_send_audio(void *handle, void *buf, int samples)
5385 {
5386 	usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5387 	usb_audio_eng_t *engp = &(statep->engines[1]);
5388 	unsigned reqframes = samples >> engp->frsmshift;
5389 	unsigned frames;
5390 	unsigned i;
5391 	size_t sz;
5392 	caddr_t bp = buf;
5393 
5394 	mutex_enter(&engp->lock);
5395 
5396 	if (!engp->started) {
5397 
5398 		mutex_exit(&engp->lock);
5399 		return;
5400 	}
5401 	engp->busy = B_TRUE;
5402 	mutex_exit(&engp->lock);
5403 
5404 	/* break requests from the driver into fragment sized chunks */
5405 	for (i = 0; i < reqframes; i += frames) {
5406 		mutex_enter(&engp->lock);
5407 
5408 		frames = reqframes - i;
5409 		if (frames > engp->fragfr)
5410 			frames = engp->fragfr;
5411 
5412 		sz = (frames << engp->frsmshift) << engp->smszshift;
5413 
5414 		/* must move data before updating framework */
5415 		usb_eng_bufio(engp, bp, sz);
5416 		engp->frames += frames;
5417 		bp += sz;
5418 
5419 		mutex_exit(&engp->lock);
5420 	}
5421 
5422 	mutex_enter(&engp->lock);
5423 	engp->io_count++;
5424 	engp->busy = B_FALSE;
5425 	cv_signal(&engp->usb_audio_cv);
5426 	mutex_exit(&engp->lock);
5427 }
5428 
5429 
5430 /*
5431  * **************************************************************************
5432  * audio framework engine callbacks
5433  */
5434 static int
5435 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
5436 {
5437 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5438 	usb_ac_state_t *statep = engp->statep;
5439 	int rv = EIO;
5440 
5441 	_NOTE(ARGUNUSED(flag));
5442 
5443 	if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
5444 
5445 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5446 		    "usb_ac_open() failed");
5447 		return (EIO);
5448 	}
5449 
5450 	mutex_enter(&engp->lock);
5451 
5452 	engp->intrate =  150;
5453 	engp->sampsz = engp->fmt.prec / 8;
5454 	engp->framesz = engp->sampsz * engp->fmt.ch;
5455 
5456 	if (engp->fmt.ch > 2) {
5457 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5458 		    "unsupported channel count: %u", engp->fmt.ch);
5459 		mutex_exit(&engp->lock);
5460 		goto OUT;
5461 	}
5462 	if (engp->fmt.prec > 16) {
5463 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5464 		    "unsupported precision: %u", engp->fmt.prec);
5465 		mutex_exit(&engp->lock);
5466 		goto OUT;
5467 	}
5468 
5469 	engp->frsmshift = engp->fmt.ch / 2;
5470 	engp->smszshift = engp->sampsz / 2;
5471 
5472 	/*
5473 	 * In order to match the requested number of samples per interrupt
5474 	 * from SADA drivers when computing the fragment size,
5475 	 * we need to first truncate the floating point result from
5476 	 *	sample rate * channels / intr rate
5477 	 * then adjust up to an even number, before multiplying it
5478 	 * with the sample size
5479 	 */
5480 	engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
5481 	if (engp->fragsz & 1)
5482 		engp->fragsz++;
5483 	engp->fragsz *= engp->sampsz;
5484 	engp->fragfr = engp->fragsz / engp->framesz;
5485 
5486 	engp->nfrags = 10;
5487 	engp->bufsz = engp->fragsz * engp->nfrags;
5488 
5489 	engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
5490 	engp->bufpos = engp->bufp;
5491 	engp->bufendp = engp->bufp + engp->bufsz;
5492 	engp->frames = 0;
5493 	engp->io_count = 0;
5494 	engp->bufio_count = 0;
5495 	engp->started = B_FALSE;
5496 	engp->busy = B_FALSE;
5497 
5498 	*nframesp = engp->nfrags * engp->fragfr;
5499 	*bufp = engp->bufp;
5500 
5501 	mutex_exit(&engp->lock);
5502 
5503 	if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
5504 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5505 		    "device setup failed");
5506 		goto OUT;
5507 	}
5508 
5509 
5510 
5511 	mutex_enter(&statep->usb_ac_mutex);
5512 	statep->flags |= AD_SETUP;
5513 	mutex_exit(&statep->usb_ac_mutex);
5514 
5515 	rv = 0;
5516 
5517 
5518 OUT:
5519 	if (rv != 0)
5520 		usb_engine_close(arg);
5521 
5522 	return (rv);
5523 }
5524 
5525 
5526 static void
5527 usb_engine_close(void *arg)
5528 {
5529 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5530 	usb_ac_state_t *statep = engp->statep;
5531 
5532 	mutex_enter(&engp->lock);
5533 	while (engp->busy) {
5534 		cv_wait(&engp->usb_audio_cv, &engp->lock);
5535 	}
5536 
5537 	mutex_exit(&engp->lock);
5538 
5539 	if (statep->flags & AD_SETUP) {
5540 		usb_ac_teardown(statep, engp);
5541 		mutex_enter(&statep->usb_ac_mutex);
5542 		statep->flags &= ~AD_SETUP;
5543 		mutex_exit(&statep->usb_ac_mutex);
5544 	}
5545 	mutex_enter(&engp->lock);
5546 
5547 	if (engp->bufp != NULL) {
5548 		kmem_free(engp->bufp, engp->bufsz);
5549 		engp->bufp = NULL;
5550 		engp->bufpos = NULL;
5551 		engp->bufendp = NULL;
5552 	}
5553 
5554 	mutex_exit(&engp->lock);
5555 
5556 	usb_ac_close(statep->usb_ac_dip);
5557 }
5558 
5559 
5560 
5561 static int
5562 usb_engine_start(void *arg)
5563 {
5564 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5565 	int rv = 0;
5566 	int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
5567 
5568 	mutex_enter(&engp->lock);
5569 	engp->started = B_TRUE;
5570 	mutex_exit(&engp->lock);
5571 
5572 	usb_ac_state_t *statep = engp->statep;
5573 
5574 	start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5575 	    usb_ac_start_play : usb_ac_start_record;
5576 
5577 	if ((*start)(statep, engp) != USB_SUCCESS) {
5578 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5579 		    "failed to start %d engine", engp->af_eflags);
5580 		rv = EIO;
5581 	}
5582 
5583 
5584 	return (rv);
5585 }
5586 
5587 
5588 static void
5589 usb_engine_stop(void *arg)
5590 {
5591 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5592 
5593 	mutex_enter(&engp->lock);
5594 	engp->started = B_FALSE;
5595 	mutex_exit(&engp->lock);
5596 
5597 	usb_ac_state_t *statep = engp->statep;
5598 	void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
5599 
5600 	stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5601 	    usb_ac_stop_play : usb_ac_stop_record;
5602 
5603 	(*stop)(statep, engp);
5604 }
5605 
5606 
5607 static uint64_t
5608 usb_engine_count(void *arg)
5609 {
5610 	usb_audio_eng_t	*engp = arg;
5611 	uint64_t	val;
5612 
5613 	mutex_enter(&engp->lock);
5614 	val = engp->frames;
5615 	mutex_exit(&engp->lock);
5616 
5617 	return (val);
5618 }
5619 
5620 
5621 static int
5622 usb_engine_format(void *arg)
5623 {
5624 	usb_audio_eng_t *engp = arg;
5625 
5626 	switch (engp->fmt.enc) {
5627 		case USB_AUDIO_FORMAT_TYPE1_MULAW:
5628 			return (AUDIO_FORMAT_ULAW);
5629 		case USB_AUDIO_FORMAT_TYPE1_ALAW:
5630 			return (AUDIO_FORMAT_ALAW);
5631 		case USB_AUDIO_FORMAT_TYPE1_PCM8:
5632 			return (AUDIO_FORMAT_U8);
5633 
5634 		case USB_AUDIO_FORMAT_TYPE1_PCM:
5635 			break;
5636 		default:
5637 			return (AUDIO_FORMAT_NONE);
5638 	}
5639 
5640 	switch (engp->fmt.prec) {
5641 		case 8:
5642 			return (AUDIO_FORMAT_S8);
5643 		case 16:
5644 			return (AUDIO_FORMAT_S16_LE);
5645 		case 24:
5646 			return (AUDIO_FORMAT_S24_LE);
5647 		case 32:
5648 			return (AUDIO_FORMAT_S32_LE);
5649 		default:
5650 			break;
5651 	}
5652 	return (AUDIO_FORMAT_NONE);
5653 
5654 
5655 }
5656 
5657 static int
5658 usb_engine_channels(void *arg)
5659 {
5660 	usb_audio_eng_t *engp = arg;
5661 
5662 	return (engp->fmt.ch);
5663 }
5664 
5665 
5666 static int
5667 usb_engine_rate(void *arg)
5668 {
5669 	usb_audio_eng_t *engp = arg;
5670 
5671 	return (engp->fmt.sr);
5672 }
5673 
5674 
5675 /*ARGSUSED*/
5676 static void
5677 usb_engine_sync(void *arg, unsigned nframes)
5678 {
5679 	/* Do nothing */
5680 }
5681 
5682 
5683 static unsigned
5684 usb_engine_qlen(void *arg)
5685 {
5686 	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5687 
5688 	return (engp->fragfr);
5689 }
5690 
5691 /*
5692  * **************************************************************************
5693  * interfaces used by USB audio
5694  */
5695 
5696 /*ARGSUSED*/
5697 static int
5698 usb_change_phy_vol(usb_ac_state_t *statep, int value)
5699 {
5700 	usb_audio_ctrl_t *ctrlp;
5701 	uint64_t cval = 0;
5702 	int64_t left, right, delta = 0;
5703 
5704 	ctrlp = statep->controls[CTL_VOLUME_STERO];
5705 
5706 	ASSERT(value != 0);
5707 
5708 	delta = (value < 0)?-1:1;
5709 
5710 	left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
5711 	right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
5712 
5713 	if (left > AF_MAX_GAIN)
5714 		left = AF_MAX_GAIN;
5715 	if (right > AF_MAX_GAIN)
5716 		right = AF_MAX_GAIN;
5717 
5718 	if (left < AF_MIN_GAIN)
5719 		left = AF_MIN_GAIN;
5720 	if (right < AF_MIN_GAIN)
5721 		right = AF_MIN_GAIN;
5722 
5723 	cval = AUDIO_CTRL_STEREO_VAL(left, right);
5724 
5725 	if (audio_control_write(ctrlp->af_ctrlp, cval)) {
5726 		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5727 		    "updateing control  to value 0x%llx by driver failed",
5728 		    (long long unsigned)cval);
5729 		return (USB_FAILURE);
5730 	}
5731 	return (USB_SUCCESS);
5732 }
5733