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