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
_init(void)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
_fini(void)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
_info(struct modinfo * modinfop)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
usb_ac_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)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
usb_ac_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)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
usb_ac_cleanup(dev_info_t * dip,usb_ac_state_t * uacp)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
usb_ac_open(dev_info_t * dip)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
usb_ac_close(dev_info_t * dip)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
usb_ac_read_msg(usb_ac_plumbed_t * plumb_infop,mblk_t * mp)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
usb_ac_power(dev_info_t * dip,int comp,int level)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
usb_ac_pwrlvl0(usb_ac_state_t * uacp)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
usb_ac_pwrlvl1(usb_ac_state_t * uacp)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
usb_ac_pwrlvl2(usb_ac_state_t * uacp)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
usb_ac_pwrlvl3(usb_ac_state_t * uacp)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
usb_ac_create_pm_components(dev_info_t * dip,usb_ac_state_t * uacp)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
usb_ac_get_featureID(usb_ac_state_t * uacp,uchar_t dir,uint_t channel,uint_t control)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
usb_ac_feature_unit_check(usb_ac_state_t * uacp,uint_t featureID,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth)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
usb_ac_handle_descriptors(usb_ac_state_t * uacp)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
usb_ac_setup_connections(usb_ac_state_t * uacp)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
usb_ac_add_unit_descriptor(usb_ac_state_t * uacp,uchar_t * buffer,size_t buflen)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
usb_ac_alloc_unit(usb_ac_state_t * uacp,uint_t unit)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
usb_ac_free_all_units(usb_ac_state_t * uacp)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
usb_ac_lookup_port_type(ushort_t termtype)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
usb_ac_update_port(usb_ac_state_t * uacp,uint_t id,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth)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
usb_ac_map_termtype_to_port(usb_ac_state_t * uacp,uint_t dir)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
usb_ac_set_port(usb_ac_state_t * uacp,uint_t dir,uint_t port)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
usb_ac_match_port(usb_ac_state_t * uacp,uint_t id,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth)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
usb_ac_set_selector(usb_ac_state_t * uacp,uint_t id,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth)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
usb_ac_set_control(usb_ac_state_t * uacp,uint_t dir,uint_t search_target,uint_t channel,uint_t control,uint_t all_or_one,uint_t * count,uint_t arg1,int (* func)(usb_ac_state_t * uacp,uint_t unit,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth))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
usb_ac_traverse_all_units(usb_ac_state_t * uacp,uint_t dir,uint_t search_target,uint_t channel,uint_t control,uint_t all_or_one,uint_t * count,uint_t arg1,uint_t * depth,int (* func)(usb_ac_state_t * uacp,uint_t unit,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth))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
usb_ac_set_monitor_gain_control(usb_ac_state_t * uacp,uint_t dir,uint_t search_target,uint_t channel,uint_t control,uint_t all_or_one,uint_t * count,uint_t arg1,int (* func)(usb_ac_state_t * uacp,uint_t unit,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth))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
usb_ac_push_unit_id(usb_ac_state_t * uacp,uint_t unit)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
usb_ac_pop_unit_id(usb_ac_state_t * uacp,uint_t unit)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
usb_ac_show_traverse_path(usb_ac_state_t * uacp)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
usb_ac_check_path(usb_ac_state_t * uacp,uint_t type)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
usb_ac_traverse_connections(usb_ac_state_t * uacp,uint_t start_unit,uint_t dir,uint_t search_target,uint_t channel,uint_t control,uint_t all_or_one,uint_t * count,uint_t arg1,uint_t * depth,int (* func)(usb_ac_state_t * uacp,uint_t unit,uint_t dir,uint_t channel,uint_t control,uint_t arg1,uint_t * depth))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
usb_ac_disconnect_event_cb(dev_info_t * dip)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
usb_ac_cpr_suspend(dev_info_t * dip)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
usb_ac_reconnect_event_cb(dev_info_t * dip)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
usb_ac_cpr_resume(dev_info_t * dip)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
usb_ac_restore_device_state(dev_info_t * dip,usb_ac_state_t * uacp)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
usb_ac_am_restore_state(void * arg)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
usb_ac_restore_audio_state(usb_ac_state_t * uacp,int flag)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
usb_ac_setup(usb_ac_state_t * uacp,usb_audio_eng_t * engine)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
usb_ac_do_setup(usb_ac_state_t * uacp,usb_audio_eng_t * engine)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
usb_ac_teardown(usb_ac_state_t * uacp,usb_audio_eng_t * engine)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
usb_ac_set_monitor_gain(usb_ac_state_t * uacp,uint_t unit,uint_t dir,uint_t channel,uint_t control,uint_t gain,uint_t * depth)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
usb_ac_set_gain(usb_ac_state_t * uacp,uint_t featureID,uint_t dir,uint_t channel,uint_t control,uint_t gain,uint_t * depth)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
usb_ac_set_format(usb_ac_state_t * uacp,usb_audio_eng_t * engine)2983 usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2984 {
2985 	usb_ac_streams_info_t	*streams_infop = NULL;
2986 	usb_audio_formats_t	format;
2987 	int old_setup_teardown_count = 0;
2988 
2989 	mutex_enter(&uacp->usb_ac_mutex);
2990 	streams_infop = (usb_ac_streams_info_t *)engine->streams;
2991 
2992 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2993 		mutex_exit(&uacp->usb_ac_mutex);
2994 
2995 		return (USB_FAILURE);
2996 	}
2997 	mutex_exit(&uacp->usb_ac_mutex);
2998 
2999 	usb_ac_serialize_access(uacp);
3000 	mutex_enter(&uacp->usb_ac_mutex);
3001 
3002 	bzero(&format, sizeof (usb_audio_formats_t));
3003 
3004 	/* save format info */
3005 	format.fmt_n_srs	= 1;
3006 	format.fmt_srs		= (uint_t *)&(engine->fmt.sr);
3007 	format.fmt_chns		= (uchar_t)engine->fmt.ch;
3008 	format.fmt_precision	= (uchar_t)engine->fmt.prec;
3009 	format.fmt_encoding	= (uchar_t)engine->fmt.enc;
3010 
3011 	old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3012 
3013 	/* isoc pipe not open and playing is not in progress */
3014 	if (old_setup_teardown_count) {
3015 		streams_infop->acs_setup_teardown_count = 1;
3016 
3017 		mutex_exit(&uacp->usb_ac_mutex);
3018 		usb_ac_release_access(uacp);
3019 
3020 		usb_ac_stop_play(uacp, engine);
3021 		usb_ac_teardown(uacp, engine);
3022 
3023 		usb_ac_serialize_access(uacp);
3024 		mutex_enter(&uacp->usb_ac_mutex);
3025 	}
3026 
3027 	/*
3028 	 * Set format for the streaming interface with lower write queue
3029 	 * This boils down to set_alternate  interface command in
3030 	 * usb_as and the reply mp contains the currently active
3031 	 * alternate number that is stored in the as_req structure
3032 	 */
3033 	if (usb_ac_send_as_cmd(uacp, engine,
3034 	    USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
3035 		USB_DPRINTF_L2(PRINT_MASK_ALL,
3036 		    uacp->usb_ac_log_handle,
3037 		    "usb_ac_set_format: failed");
3038 		goto fail;
3039 
3040 	}
3041 	int sample =  engine->fmt.sr;
3042 
3043 	/* Set the sample rate */
3044 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
3045 	    &sample) != USB_SUCCESS) {
3046 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3047 		    "usb_ac_set_format: setting format failed");
3048 		goto fail;
3049 
3050 	}
3051 
3052 	mutex_exit(&uacp->usb_ac_mutex);
3053 
3054 	usb_ac_release_access(uacp);
3055 
3056 	/* This should block until successful */
3057 	if (old_setup_teardown_count) {
3058 		(void) usb_ac_setup(uacp, engine);
3059 	}
3060 
3061 	mutex_enter(&uacp->usb_ac_mutex);
3062 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3063 	mutex_exit(&uacp->usb_ac_mutex);
3064 
3065 	return (USB_SUCCESS);
3066 fail:
3067 	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3068 	mutex_exit(&uacp->usb_ac_mutex);
3069 	usb_ac_release_access(uacp);
3070 
3071 	return (USB_FAILURE);
3072 
3073 }
3074 
3075 /*
3076  * usb_ac_start_play
3077  *	Send a start_play command down to usb_as
3078  *	Check power is done in usb_ac_send_as_cmd()
3079  */
3080 static int
usb_ac_start_play(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3081 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3082 {
3083 	int			samples;
3084 	usb_audio_play_req_t	play_req;
3085 
3086 
3087 	mutex_enter(&uacp->usb_ac_mutex);
3088 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3089 		mutex_exit(&uacp->usb_ac_mutex);
3090 
3091 		return (USB_FAILURE);
3092 	}
3093 	mutex_exit(&uacp->usb_ac_mutex);
3094 
3095 	usb_ac_serialize_access(uacp);
3096 
3097 	mutex_enter(&uacp->usb_ac_mutex);
3098 
3099 
3100 
3101 	/* Check for continuous sample rate done in usb_as */
3102 	samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
3103 	if (samples & engine->fmt.ch) {
3104 		samples++;
3105 	}
3106 
3107 	play_req.up_samples = samples;
3108 	play_req.up_handle = uacp;
3109 
3110 	/* Send setup command to usb_as */
3111 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
3112 	    (void *)&play_req) != USB_SUCCESS) {
3113 
3114 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3115 		    "usb_ac_start_play: failure");
3116 
3117 		mutex_exit(&uacp->usb_ac_mutex);
3118 
3119 		usb_ac_release_access(uacp);
3120 
3121 		return (USB_FAILURE);
3122 	}
3123 
3124 	mutex_exit(&uacp->usb_ac_mutex);
3125 
3126 	usb_ac_release_access(uacp);
3127 
3128 	return (USB_SUCCESS);
3129 }
3130 
3131 
3132 /*
3133  * usb_ac_stop_play:
3134  *	Stop the play engine
3135  *	called from mixer framework.
3136  */
3137 void
usb_ac_stop_play(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3138 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3139 {
3140 
3141 	if (engine == NULL) {
3142 		engine = &(uacp->engines[0]);
3143 	}
3144 	mutex_enter(&uacp->usb_ac_mutex);
3145 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3146 		mutex_exit(&uacp->usb_ac_mutex);
3147 
3148 		return;
3149 	}
3150 	mutex_exit(&uacp->usb_ac_mutex);
3151 
3152 	usb_ac_serialize_access(uacp);
3153 	mutex_enter(&uacp->usb_ac_mutex);
3154 
3155 	/* Send setup command to usb_as */
3156 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
3157 	    (void *)NULL) != USB_SUCCESS) {
3158 
3159 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3160 		    "usb_ac_do_pause_play: failure");
3161 	}
3162 
3163 	mutex_exit(&uacp->usb_ac_mutex);
3164 	usb_ac_release_access(uacp);
3165 }
3166 
3167 
3168 /*
3169  * usb_ac_start_record:
3170  *	Sends a start record command down to usb_as.
3171  *	Check power is done in usb_ac_send_as_cmd()
3172  */
3173 static int
usb_ac_start_record(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3174 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3175 {
3176 
3177 
3178 	mutex_enter(&uacp->usb_ac_mutex);
3179 	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3180 		mutex_exit(&uacp->usb_ac_mutex);
3181 
3182 		return (USB_FAILURE);
3183 	}
3184 	mutex_exit(&uacp->usb_ac_mutex);
3185 
3186 	usb_ac_serialize_access(uacp);
3187 	mutex_enter(&uacp->usb_ac_mutex);
3188 
3189 
3190 	/* Send setup command to usb_as */
3191 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
3192 	    (void *)uacp) != USB_SUCCESS) {
3193 
3194 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3195 		    "usb_ac_start_record: failure");
3196 
3197 		mutex_exit(&uacp->usb_ac_mutex);
3198 
3199 		usb_ac_release_access(uacp);
3200 
3201 		return (USB_FAILURE);
3202 	}
3203 
3204 	mutex_exit(&uacp->usb_ac_mutex);
3205 	usb_ac_release_access(uacp);
3206 
3207 	return (USB_SUCCESS);
3208 }
3209 
3210 
3211 /*
3212  * usb_ac_stop_record:
3213  *	Wrapper function for usb_ac_do_stop_record and is
3214  *	called form mixer framework.
3215  */
3216 static void
usb_ac_stop_record(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3217 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3218 {
3219 
3220 	usb_ac_serialize_access(uacp);
3221 	mutex_enter(&uacp->usb_ac_mutex);
3222 
3223 	/* Send setup command to usb_as */
3224 	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
3225 	    NULL) != USB_SUCCESS) {
3226 
3227 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3228 		    "usb_ac_do_stop_record: failure");
3229 	}
3230 
3231 	mutex_exit(&uacp->usb_ac_mutex);
3232 	usb_ac_release_access(uacp);
3233 }
3234 
3235 
3236 /*
3237  * Helper Functions for Mixer callbacks
3238  *
3239  * usb_ac_get_maxmin_volume:
3240  *	Send USBA command down to get the maximum or minimum gain balance
3241  *	Calculate min or max gain balance and return that. Return
3242  *	USB_FAILURE for failure cases
3243  */
3244 /* ARGSUSED */
3245 static int
usb_ac_get_maxmin_volume(usb_ac_state_t * uacp,uint_t channel,int cmd,int dir,int feature_unitID,short * max_or_minp)3246 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
3247     int dir, int feature_unitID, short *max_or_minp)
3248 {
3249 	mblk_t		*data = NULL;
3250 	usb_cr_t	cr;
3251 	usb_cb_flags_t	cb_flags;
3252 
3253 
3254 	mutex_exit(&uacp->usb_ac_mutex);
3255 
3256 	if (usb_pipe_sync_ctrl_xfer(
3257 	    uacp->usb_ac_dip,
3258 	    uacp->usb_ac_default_ph,
3259 	    USB_DEV_REQ_DEV_TO_HOST |
3260 	    USB_DEV_REQ_TYPE_CLASS |
3261 	    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
3262 	    cmd,			/* bRequest */
3263 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3264 					/* feature unit and id */
3265 	    (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
3266 	    2,				/* wLength */
3267 	    &data,
3268 	    USB_ATTRS_NONE,
3269 	    &cr, &cb_flags,
3270 	    USB_FLAGS_SLEEP) != USB_SUCCESS) {
3271 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3272 		    "usb_ac_get_maxmin_volume: failed, "
3273 		    "cr=%d, cb=0x%x cmd=%d, data=0x%p",
3274 		    cr, cb_flags, cmd, (void *)data);
3275 
3276 		freemsg(data);
3277 		mutex_enter(&uacp->usb_ac_mutex);
3278 
3279 		return (USB_FAILURE);
3280 	}
3281 
3282 	mutex_enter(&uacp->usb_ac_mutex);
3283 	ASSERT(MBLKL(data) == 2);
3284 
3285 	*max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr;
3286 
3287 	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3288 	    "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp);
3289 
3290 	freemsg(data);
3291 
3292 	return (USB_SUCCESS);
3293 }
3294 
3295 
3296 /*
3297  * usb_ac_set_volume:
3298  *	Send USBA command down to set the gain balance
3299  */
3300 /* ARGSUSED */
3301 static int
usb_ac_set_volume(usb_ac_state_t * uacp,uint_t channel,short gain,int dir,int feature_unitID)3302 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
3303     int feature_unitID)
3304 {
3305 	mblk_t		*data = NULL;
3306 	usb_cr_t	cr;
3307 	usb_cb_flags_t	cb_flags;
3308 	int		rval = USB_FAILURE;
3309 
3310 
3311 	mutex_exit(&uacp->usb_ac_mutex);
3312 
3313 	/* Construct the mblk_t from gain for sending to USBA */
3314 	data = allocb(4, BPRI_HI);
3315 	if (!data) {
3316 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3317 		    "usb_ac_set_volume: allocate data failed");
3318 		mutex_enter(&uacp->usb_ac_mutex);
3319 
3320 		return (USB_FAILURE);
3321 	}
3322 
3323 
3324 
3325 	*(data->b_wptr++) = (char)gain;
3326 	*(data->b_wptr++) = (char)(gain >> 8);
3327 
3328 	if ((rval = usb_pipe_sync_ctrl_xfer(
3329 	    uacp->usb_ac_dip,
3330 	    uacp->usb_ac_default_ph,
3331 	    USB_DEV_REQ_HOST_TO_DEV |
3332 	    USB_DEV_REQ_TYPE_CLASS |
3333 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3334 	    USB_AUDIO_SET_CUR,			/* bRequest */
3335 	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3336 						/* feature unit and id */
3337 	    (feature_unitID << 8) | uacp->usb_ac_ifno,	/* wIndex */
3338 	    2,					/* wLength */
3339 	    &data, 0,
3340 	    &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
3341 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3342 		    "usb_ac_set_volume: failed, cr=%d cb=0x%x",
3343 		    cr, cb_flags);
3344 	}
3345 
3346 	freemsg(data);
3347 	mutex_enter(&uacp->usb_ac_mutex);
3348 
3349 	return (rval);
3350 }
3351 
3352 
3353 /*
3354  * usb_ac_set_mute is called for each unit that supports the
3355  * requested control from usb_ac_traverse_connections
3356  */
3357 int
usb_ac_set_mute(usb_ac_state_t * uacp,uint_t featureID,uint_t dir,uint_t channel,uint_t control,uint_t muteval,uint_t * depth)3358 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
3359     uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
3360 {
3361 	mblk_t		*data;
3362 	usb_cr_t	cr;
3363 	usb_cb_flags_t	cb_flags;
3364 	int		rval = USB_FAILURE;
3365 
3366 
3367 	if (usb_ac_feature_unit_check(uacp, featureID,
3368 	    dir, channel, control, 0, depth) != USB_SUCCESS) {
3369 
3370 		return (USB_FAILURE);
3371 	}
3372 	mutex_exit(&uacp->usb_ac_mutex);
3373 
3374 	/* Construct the mblk_t for sending to USBA */
3375 	data = allocb(1, BPRI_HI);
3376 
3377 	if (!data) {
3378 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3379 		    "usb_ac_set_mute: allocate data failed");
3380 		mutex_enter(&uacp->usb_ac_mutex);
3381 
3382 		return (USB_FAILURE);
3383 	}
3384 
3385 
3386 	*(data->b_wptr++) = (char)muteval;
3387 
3388 	if ((rval = usb_pipe_sync_ctrl_xfer(
3389 	    uacp->usb_ac_dip,
3390 	    uacp->usb_ac_default_ph,
3391 	    USB_DEV_REQ_HOST_TO_DEV |
3392 	    USB_DEV_REQ_TYPE_CLASS |
3393 	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3394 	    USB_AUDIO_SET_CUR,			/* bRequest */
3395 	    (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
3396 						/* feature unit and id */
3397 	    (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
3398 	    1,					/* wLength */
3399 	    &data,
3400 	    0,					/* attributes */
3401 	    &cr, &cb_flags, 0)) != USB_SUCCESS) {
3402 
3403 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3404 		    "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
3405 	}
3406 	freemsg(data);
3407 
3408 	mutex_enter(&uacp->usb_ac_mutex);
3409 
3410 	return (rval);
3411 }
3412 
3413 
3414 /*
3415  * usb_ac_send_as_cmd:
3416  *	Allocate message blk, send a command down to usb_as,
3417  *	wait for the reply and free the message
3418  *
3419  *	although not really needed to raise power if sending to as
3420  *	it seems better to ensure that both interfaces are at full power
3421  */
3422 static int
usb_ac_send_as_cmd(usb_ac_state_t * uacp,usb_audio_eng_t * engine,int cmd,void * arg)3423 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
3424     int cmd, void *arg)
3425 {
3426 	usb_ac_streams_info_t *streams_infop;
3427 	usb_ac_plumbed_t *plumb_infop;
3428 	int		rv;
3429 	int		rval;
3430 	ldi_handle_t	lh;
3431 
3432 	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3433 	streams_infop = engine->streams;
3434 	plumb_infop = streams_infop->acs_plumbed;
3435 
3436 
3437 	lh = plumb_infop->acp_lh;
3438 
3439 	rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval);
3440 	if (rv != 0) {
3441 		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3442 		    "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv);
3443 
3444 		return (USB_FAILURE);
3445 	}
3446 
3447 	return (USB_SUCCESS);
3448 }
3449 
3450 
3451 /*
3452  * usb_ac_serialize/release_access:
3453  */
3454 static void
usb_ac_serialize_access(usb_ac_state_t * uacp)3455 usb_ac_serialize_access(usb_ac_state_t	*uacp)
3456 {
3457 	(void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3458 }
3459 
3460 static void
usb_ac_release_access(usb_ac_state_t * uacp)3461 usb_ac_release_access(usb_ac_state_t *uacp)
3462 {
3463 	usb_release_access(uacp->usb_ac_ser_acc);
3464 }
3465 
3466 
3467 static void
usb_ac_pm_busy_component(usb_ac_state_t * usb_ac_statep)3468 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
3469 {
3470 	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3471 
3472 	if (usb_ac_statep->usb_ac_pm != NULL) {
3473 		mutex_enter(&usb_ac_statep->usb_ac_mutex);
3474 		usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
3475 
3476 		USB_DPRINTF_L4(PRINT_MASK_PM,
3477 		    usb_ac_statep->usb_ac_log_handle,
3478 		    "usb_ac_pm_busy_component: %d",
3479 		    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3480 
3481 		mutex_exit(&usb_ac_statep->usb_ac_mutex);
3482 
3483 		if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
3484 		    DDI_SUCCESS) {
3485 			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3486 			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3487 
3488 			USB_DPRINTF_L2(PRINT_MASK_PM,
3489 			    usb_ac_statep->usb_ac_log_handle,
3490 			    "usb_ac_pm_busy_component failed: %d",
3491 			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3492 
3493 			mutex_exit(&usb_ac_statep->usb_ac_mutex);