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