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