Home | History | Annotate | Download | only in usb_as
      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 Streams Interface Driver:
     28  *
     29  * usb_as is responsible for (1) Processing audio data messages during
     30  * play and record and management of isoc pipe, (2) Selecting correct
     31  * alternate that matches a set of parameters and management of control pipe.
     32  * This driver is opened by usb_ac and interacts with usb_ac synchronously
     33  * using ioctls. If the processing involves an async USBA command, the ioctl
     34  * returns after completion of the command.
     35  *
     36  * Note: When there is a play/record, usb_as calls framework routines
     37  * directly for data (play) or sends data to mixer (record).
     38  *
     39  * Serialization: A competing thread can't be allowed to interfere with
     40  * (1) pipe, (2) streams state.
     41  * So we need some kind of serialization among the asynchronous
     42  * threads that can run in the driver. The serialization is mostly
     43  * needed to avoid races among open/close/events/power entry points
     44  * etc. Once a routine grabs access, if checks if the resource (pipe or
     45  * stream or dev state) is still accessible. If so, it proceeds with
     46  * its job and until it completes, no other thread requiring the same
     47  * resource can run.
     48  *
     49  * PM Model in usb_as: Raise power during attach and lower power in detach.
     50  * If device is not fully powered, synchronous raise power in wsrv entry points.
     51  */
     52 #include <sys/usb/usba/usbai_version.h>
     53 #include <sys/usb/usba.h>
     54 #include <sys/ddi.h>
     55 #include <sys/sunddi.h>
     56 
     57 #include <sys/audio/audio_driver.h>
     58 
     59 #include <sys/usb/clients/audio/usb_audio.h>
     60 #include <sys/usb/clients/audio/usb_mixer.h>
     61 #include <sys/usb/clients/audio/usb_as/usb_as.h>
     62 #include <sys/usb/clients/audio/usb_ac/usb_ac.h>
     63 
     64 
     65 /* debug support */
     66 uint_t	usb_as_errlevel	= USB_LOG_L4;
     67 uint_t	usb_as_errmask	= (uint_t)-1;
     68 uint_t	usb_as_instance_debug = (uint_t)-1;
     69 
     70 /*
     71  * Module linkage routines for the kernel
     72  */
     73 static int	usb_as_attach(dev_info_t *, ddi_attach_cmd_t);
     74 static int	usb_as_detach(dev_info_t *, ddi_detach_cmd_t);
     75 static int	usb_as_power(dev_info_t *, int, int);
     76 static int	usb_as_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
     77 
     78 static int usb_as_open(dev_t *, int, int, cred_t *);
     79 static int usb_as_close(dev_t, int, int, cred_t *);
     80 
     81 
     82 /* support functions */
     83 static void	usb_as_cleanup(dev_info_t *, usb_as_state_t *);
     84 
     85 static int	usb_as_handle_descriptors(usb_as_state_t *);
     86 static void	usb_as_prepare_registration_data(usb_as_state_t *);
     87 static int	usb_as_valid_format(usb_as_state_t *, uint_t,
     88 				uint_t *, uint_t);
     89 static void	usb_as_free_alts(usb_as_state_t *);
     90 
     91 static void	usb_as_create_pm_components(dev_info_t *, usb_as_state_t *);
     92 static int	usb_as_disconnect_event_cb(dev_info_t *);
     93 static int	usb_as_reconnect_event_cb(dev_info_t *);
     94 static int	usb_as_cpr_suspend(dev_info_t *);
     95 static void	usb_as_cpr_resume(dev_info_t *);
     96 
     97 static int	usb_as_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
     98 
     99 static int	usb_as_pwrlvl0(usb_as_state_t *);
    100 static int	usb_as_pwrlvl1(usb_as_state_t *);
    101 static int	usb_as_pwrlvl2(usb_as_state_t *);
    102 static int	usb_as_pwrlvl3(usb_as_state_t *);
    103 static void	usb_as_pm_busy_component(usb_as_state_t *);
    104 static void	usb_as_pm_idle_component(usb_as_state_t *);
    105 
    106 static void	usb_as_restore_device_state(dev_info_t *, usb_as_state_t *);
    107 static int	usb_as_setup(usb_as_state_t *);
    108 static void	usb_as_teardown(usb_as_state_t *);
    109 static int	usb_as_start_play(usb_as_state_t *, usb_audio_play_req_t *);
    110 static void	usb_as_continue_play(usb_as_state_t *);
    111 static void	usb_as_pause_play(usb_as_state_t *);
    112 
    113 static int	usb_as_set_format(usb_as_state_t *, usb_audio_formats_t *);
    114 static int	usb_as_set_sample_freq(usb_as_state_t *, int);
    115 static int	usb_as_send_ctrl_cmd(usb_as_state_t *, uchar_t, uchar_t,
    116 			ushort_t, ushort_t, ushort_t, mblk_t *, boolean_t);
    117 
    118 static int	usb_as_start_record(usb_as_state_t *, void *);
    119 static int	usb_as_stop_record(usb_as_state_t *);
    120 static void	usb_as_play_cb(usb_pipe_handle_t, usb_isoc_req_t *);
    121 static void	usb_as_record_cb(usb_pipe_handle_t, usb_isoc_req_t *);
    122 static void	usb_as_play_exc_cb(usb_pipe_handle_t, usb_isoc_req_t  *);
    123 static void	usb_as_record_exc_cb(usb_pipe_handle_t, usb_isoc_req_t	*);
    124 static int	usb_as_get_pktsize(usb_as_state_t *, usb_audio_formats_t *,
    125 			usb_frame_number_t);
    126 static void	usb_as_handle_shutdown(usb_as_state_t *);
    127 static int	usb_as_play_isoc_data(usb_as_state_t *,
    128 			usb_audio_play_req_t *);
    129 
    130 /* anchor for soft state structures */
    131 static void	*usb_as_statep;
    132 
    133 
    134 /*
    135  * DDI Structures
    136  */
    137 
    138 /* Entry points structure */
    139 static struct cb_ops usb_as_cb_ops = {
    140 	usb_as_open,		/* cb_open */
    141 	usb_as_close,		/* cb_close */
    142 	nodev,			/* cb_strategy */
    143 	nodev,			/* cb_print */
    144 	nodev,			/* cb_dump */
    145 	nodev,			/* cb_read */
    146 	nodev,			/* cb_write */
    147 	usb_as_ioctl,		/* cb_ioctl */
    148 	nodev,			/* cb_devmap */
    149 	nodev,			/* cb_mmap */
    150 	nodev,			/* cb_segmap */
    151 	nochpoll,		/* cb_chpoll */
    152 	ddi_prop_op,		/* cb_prop_op */
    153 	NULL,			/* cb_str */
    154 	D_MP | D_64BIT,		/* cb_flag */
    155 	CB_REV,			/* cb_rev */
    156 	nodev,			/* cb_aread */
    157 	nodev,			/* cb_arwite */
    158 };
    159 
    160 /* Device operations structure */
    161 static struct dev_ops usb_as_dev_ops = {
    162 	DEVO_REV,		/* devo_rev */
    163 	0,			/* devo_refcnt */
    164 	usb_as_getinfo,		/* devo_getinfo */
    165 	nulldev,		/* devo_identify - obsolete */
    166 	nulldev,		/* devo_probe - not needed */
    167 	usb_as_attach,		/* devo_attach */
    168 	usb_as_detach,		/* devo_detach */
    169 	nodev,			/* devo_reset */
    170 	&usb_as_cb_ops,		/* devi_cb_ops */
    171 	NULL,			/* devo_busb_as_ops */
    172 	usb_as_power,		/* devo_power */
    173 	ddi_quiesce_not_needed,	/* devo_quiesce */
    174 };
    175 
    176 /* Linkage structure for loadable drivers */
    177 static struct modldrv usb_as_modldrv = {
    178 	&mod_driverops,			/* drv_modops */
    179 	"USB Audio Streaming Driver",	/* drv_linkinfo */
    180 	&usb_as_dev_ops			/* drv_dev_ops */
    181 };
    182 
    183 /* Module linkage structure */
    184 static struct modlinkage usb_as_modlinkage = {
    185 	MODREV_1,			/* ml_rev */
    186 	(void *)&usb_as_modldrv,	/* ml_linkage */
    187 	NULL				/* NULL terminates the list */
    188 };
    189 
    190 
    191 static usb_event_t usb_as_events = {
    192 	usb_as_disconnect_event_cb,
    193 	usb_as_reconnect_event_cb,
    194 	NULL, NULL
    195 };
    196 
    197 /*
    198  * Mixer registration Management
    199  *	use defaults as much as possible
    200  */
    201 
    202 /* default sample rates that must be supported */
    203 static uint_t usb_as_default_srs[] = {
    204 	8000,	9600, 11025, 16000, 18900, 22050,
    205 	32000,	33075, 37800, 44100, 48000, 0
    206 };
    207 
    208 _NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
    209 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_isoc_req_t))
    210 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_isoc_pkt_descr))
    211 
    212 int
    213 _init(void)
    214 {
    215 	int rval;
    216 
    217 	/* initialize the soft state */
    218 	if ((rval = ddi_soft_state_init(&usb_as_statep,
    219 	    sizeof (usb_as_state_t), 1)) != DDI_SUCCESS) {
    220 
    221 		return (rval);
    222 	}
    223 
    224 	if ((rval = mod_install(&usb_as_modlinkage)) != 0) {
    225 		ddi_soft_state_fini(&usb_as_statep);
    226 	}
    227 
    228 	return (rval);
    229 }
    230 
    231 
    232 int
    233 _fini(void)
    234 {
    235 	int rval;
    236 
    237 	if ((rval = mod_remove(&usb_as_modlinkage)) == 0) {
    238 		/* Free the soft state internal structures */
    239 		ddi_soft_state_fini(&usb_as_statep);
    240 	}
    241 
    242 	return (rval);
    243 }
    244 
    245 
    246 int
    247 _info(struct modinfo *modinfop)
    248 {
    249 	return (mod_info(&usb_as_modlinkage, modinfop));
    250 }
    251 
    252 
    253 /*ARGSUSED*/
    254 static int
    255 usb_as_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd,
    256 			void *arg, void **result)
    257 {
    258 	usb_as_state_t	*uasp = NULL;
    259 	int		error = DDI_FAILURE;
    260 	int		instance = USB_AS_MINOR_TO_INSTANCE(
    261 	    getminor((dev_t)arg));
    262 
    263 	switch (infocmd) {
    264 	case DDI_INFO_DEVT2DEVINFO:
    265 
    266 		if ((uasp = ddi_get_soft_state(usb_as_statep,
    267 		    instance)) != NULL) {
    268 			*result = uasp->usb_as_dip;
    269 			if (*result != NULL) {
    270 				error = DDI_SUCCESS;
    271 			}
    272 		} else {
    273 			*result = NULL;
    274 		}
    275 		break;
    276 	case DDI_INFO_DEVT2INSTANCE:
    277 		*result = (void *)(uintptr_t)instance;
    278 		error = DDI_SUCCESS;
    279 		break;
    280 	default:
    281 		break;
    282 	}
    283 
    284 	return (error);
    285 }
    286 
    287 
    288 static int
    289 usb_as_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
    290 {
    291 	int			instance = ddi_get_instance(dip);
    292 	usb_as_state_t		*uasp;
    293 
    294 	switch (cmd) {
    295 		case DDI_ATTACH:
    296 
    297 			break;
    298 		case DDI_RESUME:
    299 			usb_as_cpr_resume(dip);
    300 
    301 			return (DDI_SUCCESS);
    302 		default:
    303 
    304 			return (DDI_FAILURE);
    305 	}
    306 
    307 	/*
    308 	 * Allocate soft state information.
    309 	 */
    310 	if (ddi_soft_state_zalloc(usb_as_statep, instance) != DDI_SUCCESS) {
    311 
    312 		return (DDI_FAILURE);
    313 	}
    314 
    315 	/*
    316 	 * get soft state space and initialize
    317 	 */
    318 	uasp = (usb_as_state_t *)ddi_get_soft_state(usb_as_statep, instance);
    319 	if (uasp == NULL) {
    320 
    321 		return (DDI_FAILURE);
    322 	}
    323 
    324 	uasp->usb_as_log_handle = usb_alloc_log_hdl(dip, "as",
    325 	    &usb_as_errlevel,
    326 	    &usb_as_errmask, &usb_as_instance_debug, 0);
    327 
    328 	uasp->usb_as_instance = instance;
    329 	uasp->usb_as_dip = dip;
    330 
    331 	(void) snprintf(uasp->dstr, sizeof (uasp->dstr), "%s#%d",
    332 	    ddi_driver_name(dip), instance);
    333 
    334 	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
    335 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
    336 		    "usb_client_attach failed");
    337 
    338 		usb_free_log_hdl(uasp->usb_as_log_handle);
    339 		ddi_soft_state_free(usb_as_statep, uasp->usb_as_instance);
    340 
    341 		return (DDI_FAILURE);
    342 	}
    343 
    344 	if (usb_get_dev_data(dip, &uasp->usb_as_dev_data,
    345 	    USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
    346 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
    347 		    "usb_get_dev_data failed");
    348 		usb_client_detach(dip, NULL);
    349 		usb_free_log_hdl(uasp->usb_as_log_handle);
    350 		ddi_soft_state_free(usb_as_statep, uasp->usb_as_instance);
    351 
    352 		return (DDI_FAILURE);
    353 	}
    354 
    355 	/* initialize mutex */
    356 	mutex_init(&uasp->usb_as_mutex, NULL, MUTEX_DRIVER,
    357 	    uasp->usb_as_dev_data->dev_iblock_cookie);
    358 
    359 	cv_init(&uasp->usb_as_pipe_cv, NULL, CV_DRIVER, NULL);
    360 
    361 	uasp->usb_as_ser_acc = usb_init_serialization(dip,
    362 	    USB_INIT_SER_CHECK_SAME_THREAD);
    363 
    364 	uasp->usb_as_default_ph = uasp->usb_as_dev_data->dev_default_ph;
    365 	uasp->usb_as_isoc_pp.pp_max_async_reqs = 1;
    366 
    367 	/* parse all descriptors */
    368 	if (usb_as_handle_descriptors(uasp) != USB_SUCCESS) {
    369 
    370 		goto fail;
    371 	}
    372 
    373 	usb_free_descr_tree(dip, uasp->usb_as_dev_data);
    374 
    375 	if ((ddi_create_minor_node(dip, "usb_as", S_IFCHR,
    376 	    USB_AS_CONSTRUCT_MINOR(instance),
    377 	    NULL, 0)) != DDI_SUCCESS) {
    378 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
    379 		    "usb_as_attach: couldn't create minor node");
    380 
    381 		goto fail;
    382 	}
    383 
    384 	/* we are online */
    385 	uasp->usb_as_dev_state = USB_DEV_ONLINE;
    386 
    387 	/* create components to power manage this device */
    388 	usb_as_create_pm_components(dip, uasp);
    389 
    390 	/* Register for events */
    391 	if (usb_register_event_cbs(dip, &usb_as_events, 0) != USB_SUCCESS) {
    392 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
    393 		    "usb_as_attach: couldn't register for events");
    394 
    395 		goto fail;
    396 	}
    397 
    398 	/* report device */
    399 	ddi_report_dev(dip);
    400 
    401 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
    402 	    "usb_as_attach: End");
    403 
    404 	return (DDI_SUCCESS);
    405 
    406 fail:
    407 	if (uasp) {
    408 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
    409 		    "attach failed");
    410 		usb_as_cleanup(dip, uasp);
    411 	}
    412 
    413 	return (DDI_FAILURE);
    414 }
    415 
    416 
    417 /*ARGSUSED*/
    418 static int
    419 usb_as_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    420 {
    421 	int instance = ddi_get_instance(dip);
    422 	usb_as_state_t	*uasp;
    423 	int rval;
    424 
    425 	uasp = ddi_get_soft_state(usb_as_statep, instance);
    426 
    427 	switch (cmd) {
    428 	case DDI_DETACH:
    429 		usb_as_cleanup(dip, uasp);
    430 
    431 		return (DDI_SUCCESS);
    432 	case DDI_SUSPEND:
    433 		rval = usb_as_cpr_suspend(dip);
    434 
    435 		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
    436 	default:
    437 
    438 		return (DDI_FAILURE);
    439 	}
    440 }
    441 
    442 
    443 static void
    444 usb_as_cleanup(dev_info_t *dip, usb_as_state_t *uasp)
    445 {
    446 	usb_as_power_t	*uaspm;
    447 
    448 	if (uasp == NULL) {
    449 
    450 		return;
    451 	}
    452 
    453 	uaspm = uasp->usb_as_pm;
    454 
    455 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    456 	    "usb_as_cleanup: uaspm=0x%p", (void *)uaspm);
    457 
    458 	if (uasp->usb_as_isoc_ph) {
    459 		usb_pipe_close(dip, uasp->usb_as_isoc_ph,
    460 		    USB_FLAGS_SLEEP, NULL, NULL);
    461 	}
    462 	/*
    463 	 * Disable the event callbacks first, after this point, event
    464 	 * callbacks will never get called. Note we shouldn't hold
    465 	 * mutex while unregistering events because there may be a
    466 	 * competing event callback thread. Event callbacks are done
    467 	 * with ndi mutex held and this can cause a potential deadlock.
    468 	 */
    469 	usb_unregister_event_cbs(dip, &usb_as_events);
    470 
    471 	mutex_enter(&uasp->usb_as_mutex);
    472 
    473 	if (uaspm && (uasp->usb_as_dev_state != USB_DEV_DISCONNECTED)) {
    474 		if (uaspm->aspm_wakeup_enabled) {
    475 			mutex_exit(&uasp->usb_as_mutex);
    476 
    477 			/*
    478 			 * We need to raise power first because
    479 			 * we need to send down a command to disable
    480 			 * remote wakeup
    481 			 */
    482 			usb_as_pm_busy_component(uasp);
    483 			(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
    484 
    485 			if (usb_handle_remote_wakeup(dip,
    486 			    USB_REMOTE_WAKEUP_DISABLE)) {
    487 				USB_DPRINTF_L2(PRINT_MASK_ALL,
    488 				    uasp->usb_as_log_handle,
    489 				    "disable remote wake up failed");
    490 			}
    491 			usb_as_pm_idle_component(uasp);
    492 		} else {
    493 			mutex_exit(&uasp->usb_as_mutex);
    494 		}
    495 
    496 		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
    497 
    498 		mutex_enter(&uasp->usb_as_mutex);
    499 	}
    500 
    501 	if (uaspm) {
    502 		kmem_free(uaspm, sizeof (usb_as_power_t));
    503 		uasp->usb_as_pm = NULL;
    504 	}
    505 
    506 	usb_client_detach(dip, uasp->usb_as_dev_data);
    507 
    508 	usb_as_free_alts(uasp);
    509 
    510 	mutex_exit(&uasp->usb_as_mutex);
    511 	mutex_destroy(&uasp->usb_as_mutex);
    512 
    513 	usb_fini_serialization(uasp->usb_as_ser_acc);
    514 
    515 	ddi_remove_minor_node(dip, NULL);
    516 	usb_free_log_hdl(uasp->usb_as_log_handle);
    517 	ddi_soft_state_free(usb_as_statep, uasp->usb_as_instance);
    518 
    519 	ddi_prop_remove_all(dip);
    520 }
    521 
    522 
    523 /*
    524  * usb_as_open:
    525  *	Open entry point for plumbing only
    526  */
    527 /*ARGSUSED*/
    528 static int
    529 usb_as_open(dev_t *devp, int flag, int otyp, cred_t *credp)
    530 {
    531 	int		inst = USB_AS_MINOR_TO_INSTANCE(getminor(*devp));
    532 	usb_as_state_t	*uasp = ddi_get_soft_state(usb_as_statep, inst);
    533 
    534 	if (uasp == NULL) {
    535 
    536 		return (ENXIO);
    537 	}
    538 
    539 	/* Do mux plumbing stuff */
    540 	USB_DPRINTF_L4(PRINT_MASK_OPEN, uasp->usb_as_log_handle,
    541 	    "usb_as_open: start");
    542 
    543 	mutex_enter(&uasp->usb_as_mutex);
    544 
    545 	if (uasp->usb_as_flag == USB_AS_OPEN || credp != kcred) {
    546 		USB_DPRINTF_L2(PRINT_MASK_OPEN, uasp->usb_as_log_handle,
    547 		    "usb_as_open:multiple opens or opens from userspace"
    548 		    " not supported");
    549 
    550 		mutex_exit(&uasp->usb_as_mutex);
    551 
    552 		return (ENXIO);
    553 	}
    554 
    555 	/* fail open on a disconnected device */
    556 	if (uasp->usb_as_dev_state == USB_DEV_DISCONNECTED) {
    557 		USB_DPRINTF_L2(PRINT_MASK_OPEN, uasp->usb_as_log_handle,
    558 		    "usb_as_open: disconnected");
    559 		mutex_exit(&uasp->usb_as_mutex);
    560 
    561 		return (ENODEV);
    562 	}
    563 
    564 	/* Initialize state */
    565 	uasp->usb_as_flag = USB_AS_OPEN;
    566 	mutex_exit(&uasp->usb_as_mutex);
    567 
    568 	/*
    569 	 * go to full power, and remain pm_busy till close
    570 	 */
    571 	usb_as_pm_busy_component(uasp);
    572 	(void) pm_raise_power(uasp->usb_as_dip, 0, USB_DEV_OS_FULL_PWR);
    573 
    574 	USB_DPRINTF_L4(PRINT_MASK_OPEN, uasp->usb_as_log_handle,
    575 	    "usb_as_open:done");
    576 
    577 	return (0);
    578 }
    579 
    580 
    581 /*
    582  * usb_as_close:
    583  *	Close entry point for plumbing
    584  */
    585 /*ARGSUSED*/
    586 static int
    587 usb_as_close(dev_t dev, int flag, int otyp, cred_t *credp)
    588 {
    589 	int		inst = USB_AS_MINOR_TO_INSTANCE(getminor(dev));
    590 	usb_as_state_t	*uasp = ddi_get_soft_state(usb_as_statep, inst);
    591 
    592 	USB_DPRINTF_L4(PRINT_MASK_CLOSE, uasp->usb_as_log_handle,
    593 	    "usb_as_close: inst=%d", inst);
    594 
    595 	mutex_enter(&uasp->usb_as_mutex);
    596 	uasp->usb_as_flag = USB_AS_DISMANTLING;
    597 	mutex_exit(&uasp->usb_as_mutex);
    598 
    599 	/*
    600 	 * Avoid races with other routines.
    601 	 * For example, if a control transfer is going on, wait
    602 	 * for that to be completed
    603 	 * At this point default pipe cannot be open.
    604 	 */
    605 	(void) usb_serialize_access(uasp->usb_as_ser_acc, USB_WAIT, 0);
    606 
    607 	usb_release_access(uasp->usb_as_ser_acc);
    608 
    609 	/* we can now power down */
    610 	usb_as_pm_idle_component(uasp);
    611 
    612 	mutex_enter(&uasp->usb_as_mutex);
    613 	uasp->usb_as_flag = 0;
    614 	mutex_exit(&uasp->usb_as_mutex);
    615 
    616 	return (0);
    617 }
    618 
    619 
    620 /*
    621  *
    622  */
    623 /*ARGSUSED*/
    624 static int
    625 usb_as_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
    626     int *rvalp)
    627 {
    628 	int		inst = USB_AS_MINOR_TO_INSTANCE(getminor(dev));
    629 	usb_as_state_t	*uasp = ddi_get_soft_state(usb_as_statep, inst);
    630 	int		rv = USB_SUCCESS;
    631 
    632 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    633 	    "usb_as_ioctl: Begin inst=%d, cmd=0x%x, arg=0x%p",
    634 	    inst, cmd, (void *)arg);
    635 
    636 	if (!(mode & FKIOCTL)) {
    637 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    638 		    "usb_as_ioctl: inst=%d, user space not supported", inst);
    639 		return (ENXIO);
    640 	}
    641 
    642 	mutex_enter(&uasp->usb_as_mutex);
    643 
    644 	switch (cmd) {
    645 	case USB_AUDIO_MIXER_REGISTRATION:
    646 		USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    647 		    "usb_as_ioctl(mixer reg): inst=%d", inst);
    648 
    649 		/*
    650 		 * Copy the usb_as_reg structure to the structure
    651 		 * that usb_ac passed. Note that this is a structure
    652 		 * assignment and not a pointer assignment!
    653 		 */
    654 		*(usb_as_registration_t *)arg = uasp->usb_as_reg;
    655 
    656 		break;
    657 	case USB_AUDIO_SET_FORMAT:
    658 		rv = usb_as_set_format(uasp, (usb_audio_formats_t *)arg);
    659 		break;
    660 	case USB_AUDIO_SET_SAMPLE_FREQ:
    661 		rv = usb_as_set_sample_freq(uasp, *(int *)arg);
    662 		break;
    663 	case USB_AUDIO_SETUP:
    664 		rv = usb_as_setup(uasp);
    665 		break;
    666 	case USB_AUDIO_TEARDOWN:
    667 		usb_as_teardown(uasp);
    668 		break;
    669 	case USB_AUDIO_START_PLAY:
    670 		rv = usb_as_start_play(uasp, (usb_audio_play_req_t *)arg);
    671 		break;
    672 	case USB_AUDIO_STOP_PLAY:
    673 	case USB_AUDIO_PAUSE_PLAY:
    674 		usb_as_pause_play(uasp);
    675 		break;
    676 	case USB_AUDIO_START_RECORD:
    677 		rv = usb_as_start_record(uasp, (void *)arg);
    678 		break;
    679 	case USB_AUDIO_STOP_RECORD:
    680 		rv = usb_as_stop_record(uasp);
    681 		break;
    682 	default:
    683 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    684 		    "usb_as_ioctl: unknown IOCTL, cmd=%d", cmd);
    685 		break;
    686 	}
    687 
    688 	mutex_exit(&uasp->usb_as_mutex);
    689 
    690 	return (rv == USB_SUCCESS ? 0 : ENXIO);
    691 }
    692 
    693 
    694 /*
    695  * usb_as_set_sample_freq:
    696  *	Sets the sample freq by sending a control command to interface
    697  *	Although not required for continuous sample rate devices, some
    698  *	devices such as plantronics devices do need this.
    699  *	On the other hand, the TI chip which does not support continuous
    700  *	sample rate stalls on this request
    701  *	Therefore, we ignore errors and carry on regardless
    702  */
    703 static int
    704 usb_as_set_sample_freq(usb_as_state_t *uasp, int freq)
    705 {
    706 	int	alt, ep;
    707 	mblk_t	*data;
    708 	int	rval = USB_FAILURE;
    709 	boolean_t ignore_errors;
    710 
    711 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
    712 
    713 	alt = uasp->usb_as_alternate;
    714 
    715 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    716 	    "usb_as_set_sample_freq: inst=%d cont_sr=%d freq=%d",
    717 	    ddi_get_instance(uasp->usb_as_dip),
    718 	    uasp->usb_as_alts[alt].alt_continuous_sr, freq);
    719 
    720 	ignore_errors = B_TRUE;
    721 
    722 	ep = uasp->usb_as_alts[alt].alt_ep->bEndpointAddress;
    723 
    724 	data = allocb(4, BPRI_HI);
    725 	if (data) {
    726 		*(data->b_wptr++) = (char)freq;
    727 		*(data->b_wptr++) = (char)(freq >> 8);
    728 		*(data->b_wptr++) = (char)(freq >> 16);
    729 
    730 		mutex_exit(&uasp->usb_as_mutex);
    731 
    732 		if ((rval = usb_as_send_ctrl_cmd(uasp,
    733 		    USB_DEV_REQ_HOST_TO_DEV |
    734 		    USB_DEV_REQ_TYPE_CLASS |
    735 		    USB_DEV_REQ_RCPT_EP,		/* bmRequestType */
    736 		    USB_AUDIO_SET_CUR,			/* bRequest */
    737 		    USB_AUDIO_SAMPLING_FREQ_CONTROL << 8, /* wValue */
    738 		    ep,					/* wIndex */
    739 		    3,					/* wLength */
    740 		    data,
    741 		    ignore_errors)) != USB_SUCCESS) {
    742 			USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    743 			    "usb_as_set_sample_freq: set sample freq failed");
    744 		}
    745 		mutex_enter(&uasp->usb_as_mutex);
    746 	}
    747 	freemsg(data);
    748 
    749 	return (rval);
    750 }
    751 
    752 
    753 /*
    754  * usb_as_set_format:
    755  *	Matches channel, encoding and precision and find out
    756  *	the right alternate. Sets alternate interface and returns it.
    757  */
    758 static int
    759 usb_as_set_format(usb_as_state_t *uasp, usb_audio_formats_t *format)
    760 {
    761 	int		n;
    762 	usb_as_registration_t *reg;
    763 	int		alt, rval;
    764 	uint_t		interface;
    765 
    766 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
    767 
    768 	if (uasp->usb_as_request_count) {
    769 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    770 		    "usb_as_set_format: failing inst=%d, rq_cnt=%d",
    771 		    ddi_get_instance(uasp->usb_as_dip),
    772 		    uasp->usb_as_request_count);
    773 
    774 		return (USB_FAILURE);
    775 	}
    776 
    777 	reg = &uasp->usb_as_reg;
    778 	interface = uasp->usb_as_ifno;
    779 
    780 	uasp->usb_as_curr_format = *format;
    781 
    782 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    783 	    "usb_as_set_format: inst=%d, reg=0x%p, format=0x%p",
    784 	    ddi_get_instance(uasp->usb_as_dip), (void *)reg, (void *)format);
    785 
    786 	for (n = 0; n < reg->reg_n_formats; n++) {
    787 		if ((format->fmt_chns == reg->reg_formats[n].fmt_chns) &&
    788 		    (format->fmt_precision == reg->reg_formats[n].
    789 		    fmt_precision) && (format->fmt_encoding ==
    790 		    reg->reg_formats[n].fmt_encoding)) {
    791 			/*
    792 			 * Found the alternate
    793 			 */
    794 			uasp->usb_as_alternate = alt =
    795 			    reg->reg_formats[n].fmt_alt;
    796 			break;
    797 		}
    798 	}
    799 
    800 	if (n >= reg->reg_n_formats) {
    801 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    802 		    "usb_as_set_format: Didn't find a matching alt");
    803 
    804 		return (USB_FAILURE);
    805 	}
    806 
    807 
    808 	USB_DPRINTF_L3(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    809 	    "usb_as_set_format: interface=%d alternate=%d",
    810 	    interface, alt);
    811 
    812 	mutex_exit(&uasp->usb_as_mutex);
    813 
    814 	rval = usb_as_send_ctrl_cmd(uasp,
    815 					/* bmRequestType */
    816 	    USB_DEV_REQ_HOST_TO_DEV | USB_DEV_REQ_RCPT_IF,
    817 	    USB_REQ_SET_IF,		/* bRequest */
    818 	    alt,			/* wValue */
    819 	    interface,			/* wIndex */
    820 	    0,				/* wLength */
    821 	    NULL, B_FALSE);
    822 
    823 	mutex_enter(&uasp->usb_as_mutex);
    824 
    825 	if (rval != USB_SUCCESS) {
    826 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    827 		    "usb_as_set_format: set_alternate failed");
    828 	} else {
    829 		format->fmt_alt = (uchar_t)alt;
    830 	}
    831 
    832 	return (rval);
    833 }
    834 
    835 
    836 /*
    837  * usb_as_setup:
    838  *	Open isoc pipe. Will hang around till bandwidth
    839  *	is available.
    840  */
    841 static int
    842 usb_as_setup(usb_as_state_t *uasp)
    843 {
    844 	int alt = uasp->usb_as_alternate;
    845 	usb_ep_descr_t *ep = (usb_ep_descr_t *)uasp->usb_as_alts[alt].alt_ep;
    846 	int rval;
    847 
    848 
    849 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
    850 
    851 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    852 	    "usb_as_setup: Begin usb_as_setup, inst=%d",
    853 	    ddi_get_instance(uasp->usb_as_dip));
    854 
    855 
    856 	/* Set record packet size to max packet size */
    857 	if (uasp->usb_as_alts[alt].alt_mode == USB_AUDIO_RECORD) {
    858 		uasp->usb_as_record_pkt_size = ep->wMaxPacketSize;
    859 	} else {
    860 		uasp->usb_as_record_pkt_size = 0;
    861 	}
    862 
    863 	if (uasp->usb_as_isoc_ph != NULL) {
    864 		while (uasp->usb_as_request_count) {
    865 			cv_wait(&uasp->usb_as_pipe_cv,
    866 			    &uasp->usb_as_mutex);
    867 		}
    868 
    869 		/* close the isoc pipe which is opened before */
    870 		mutex_exit(&uasp->usb_as_mutex);
    871 		usb_pipe_close(uasp->usb_as_dip, uasp->usb_as_isoc_ph,
    872 		    USB_FLAGS_SLEEP, NULL, (usb_opaque_t)NULL);
    873 
    874 		mutex_enter(&uasp->usb_as_mutex);
    875 		uasp->usb_as_isoc_ph = NULL;
    876 	}
    877 
    878 	ASSERT(uasp->usb_as_request_count == 0);
    879 	mutex_exit(&uasp->usb_as_mutex);
    880 
    881 	/* open isoc pipe, may fail if there is no bandwidth  */
    882 	rval = usb_pipe_open(uasp->usb_as_dip, ep, &uasp->usb_as_isoc_pp,
    883 	    USB_FLAGS_SLEEP, &uasp->usb_as_isoc_ph);
    884 
    885 	if (rval != USB_SUCCESS) {
    886 		switch (rval) {
    887 		case USB_NO_BANDWIDTH:
    888 			USB_DPRINTF_L0(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    889 			    "no bandwidth available");
    890 			break;
    891 		case USB_NOT_SUPPORTED:
    892 			USB_DPRINTF_L0(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    893 			    "Operating a full/high speed audio device on a "
    894 			    "high speed port is not supported");
    895 			break;
    896 		default:
    897 			USB_DPRINTF_L2(PRINT_MASK_ALL,
    898 			    uasp->usb_as_log_handle,
    899 			    "usb_as_setup: isoc pipe open failed (%d)",
    900 			    rval);
    901 		}
    902 
    903 		mutex_enter(&uasp->usb_as_mutex);
    904 
    905 		return (USB_FAILURE);
    906 	}
    907 
    908 	(void) usb_pipe_set_private(uasp->usb_as_isoc_ph, (usb_opaque_t)uasp);
    909 
    910 	mutex_enter(&uasp->usb_as_mutex);
    911 	uasp->usb_as_audio_state = USB_AS_IDLE;
    912 	uasp->usb_as_setup_cnt++;
    913 
    914 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    915 	    "usb_as_setup: End");
    916 
    917 	return (USB_SUCCESS);
    918 }
    919 
    920 
    921 /*
    922  * usb_as_teardown
    923  *
    924  */
    925 static void
    926 usb_as_teardown(usb_as_state_t *uasp)
    927 {
    928 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    929 	    "usb_as_teardown: Begin inst=%d",
    930 	    ddi_get_instance(uasp->usb_as_dip));
    931 
    932 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
    933 
    934 	uasp->usb_as_audio_state = USB_AS_IDLE;
    935 
    936 	ASSERT(uasp->usb_as_isoc_ph);
    937 	/* reset setup flag */
    938 	uasp->usb_as_setup_cnt--;
    939 
    940 
    941 	ASSERT(uasp->usb_as_setup_cnt == 0);
    942 
    943 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    944 	    "usb_as_teardown: End");
    945 }
    946 
    947 
    948 /*
    949  * usb_as_start_play
    950  */
    951 static int
    952 usb_as_start_play(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
    953 {
    954 	int		n_requests;
    955 	int		rval = USB_FAILURE;
    956 
    957 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    958 	    "usb_as_start_play: Begin inst=%d, req_cnt=%d",
    959 	    ddi_get_instance(uasp->usb_as_dip), uasp->usb_as_request_count);
    960 
    961 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
    962 
    963 	uasp->usb_as_request_samples = play_req->up_samples;
    964 	uasp->usb_as_ahdl = play_req->up_handle;
    965 	uasp->usb_as_audio_state = USB_AS_ACTIVE;
    966 
    967 	if ((uasp->usb_as_request_count >= USB_AS_MAX_REQUEST_COUNT) ||
    968 	    (uasp->usb_as_audio_state == USB_AS_IDLE) ||
    969 	    (uasp->usb_as_audio_state == USB_AS_PLAY_PAUSED)) {
    970 		USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    971 		    "nothing to do or paused or idle (%d)",
    972 		    uasp->usb_as_audio_state);
    973 		rval = USB_SUCCESS;
    974 	} else {
    975 		USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    976 		    "usb_as_start_play: samples=%d requestcount=%d ",
    977 		    uasp->usb_as_request_samples, uasp->usb_as_request_count);
    978 
    979 		/* queue up as many requests as allowed */
    980 		for (n_requests = uasp->usb_as_request_count;
    981 		    n_requests < USB_AS_MAX_REQUEST_COUNT; n_requests++) {
    982 			if ((rval = usb_as_play_isoc_data(uasp, play_req)) !=
    983 			    USB_SUCCESS) {
    984 				break;
    985 			}
    986 		}
    987 	}
    988 
    989 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
    990 	    "usb_as_start_play: End");
    991 
    992 	return (rval);
    993 }
    994 
    995 
    996 /*
    997  * usb_as_continue_play:
    998  *	this function is called from the play callbacks
    999  */
   1000 static void
   1001 usb_as_continue_play(usb_as_state_t *uasp)
   1002 {
   1003 	int		n_requests;
   1004 
   1005 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1006 	    "usb_as_contine_play: Begin req_cnt=%d",
   1007 	    uasp->usb_as_request_count);
   1008 
   1009 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
   1010 
   1011 	if (uasp->usb_as_dev_state == USB_DEV_DISCONNECTED) {
   1012 		usb_as_handle_shutdown(uasp);
   1013 
   1014 		return;
   1015 	}
   1016 
   1017 	if ((uasp->usb_as_request_count >= USB_AS_MAX_REQUEST_COUNT) ||
   1018 	    (uasp->usb_as_audio_state == USB_AS_IDLE) ||
   1019 	    (uasp->usb_as_audio_state == USB_AS_PLAY_PAUSED)) {
   1020 		USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1021 		    "usb_as_continue_play: nothing to do (audio_state=%d)",
   1022 		    uasp->usb_as_audio_state);
   1023 	} else {
   1024 		USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1025 		    "usb_as_continue_play: samples=%d requestcount=%d ",
   1026 		    uasp->usb_as_request_samples, uasp->usb_as_request_count);
   1027 
   1028 		/* queue up as many requests as allowed */
   1029 		for (n_requests = uasp->usb_as_request_count;
   1030 		    n_requests < USB_AS_MAX_REQUEST_COUNT; n_requests++) {
   1031 			if (usb_as_play_isoc_data(uasp, NULL) !=
   1032 			    USB_SUCCESS) {
   1033 
   1034 				break;
   1035 			}
   1036 		}
   1037 	}
   1038 
   1039 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1040 	    "usb_as_continue_play: End");
   1041 }
   1042 
   1043 
   1044 static void
   1045 usb_as_handle_shutdown(usb_as_state_t *uasp)
   1046 {
   1047 	void	*ahdl;
   1048 
   1049 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1050 	    "usb_as_handle_shutdown, inst=%d",
   1051 	    ddi_get_instance(uasp->usb_as_dip));
   1052 
   1053 	USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1054 	    "usb_as_handle_shutdown: am_play_shutdown");
   1055 
   1056 	uasp->usb_as_audio_state = USB_AS_IDLE;
   1057 	uasp->usb_as_pkt_count = 0;
   1058 	ahdl = uasp->usb_as_ahdl;
   1059 
   1060 	mutex_exit(&uasp->usb_as_mutex);
   1061 	usb_ac_stop_play(ahdl, NULL);
   1062 	mutex_enter(&uasp->usb_as_mutex);
   1063 }
   1064 
   1065 
   1066 static int
   1067 usb_as_play_isoc_data(usb_as_state_t *uasp, usb_audio_play_req_t *play_req)
   1068 {
   1069 	int		rval = USB_FAILURE;
   1070 
   1071 	usb_isoc_req_t *isoc_req = NULL;
   1072 	usb_audio_formats_t *format = &uasp->usb_as_curr_format;
   1073 	mblk_t		*data = NULL;
   1074 	void *	ahdl = uasp->usb_as_ahdl;
   1075 	int		precision;
   1076 	int		pkt, frame, n, n_pkts, count;
   1077 	size_t		bufsize;
   1078 	int		pkt_len[USB_AS_N_FRAMES];
   1079 
   1080 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
   1081 
   1082 	/* we only support two precisions */
   1083 	if ((format->fmt_precision != USB_AUDIO_PRECISION_8) &&
   1084 	    (format->fmt_precision != USB_AUDIO_PRECISION_16)) {
   1085 
   1086 		rval = USB_FAILURE;
   1087 
   1088 		goto done;
   1089 	}
   1090 
   1091 	precision = (format->fmt_precision == USB_AUDIO_PRECISION_8) ? 1 : 2;
   1092 
   1093 	frame = uasp->usb_as_pkt_count;
   1094 
   1095 	/*
   1096 	 * calculate total bufsize by determining the pkt size for
   1097 	 * each frame
   1098 	 */
   1099 	for (bufsize = pkt = 0; pkt < USB_AS_N_FRAMES; pkt++) {
   1100 		pkt_len[pkt] = usb_as_get_pktsize(uasp, format, frame++);
   1101 		bufsize += pkt_len[pkt];
   1102 	}
   1103 
   1104 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1105 	    "usb_as_play_isoc_data: Begin bufsize=0x%lx, inst=%d", bufsize,
   1106 	    ddi_get_instance(uasp->usb_as_dip));
   1107 
   1108 	mutex_exit(&uasp->usb_as_mutex);
   1109 
   1110 	if ((data = allocb(bufsize, BPRI_HI)) == NULL) {
   1111 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1112 		    "usb_as_play_isoc_data: allocb failed");
   1113 		mutex_enter(&uasp->usb_as_mutex);
   1114 
   1115 		goto done;
   1116 	}
   1117 
   1118 	/*
   1119 	 * restriction of Boomer: cannot call usb_ac_get_audio() in the context
   1120 	 * of start so we play a fragment of silence at first
   1121 	 */
   1122 	if (play_req != NULL) {
   1123 		bzero(data->b_wptr, bufsize);
   1124 		count = bufsize / precision;
   1125 
   1126 	} else if ((count = usb_ac_get_audio(ahdl, (void *)data->b_wptr,
   1127 	    bufsize / precision)) == 0) {
   1128 		mutex_enter(&uasp->usb_as_mutex);
   1129 		if (uasp->usb_as_request_count == 0) {
   1130 			usb_as_handle_shutdown(uasp);
   1131 
   1132 			/* Don't return failure for 0 bytes of data sent */
   1133 			if (play_req) {
   1134 				/*
   1135 				 * Since we set rval to SUCCESS
   1136 				 * we treat it as a special case
   1137 				 * and free data here
   1138 				 */
   1139 				rval = USB_SUCCESS;
   1140 				freemsg(data);
   1141 				data = NULL;
   1142 
   1143 				goto done;
   1144 			}
   1145 		} else {
   1146 			USB_DPRINTF_L2(PRINT_MASK_ALL,
   1147 			    uasp->usb_as_log_handle,
   1148 			    "usb_as_play_isoc_data: no audio bytes, "
   1149 			    "rcnt=0x%x ", uasp->usb_as_request_count);
   1150 		}
   1151 		rval = USB_FAILURE;
   1152 
   1153 		goto done;
   1154 	}
   1155 
   1156 	bufsize = n = count * precision;
   1157 	data->b_wptr += n;
   1158 
   1159 	/* calculate how many frames we can actually fill */
   1160 	for (n_pkts = 0; (n_pkts < USB_AS_N_FRAMES) && (n > 0); n_pkts++) {
   1161 		if (n < pkt_len[n_pkts]) {
   1162 			pkt_len[n_pkts] = n;
   1163 		}
   1164 		n -= pkt_len[n_pkts];
   1165 	}
   1166 
   1167 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1168 	    "usb_as_play_isoc_data: n_pkts=%d, bufsize=%ld, n=%d",
   1169 	    n_pkts, bufsize, count * precision);
   1170 
   1171 	/* allocate an isoc request packet */
   1172 	if ((isoc_req = usb_alloc_isoc_req(uasp->usb_as_dip,
   1173 	    n_pkts, 0, 0)) == NULL) {
   1174 		mutex_enter(&uasp->usb_as_mutex);
   1175 
   1176 		goto done;
   1177 	}
   1178 
   1179 
   1180 
   1181 	/* initialize the packet descriptor */
   1182 	for (pkt = 0; pkt < n_pkts; pkt++) {
   1183 		isoc_req->isoc_pkt_descr[pkt].isoc_pkt_length =
   1184 		    pkt_len[pkt];
   1185 	}
   1186 
   1187 	isoc_req->isoc_data		= data;
   1188 	isoc_req->isoc_pkts_count	= (ushort_t)n_pkts;
   1189 	isoc_req->isoc_attributes	= USB_ATTRS_ISOC_XFER_ASAP |
   1190 	    USB_ATTRS_AUTOCLEARING;
   1191 	isoc_req->isoc_cb		= usb_as_play_cb;
   1192 	isoc_req->isoc_exc_cb		= usb_as_play_exc_cb;
   1193 	isoc_req->isoc_client_private	= (usb_opaque_t)uasp;
   1194 
   1195 	mutex_enter(&uasp->usb_as_mutex);
   1196 
   1197 	USB_DPRINTF_L3(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1198 	    "usb_as_play_isoc_data: rq=0x%p data=0x%p cnt=0x%x "
   1199 	    "pkt=0x%p rqcnt=%d ", (void *)isoc_req, (void *)data, count,
   1200 	    (void *)isoc_req->isoc_pkt_descr, uasp->usb_as_request_count);
   1201 
   1202 	ASSERT(isoc_req->isoc_data != NULL);
   1203 
   1204 	uasp->usb_as_send_debug_count++;
   1205 	uasp->usb_as_request_count++;
   1206 	uasp->usb_as_pkt_count += n_pkts;
   1207 	mutex_exit(&uasp->usb_as_mutex);
   1208 
   1209 	if ((rval = usb_pipe_isoc_xfer(uasp->usb_as_isoc_ph,
   1210 	    isoc_req, 0)) != USB_SUCCESS) {
   1211 
   1212 		mutex_enter(&uasp->usb_as_mutex);
   1213 		uasp->usb_as_request_count--;
   1214 		cv_signal(&uasp->usb_as_pipe_cv);
   1215 		uasp->usb_as_send_debug_count--;
   1216 		uasp->usb_as_pkt_count -= n_pkts;
   1217 
   1218 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1219 		    "usb_as_play_isoc_data: rval=%d", rval);
   1220 
   1221 		rval = USB_FAILURE;
   1222 
   1223 	} else {
   1224 		mutex_enter(&uasp->usb_as_mutex);
   1225 
   1226 		data = NULL;
   1227 		isoc_req = NULL;
   1228 	}
   1229 
   1230 done:
   1231 	if (rval != USB_SUCCESS) {
   1232 		freemsg(data);
   1233 		if (isoc_req) {
   1234 			isoc_req->isoc_data = NULL;
   1235 			usb_free_isoc_req(isoc_req);
   1236 		}
   1237 	}
   1238 
   1239 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1240 	    "usb_as_play_isoc_data: SEND CNT=%d, RCV COUNT=%d",
   1241 	    uasp->usb_as_send_debug_count, uasp->usb_as_rcv_debug_count);
   1242 
   1243 	return (rval);
   1244 }
   1245 
   1246 
   1247 static void
   1248 usb_as_pause_play(usb_as_state_t *uasp)
   1249 {
   1250 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
   1251 
   1252 	/* this will stop the isoc request in the play callback */
   1253 	uasp->usb_as_audio_state = USB_AS_PLAY_PAUSED;
   1254 }
   1255 
   1256 
   1257 /*ARGSUSED*/
   1258 static void
   1259 usb_as_play_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
   1260 {
   1261 	usb_as_state_t *uasp = (usb_as_state_t *)
   1262 	    (isoc_req->isoc_client_private);
   1263 	int i;
   1264 
   1265 	USB_DPRINTF_L4(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1266 	    "usb_as_play_cb: Begin ph=0x%p, isoc_req=0x%p",
   1267 	    (void *)ph, (void *)isoc_req);
   1268 
   1269 	ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) != 0);
   1270 
   1271 	for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
   1272 		if (isoc_req->isoc_pkt_descr[i].isoc_pkt_status !=
   1273 		    USB_CR_OK) {
   1274 			USB_DPRINTF_L2(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1275 			    "usb_as_play_cb: \tpkt%d: len=%d status=%s", i,
   1276 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
   1277 			    usb_str_cr(isoc_req->
   1278 			    isoc_pkt_descr[i].isoc_pkt_status));
   1279 		}
   1280 	}
   1281 
   1282 	mutex_enter(&uasp->usb_as_mutex);
   1283 	if (isoc_req->isoc_error_count) {
   1284 		USB_DPRINTF_L2(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1285 		    "usb_as_play_cb: error_count = %d",
   1286 		    isoc_req->isoc_error_count);
   1287 	}
   1288 
   1289 	usb_free_isoc_req(isoc_req);
   1290 	uasp->usb_as_request_count--;
   1291 	cv_signal(&uasp->usb_as_pipe_cv);
   1292 	uasp->usb_as_rcv_debug_count++;
   1293 	usb_as_continue_play(uasp);
   1294 
   1295 	USB_DPRINTF_L4(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1296 	    "usb_as_play_cb: SEND CNT=%d, RCV COUNT=%d",
   1297 	    uasp->usb_as_send_debug_count, uasp->usb_as_rcv_debug_count);
   1298 
   1299 	USB_DPRINTF_L4(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1300 	    "usb_as_play_cb: End, req_cnt=%d", uasp->usb_as_request_count);
   1301 
   1302 	mutex_exit(&uasp->usb_as_mutex);
   1303 }
   1304 
   1305 
   1306 static void
   1307 usb_as_play_exc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
   1308 {
   1309 	int i;
   1310 	usb_as_state_t	*uasp = (usb_as_state_t *)
   1311 	    (isoc_req->isoc_client_private);
   1312 	usb_cr_t	cr = isoc_req->isoc_completion_reason;
   1313 	usb_cb_flags_t	cb_flags = isoc_req->isoc_cb_flags;
   1314 
   1315 	USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1316 	    "usb_as_play_exc_cb: ph=0x%p, rq=0x%p data=0x%p pkts=0x%x "
   1317 	    "cr=%d, cb_flag=0x%x", (void *)ph, (void *)isoc_req,
   1318 	    (void *)isoc_req->isoc_data, isoc_req->isoc_pkts_count,
   1319 	    cr, cb_flags);
   1320 
   1321 	ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) == 0);
   1322 
   1323 	for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
   1324 		if (isoc_req->isoc_pkt_descr[i].isoc_pkt_status ==
   1325 		    USB_CR_OK) {
   1326 			USB_DPRINTF_L2(PRINT_MASK_ALL,
   1327 			    uasp->usb_as_log_handle,
   1328 			    "usb_as_play_exc_cb: \tpkt%d: len=%d status=%d",
   1329 			    i,
   1330 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
   1331 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_status);
   1332 		}
   1333 	}
   1334 
   1335 	usb_free_isoc_req(isoc_req);
   1336 
   1337 	mutex_enter(&uasp->usb_as_mutex);
   1338 	uasp->usb_as_rcv_debug_count++;
   1339 	uasp->usb_as_request_count--;
   1340 	cv_signal(&uasp->usb_as_pipe_cv);
   1341 	usb_as_handle_shutdown(uasp);
   1342 
   1343 	USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1344 	    "usb_as_play_exc_cb: SEND CNT=%d, RCV COUNT=%d",
   1345 	    uasp->usb_as_send_debug_count, uasp->usb_as_rcv_debug_count);
   1346 
   1347 	USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1348 	    "usb_as_play_exc_cb: End request_count=%d",
   1349 	    uasp->usb_as_request_count);
   1350 
   1351 	mutex_exit(&uasp->usb_as_mutex);
   1352 }
   1353 
   1354 
   1355 /*
   1356  * usb_as_start_record
   1357  */
   1358 static int
   1359 usb_as_start_record(usb_as_state_t *uasp, void * ahdl)
   1360 {
   1361 	int		rval = USB_FAILURE;
   1362 	usb_isoc_req_t *isoc_req;
   1363 	ushort_t	record_pkt_size = uasp->usb_as_record_pkt_size;
   1364 	ushort_t	n_pkt = 1, pkt;
   1365 
   1366 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1367 	    "usb_as_start_record: inst=%d",
   1368 	    ddi_get_instance(uasp->usb_as_dip));
   1369 
   1370 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
   1371 
   1372 	/*
   1373 	 * A start_record should not happen when stop polling is
   1374 	 * happening
   1375 	 */
   1376 	ASSERT(uasp->usb_as_audio_state != USB_AS_STOP_POLLING_STARTED);
   1377 
   1378 	if (uasp->usb_as_audio_state == USB_AS_IDLE) {
   1379 
   1380 		uasp->usb_as_ahdl = ahdl;
   1381 		uasp->usb_as_audio_state = USB_AS_ACTIVE;
   1382 		mutex_exit(&uasp->usb_as_mutex);
   1383 
   1384 		if ((isoc_req = usb_alloc_isoc_req(uasp->usb_as_dip, n_pkt,
   1385 		    n_pkt * record_pkt_size, 0)) != NULL) {
   1386 			/* Initialize the packet descriptor */
   1387 			for (pkt = 0; pkt < n_pkt; pkt++) {
   1388 				isoc_req->isoc_pkt_descr[pkt].
   1389 				    isoc_pkt_length = record_pkt_size;
   1390 			}
   1391 
   1392 			isoc_req->isoc_pkts_count = n_pkt;
   1393 			isoc_req->isoc_pkts_length = record_pkt_size;
   1394 			isoc_req->isoc_attributes = USB_ATTRS_ISOC_XFER_ASAP |
   1395 			    USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING;
   1396 			isoc_req->isoc_cb = usb_as_record_cb;
   1397 			isoc_req->isoc_exc_cb = usb_as_record_exc_cb;
   1398 			isoc_req->isoc_client_private = (usb_opaque_t)uasp;
   1399 
   1400 			rval = usb_pipe_isoc_xfer(uasp->usb_as_isoc_ph,
   1401 			    isoc_req, 0);
   1402 
   1403 		} else {
   1404 			USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1405 			    "usb_as_start_record: Isoc req allocation failed");
   1406 		}
   1407 
   1408 		mutex_enter(&uasp->usb_as_mutex);
   1409 
   1410 	} else {
   1411 
   1412 		USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1413 		    "usb_as_start_record: Record in progress");
   1414 
   1415 		rval = USB_SUCCESS;
   1416 	}
   1417 
   1418 	if (rval != USB_SUCCESS) {
   1419 		uasp->usb_as_audio_state = USB_AS_IDLE;
   1420 		if (isoc_req) {
   1421 			usb_free_isoc_req(isoc_req);
   1422 			isoc_req = NULL;
   1423 		}
   1424 	}
   1425 
   1426 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1427 	    "usb_as_start_record: rval=%d", rval);
   1428 
   1429 	return (rval);
   1430 }
   1431 
   1432 
   1433 static int
   1434 usb_as_stop_record(usb_as_state_t *uasp)
   1435 {
   1436 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1437 	    "usb_as_stop_record: ");
   1438 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
   1439 
   1440 	/* if we are disconnected, the pipe will be closed anyways */
   1441 	if (uasp->usb_as_dev_state == USB_DEV_DISCONNECTED)
   1442 		return (USB_SUCCESS);
   1443 
   1444 	switch (uasp->usb_as_audio_state) {
   1445 	case USB_AS_ACTIVE:
   1446 		mutex_exit(&uasp->usb_as_mutex);
   1447 
   1448 		/*
   1449 		 * Stop polling. When the completion reason indicate that
   1450 		 * polling is over, return response message up.
   1451 		 */
   1452 		usb_pipe_stop_isoc_polling(uasp->usb_as_isoc_ph,
   1453 		    USB_FLAGS_SLEEP);
   1454 		mutex_enter(&uasp->usb_as_mutex);
   1455 
   1456 		break;
   1457 	case USB_AS_STOP_POLLING_STARTED:
   1458 		/* A stop polling in progress, wait for completion and reply */
   1459 		break;
   1460 	default:
   1461 		break;
   1462 	}
   1463 
   1464 	return (USB_SUCCESS);
   1465 }
   1466 
   1467 
   1468 static void
   1469 usb_as_record_exc_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
   1470 {
   1471 	usb_as_state_t	*uasp = (usb_as_state_t *)
   1472 	    (isoc_req->isoc_client_private);
   1473 	usb_cr_t	completion_reason;
   1474 	int		rval;
   1475 
   1476 	completion_reason = isoc_req->isoc_completion_reason;
   1477 
   1478 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1479 	    "usb_as_record_exc_cb: ph=0x%p, isoc_req=0x%p, cr=%d",
   1480 	    (void *)ph, (void *)isoc_req, completion_reason);
   1481 
   1482 	ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) == 0);
   1483 
   1484 	switch (completion_reason) {
   1485 	case USB_CR_STOPPED_POLLING:
   1486 	case USB_CR_PIPE_CLOSING:
   1487 	case USB_CR_PIPE_RESET:
   1488 
   1489 		break;
   1490 	case USB_CR_NO_RESOURCES:
   1491 		/*
   1492 		 * keep the show going: Since we have the original
   1493 		 * request, we just resubmit it
   1494 		 */
   1495 		rval = usb_pipe_isoc_xfer(uasp->usb_as_isoc_ph, isoc_req, 0);
   1496 
   1497 		USB_DPRINTF_L3(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1498 		    "usb_as_record_exc_cb: restart record rval=%d", rval);
   1499 
   1500 		return;
   1501 	default:
   1502 
   1503 		mutex_enter(&uasp->usb_as_mutex);
   1504 
   1505 		/* Do not start if one is already in progress */
   1506 		if (uasp->usb_as_audio_state != USB_AS_STOP_POLLING_STARTED) {
   1507 			uasp->usb_as_audio_state = USB_AS_STOP_POLLING_STARTED;
   1508 
   1509 			mutex_exit(&uasp->usb_as_mutex);
   1510 			(void) usb_pipe_stop_isoc_polling(ph,
   1511 			    USB_FLAGS_NOSLEEP);
   1512 
   1513 			return;
   1514 		} else {
   1515 			mutex_exit(&uasp->usb_as_mutex);
   1516 		}
   1517 
   1518 		break;
   1519 	}
   1520 	usb_free_isoc_req(isoc_req);
   1521 
   1522 	mutex_enter(&uasp->usb_as_mutex);
   1523 	USB_DPRINTF_L3(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1524 	    "usb_as_record_exc_cb: state=%d cr=0x%x",
   1525 	    uasp->usb_as_audio_state, completion_reason);
   1526 
   1527 	uasp->usb_as_audio_state = USB_AS_IDLE;
   1528 	mutex_exit(&uasp->usb_as_mutex);
   1529 }
   1530 
   1531 
   1532 /*ARGSUSED*/
   1533 static void
   1534 usb_as_record_cb(usb_pipe_handle_t ph, usb_isoc_req_t *isoc_req)
   1535 {
   1536 	usb_as_state_t *uasp = (usb_as_state_t *)isoc_req->isoc_client_private;
   1537 	int		i, offset, sz;
   1538 	void *	ahdl;
   1539 	usb_audio_formats_t *format = &uasp->usb_as_curr_format;
   1540 	int		precision;
   1541 
   1542 	USB_DPRINTF_L4(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1543 	    "usb_as_record_cb: rq=0x%p data=0x%p pkts=0x%x",
   1544 	    (void *)isoc_req, (void *)isoc_req->isoc_data,
   1545 	    isoc_req->isoc_pkts_count);
   1546 
   1547 	USB_DPRINTF_L4(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1548 	    "\tfno=%" PRId64 ", n_pkts=%u, flag=0x%x, data=0x%p, cnt=%d",
   1549 	    isoc_req->isoc_frame_no, isoc_req->isoc_pkts_count,
   1550 	    isoc_req->isoc_attributes, (void *)isoc_req->isoc_data,
   1551 	    isoc_req->isoc_error_count);
   1552 
   1553 	ASSERT((isoc_req->isoc_cb_flags & USB_CB_INTR_CONTEXT) != 0);
   1554 
   1555 	mutex_enter(&uasp->usb_as_mutex);
   1556 	ahdl = uasp->usb_as_ahdl;
   1557 	sz = uasp->usb_as_record_pkt_size;
   1558 	precision = (format->fmt_precision == USB_AUDIO_PRECISION_8) ? 1 : 2;
   1559 
   1560 	if (uasp->usb_as_audio_state != USB_AS_IDLE) {
   1561 		for (offset = i = 0; i < isoc_req->isoc_pkts_count; i++) {
   1562 			USB_DPRINTF_L3(PRINT_MASK_CB, uasp->usb_as_log_handle,
   1563 			    "\tpkt%d: "
   1564 			    "offset=%d pktsize=%d len=%d status=%d resid=%d",
   1565 			    i, offset, sz,
   1566 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
   1567 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_status,
   1568 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length);
   1569 
   1570 			if (isoc_req->isoc_pkt_descr[i].isoc_pkt_status !=
   1571 			    USB_CR_OK) {
   1572 				USB_DPRINTF_L2(PRINT_MASK_CB,
   1573 				    uasp->usb_as_log_handle,
   1574 				    "record: pkt=%d offset=0x%x status=%s",
   1575 				    i, offset, usb_str_cr(isoc_req->
   1576 				    isoc_pkt_descr[i].isoc_pkt_status));
   1577 			}
   1578 			mutex_exit(&uasp->usb_as_mutex);
   1579 
   1580 			usb_ac_send_audio(ahdl,
   1581 			    isoc_req->isoc_data->b_rptr + offset,
   1582 			    isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length /
   1583 			    precision);
   1584 
   1585 			mutex_enter(&uasp->usb_as_mutex);
   1586 			offset += isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
   1587 		}
   1588 	}
   1589 
   1590 	mutex_exit(&uasp->usb_as_mutex);
   1591 
   1592 	usb_free_isoc_req(isoc_req);
   1593 }
   1594 
   1595 
   1596 /*
   1597  * Support for sample rates that are not multiple of 1K. We have 3 such
   1598  * sample rates: 11025, 22050 and 44100.
   1599  */
   1600 typedef struct usb_as_pktsize_table {
   1601 	uint_t		sr;
   1602 	ushort_t	pkt;
   1603 	ushort_t	cycle;
   1604 	int		extra;
   1605 } usb_as_pktsize_table_t;
   1606 
   1607 /*
   1608  * usb_as_pktsize_info is the table that calculates the pktsize
   1609  * corresponding to the current frame and the current format.
   1610  * Since the int_rate is 1000, we have to do special arithmetic for
   1611  * sample rates not multiple of 1K. For example,
   1612  * if the sample rate is 48000(i.e multiple of 1K), we can send 48000/1000
   1613  * = 48 samples every packet per channel. Since we have to support sample
   1614  * rate like 11025, 22050 and 44100, we will have some extra samples
   1615  * at the end that we need to spread among the 1000 cycles. So if we make
   1616  * the pktsize as below for these sample rates, at the end of 1000 cycles,
   1617  * we will be able to send all the data in the correct rate:
   1618  *
   1619  * 11025: 39 samples of 11, 1 of 12
   1620  * 22050: 19 samples of 22, 1 of 23
   1621  * 44100: 9 samples of 44, 1 of 45
   1622  *
   1623  * frameno is a simple counter maintained in the soft state structure.
   1624  * So the pkt size is:
   1625  * pkt_size =  ((frameno %  cycle) ?  pkt : (pkt + extra));
   1626  *
   1627  */
   1628 static usb_as_pktsize_table_t usb_as_pktsize_info[] = {
   1629 	{8000,	8,	1000,	0},
   1630 	{9600,	10,	5,	-2},
   1631 	{11025,	11,	40,	1},
   1632 	{16000,	16,	1000,	0},
   1633 	{18900, 19,	10,	-1},
   1634 	{22050,	22,	20,	1},
   1635 	{32000,	32,	1000,	0},
   1636 	{33075, 33,	12,	1},
   1637 	{37800, 38,	5,	-1},
   1638 	{44100,	44,	10,	1},
   1639 	{48000, 48,	1000,	0},
   1640 	{ 0 }
   1641 };
   1642 
   1643 
   1644 static int
   1645 usb_as_get_pktsize(usb_as_state_t *uasp, usb_audio_formats_t *format,
   1646 	usb_frame_number_t frameno)
   1647 {
   1648 	int	n;
   1649 	int	pkt_size = 0;
   1650 	ushort_t pkt, cycle;
   1651 	int	extra;
   1652 	int	n_srs =
   1653 	    sizeof (usb_as_pktsize_info) / sizeof (usb_as_pktsize_table_t);
   1654 
   1655 	for (n = 0; n < n_srs; n++) {
   1656 		if (usb_as_pktsize_info[n].sr == format->fmt_sr) {
   1657 			cycle	= usb_as_pktsize_info[n].cycle;
   1658 			pkt	= usb_as_pktsize_info[n].pkt;
   1659 			extra	= usb_as_pktsize_info[n].extra;
   1660 			pkt_size = (((frameno + 1) % cycle) ?
   1661 			    pkt : (pkt + extra));
   1662 			pkt_size *= ((format->fmt_precision ==
   1663 			    USB_AUDIO_PRECISION_16) ? 2 : 1)
   1664 			    * format->fmt_chns;
   1665 			break;
   1666 		}
   1667 	}
   1668 
   1669 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1670 	    "usb_as_get_pktsize: %d", pkt_size);
   1671 
   1672 	return (pkt_size);
   1673 }
   1674 
   1675 
   1676 /*
   1677  * usb_as_send_ctrl_cmd:
   1678  *	Opens the pipe; sends a control command down
   1679  */
   1680 static int
   1681 usb_as_send_ctrl_cmd(usb_as_state_t *uasp,
   1682 	uchar_t	bmRequestType, uchar_t bRequest,
   1683 	ushort_t wValue, ushort_t wIndex, ushort_t wLength,
   1684 	mblk_t	*data, boolean_t ignore_errors)
   1685 {
   1686 	usb_ctrl_setup_t setup;
   1687 	usb_cr_t cr;
   1688 	usb_cb_flags_t cf;
   1689 
   1690 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1691 	    "usb_as_send_ctrl_cmd: Begin bmRequestType=%d,\n\t"
   1692 	    "bRequest=%d, wValue=%d, wIndex=%d, wLength=%d, data=0x%p",
   1693 	    bmRequestType, bRequest, wValue, wIndex, wLength, (void *)data);
   1694 
   1695 	setup.bmRequestType	= bmRequestType & ~USB_DEV_REQ_DEV_TO_HOST;
   1696 	setup.bRequest		= bRequest;
   1697 	setup.wValue		= wValue;
   1698 	setup.wIndex		= wIndex;
   1699 	setup.wLength		= wLength;
   1700 	setup.attrs		= 0;
   1701 
   1702 	if (usb_pipe_ctrl_xfer_wait(uasp->usb_as_default_ph, &setup, &data,
   1703 	    &cr, &cf, 0) != USB_SUCCESS) {
   1704 		USB_DPRINTF_L2(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   1705 		    "usb_as_send_ctrl_cmd: usba xfer failed (req=%d), "
   1706 		    "completion reason: 0x%x, completion flags: 0x%x",
   1707 		    bRequest, cr, cf);
   1708 
   1709 		return (ignore_errors ? USB_SUCCESS: USB_FAILURE);
   1710 	}
   1711 
   1712 	return (USB_SUCCESS);
   1713 }
   1714 
   1715 
   1716 /*
   1717  * Power management
   1718  */
   1719 
   1720 /*ARGSUSED*/
   1721 static void
   1722 usb_as_create_pm_components(dev_info_t *dip, usb_as_state_t *uasp)
   1723 {
   1724 	usb_as_power_t	*uaspm;
   1725 	uint_t		pwr_states;
   1726 
   1727 	USB_DPRINTF_L4(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1728 	    "usb_as_create_pm_components: begin");
   1729 
   1730 	/* Allocate the state structure */
   1731 	uaspm = kmem_zalloc(sizeof (usb_as_power_t), KM_SLEEP);
   1732 	uasp->usb_as_pm = uaspm;
   1733 	uaspm->aspm_state = uasp;
   1734 	uaspm->aspm_capabilities = 0;
   1735 	uaspm->aspm_current_power = USB_DEV_OS_FULL_PWR;
   1736 
   1737 	USB_DPRINTF_L3(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1738 	    "usb_as_pm_components: remote Wakeup enabled");
   1739 	if (usb_create_pm_components(dip, &pwr_states) ==
   1740 	    USB_SUCCESS) {
   1741 		if (usb_handle_remote_wakeup(dip,
   1742 		    USB_REMOTE_WAKEUP_ENABLE) != USB_SUCCESS) {
   1743 			USB_DPRINTF_L2(PRINT_MASK_PM,
   1744 			    uasp->usb_as_log_handle,
   1745 			    "enable remote wakeup failed");
   1746 		} else {
   1747 			uaspm->aspm_wakeup_enabled = 1;
   1748 		}
   1749 		uaspm->aspm_pwr_states = (uint8_t)pwr_states;
   1750 		(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
   1751 	}
   1752 
   1753 	USB_DPRINTF_L4(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1754 	    "usb_as_create_pm_components: end");
   1755 }
   1756 
   1757 
   1758 /*
   1759  * usb_as_power:
   1760  *	power entry point
   1761  */
   1762 static int
   1763 usb_as_power(dev_info_t *dip, int comp, int level)
   1764 {
   1765 	int		instance = ddi_get_instance(dip);
   1766 	usb_as_state_t	*uasp;
   1767 	usb_as_power_t	*uaspm;
   1768 	int		retval = USB_FAILURE;
   1769 
   1770 	uasp = ddi_get_soft_state(usb_as_statep, instance);
   1771 
   1772 	USB_DPRINTF_L4(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1773 	    "usb_as_power: comp=%d level=%d", comp, level);
   1774 
   1775 	(void) usb_serialize_access(uasp->usb_as_ser_acc, USB_WAIT, 0);
   1776 
   1777 	mutex_enter(&uasp->usb_as_mutex);
   1778 	uaspm = uasp->usb_as_pm;
   1779 
   1780 	if (USB_DEV_PWRSTATE_OK(uaspm->aspm_pwr_states, level)) {
   1781 		USB_DPRINTF_L2(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1782 		    "usb_as_power: illegal level=%d pwr_states=%d",
   1783 		    level, uaspm->aspm_pwr_states);
   1784 
   1785 		goto done;
   1786 	}
   1787 
   1788 	switch (level) {
   1789 	case USB_DEV_OS_PWR_OFF:
   1790 		retval = usb_as_pwrlvl0(uasp);
   1791 		break;
   1792 	case USB_DEV_OS_PWR_1:
   1793 		retval = usb_as_pwrlvl1(uasp);
   1794 		break;
   1795 	case USB_DEV_OS_PWR_2:
   1796 		retval = usb_as_pwrlvl2(uasp);
   1797 		break;
   1798 	case USB_DEV_OS_FULL_PWR:
   1799 		retval = usb_as_pwrlvl3(uasp);
   1800 		break;
   1801 	default:
   1802 		retval = USB_FAILURE;
   1803 		break;
   1804 	}
   1805 
   1806 done:
   1807 
   1808 	usb_release_access(uasp->usb_as_ser_acc);
   1809 	mutex_exit(&uasp->usb_as_mutex);
   1810 
   1811 	return ((retval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
   1812 }
   1813 
   1814 
   1815 /*
   1816  * functions to handle power transition for various levels
   1817  * These functions act as place holders to issue USB commands
   1818  * to the devices to change their power levels
   1819  * Level 0 = Device is powered off
   1820  * Level 3 = Device if full powered
   1821  * Level 1,2 = Intermediate power level of the device as implemented
   1822  *	by the hardware.
   1823  * Note that Level 0 is OS power-off and Level 3 is OS full-power.
   1824  */
   1825 static int
   1826 usb_as_pwrlvl0(usb_as_state_t *uasp)
   1827 {
   1828 	usb_as_power_t	*uaspm;
   1829 	int		rval;
   1830 
   1831 	uaspm = uasp->usb_as_pm;
   1832 
   1833 	switch (uasp->usb_as_dev_state) {
   1834 	case USB_DEV_ONLINE:
   1835 		/* Deny the powerdown request if the device is busy */
   1836 		if (uaspm->aspm_pm_busy != 0) {
   1837 
   1838 			return (USB_FAILURE);
   1839 		}
   1840 
   1841 		if (uasp->usb_as_audio_state != USB_AS_IDLE) {
   1842 
   1843 			return (USB_FAILURE);
   1844 		}
   1845 
   1846 		/* Issue USB D3 command to the device here */
   1847 		rval = usb_set_device_pwrlvl3(uasp->usb_as_dip);
   1848 		ASSERT(rval == USB_SUCCESS);
   1849 
   1850 		uasp->usb_as_dev_state = USB_DEV_PWRED_DOWN;
   1851 		uaspm->aspm_current_power = USB_DEV_OS_PWR_OFF;
   1852 
   1853 		/* FALLTHRU */
   1854 	case USB_DEV_DISCONNECTED:
   1855 	case USB_DEV_SUSPENDED:
   1856 		/* allow a disconnected/cpr'ed device to go to low power */
   1857 
   1858 		return (USB_SUCCESS);
   1859 	case USB_DEV_PWRED_DOWN:
   1860 	default:
   1861 		USB_DPRINTF_L2(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1862 		    "usb_as_pwrlvl0: Illegal dev_state");
   1863 
   1864 		return (USB_FAILURE);
   1865 	}
   1866 }
   1867 
   1868 
   1869 /* ARGSUSED */
   1870 static int
   1871 usb_as_pwrlvl1(usb_as_state_t *uasp)
   1872 {
   1873 	int		rval;
   1874 
   1875 	/* Issue USB D2 command to the device here */
   1876 	rval = usb_set_device_pwrlvl2(uasp->usb_as_dip);
   1877 	ASSERT(rval == USB_SUCCESS);
   1878 
   1879 	return (USB_FAILURE);
   1880 }
   1881 
   1882 
   1883 /* ARGSUSED */
   1884 static int
   1885 usb_as_pwrlvl2(usb_as_state_t *uasp)
   1886 {
   1887 	int		rval;
   1888 
   1889 	rval = usb_set_device_pwrlvl1(uasp->usb_as_dip);
   1890 	ASSERT(rval == USB_SUCCESS);
   1891 
   1892 	return (USB_FAILURE);
   1893 }
   1894 
   1895 
   1896 static int
   1897 usb_as_pwrlvl3(usb_as_state_t *uasp)
   1898 {
   1899 	usb_as_power_t	*uaspm;
   1900 	int		rval;
   1901 
   1902 	uaspm = uasp->usb_as_pm;
   1903 
   1904 	switch (uasp->usb_as_dev_state) {
   1905 	case USB_DEV_PWRED_DOWN:
   1906 
   1907 		/* Issue USB D0 command to the device here */
   1908 		rval = usb_set_device_pwrlvl0(uasp->usb_as_dip);
   1909 		ASSERT(rval == USB_SUCCESS);
   1910 
   1911 		uasp->usb_as_dev_state = USB_DEV_ONLINE;
   1912 		uaspm->aspm_current_power = USB_DEV_OS_FULL_PWR;
   1913 
   1914 		/* FALLTHRU */
   1915 	case USB_DEV_ONLINE:
   1916 		/* we are already in full power */
   1917 
   1918 		/* fall thru */
   1919 	case USB_DEV_DISCONNECTED:
   1920 	case USB_DEV_SUSPENDED:
   1921 		/* allow power change on a disconnected/cpr'ed device */
   1922 
   1923 		return (USB_SUCCESS);
   1924 	default:
   1925 		USB_DPRINTF_L2(PRINT_MASK_PM, uasp->usb_as_log_handle,
   1926 		    "usb_as_pwrlvl3: Illegal dev_state");
   1927 
   1928 		return (DDI_FAILURE);
   1929 	}
   1930 }
   1931 
   1932 
   1933 /*
   1934  * Descriptor Management
   1935  *
   1936  * usb_as_handle_descriptors:
   1937  *	read and parse all descriptors and build up usb_as_alts list
   1938  *
   1939  *	the order is as follows:
   1940  *	    interface, general, format, endpoint, CV endpoint
   1941  */
   1942 static int
   1943 usb_as_handle_descriptors(usb_as_state_t *uasp)
   1944 {
   1945 	usb_client_dev_data_t		*dev_data = uasp->usb_as_dev_data;
   1946 	int				interface = dev_data->dev_curr_if;
   1947 	uint_t				alternate;
   1948 	uint_t				n_alternates;
   1949 	int				len, i, n, n_srs, sr, index;
   1950 	int				rval = USB_SUCCESS;
   1951 	usb_if_descr_t			*if_descr;
   1952 	usb_audio_as_if_descr_t 	*general;
   1953 	usb_audio_type1_format_descr_t	*format;
   1954 	usb_ep_descr_t			*ep;
   1955 	usb_audio_as_isoc_ep_descr_t	*cs_ep;
   1956 	usb_if_data_t			*if_data;
   1957 	usb_alt_if_data_t		*altif_data;
   1958 	usb_ep_data_t			*ep_data;
   1959 
   1960 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   1961 	    "usb_as_handle_descriptors: cfg=%ld interface=%d",
   1962 	    (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]),
   1963 	    dev_data->dev_curr_if);
   1964 
   1965 	if_data = &dev_data->dev_curr_cfg->cfg_if[dev_data->dev_curr_if];
   1966 	uasp->usb_as_ifno = interface;
   1967 
   1968 	/*
   1969 	 * find the number of alternates for this interface
   1970 	 * and allocate an array to store the descriptors for
   1971 	 * each alternate
   1972 	 */
   1973 	uasp->usb_as_n_alternates = n_alternates = if_data->if_n_alt;
   1974 	uasp->usb_as_alts = kmem_zalloc((n_alternates) *
   1975 	    sizeof (usb_as_alt_descr_t), KM_SLEEP);
   1976 
   1977 	/*
   1978 	 * for each alternate read descriptors
   1979 	 */
   1980 	for (alternate = 0; alternate < n_alternates; alternate++) {
   1981 		altif_data = &if_data->if_alt[alternate];
   1982 
   1983 		uasp->usb_as_alts[alternate].alt_if =
   1984 		    kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP);
   1985 		if_descr = &altif_data->altif_descr;
   1986 
   1987 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   1988 		    "interface (%d.%d):\n\t"
   1989 		    "l = 0x%x type = 0x%x n = 0x%x alt = 0x%x #ep = 0x%x\n\t"
   1990 		    "iclass = 0x%x subclass = 0x%x proto = 0x%x string = 0x%x",
   1991 		    interface, alternate,
   1992 		    if_descr->bLength, if_descr->bDescriptorType,
   1993 		    if_descr->bInterfaceNumber, if_descr->bAlternateSetting,
   1994 		    if_descr->bNumEndpoints, if_descr->bInterfaceClass,
   1995 		    if_descr->bInterfaceSubClass,
   1996 		    if_descr->bInterfaceProtocol, if_descr->iInterface);
   1997 
   1998 		*(uasp->usb_as_alts[alternate].alt_if) = *if_descr;
   1999 
   2000 		/* read the general descriptor */
   2001 		index = 0;
   2002 
   2003 		if (altif_data->altif_cvs == NULL) {
   2004 
   2005 			continue;
   2006 		}
   2007 
   2008 		general = kmem_zalloc(sizeof (*general), KM_SLEEP);
   2009 
   2010 		len = usb_parse_data(AS_IF_DESCR_FORMAT,
   2011 		    altif_data->altif_cvs[index].cvs_buf,
   2012 		    altif_data->altif_cvs[index].cvs_buf_len,
   2013 		    (void *)general, sizeof (*general));
   2014 
   2015 		/* is this a sane header descriptor */
   2016 		if (!((len >= AS_IF_DESCR_SIZE) &&
   2017 		    (general->bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
   2018 		    (general->bDescriptorSubType == USB_AUDIO_AS_GENERAL))) {
   2019 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
   2020 			    uasp->usb_as_log_handle,
   2021 			    "invalid general cs interface descr");
   2022 
   2023 			kmem_free(general, sizeof (*general));
   2024 
   2025 			continue;
   2026 		}
   2027 
   2028 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2029 		    "general (%d.%d): type=0x%x subtype=0x%x termlink=0x%x\n\t"
   2030 		    "delay=0x%x format=0x%x",
   2031 		    interface, alternate,
   2032 		    general->bDescriptorType, general->bDescriptorSubType,
   2033 		    general->bTerminalLink, general->bDelay,
   2034 		    general->wFormatTag);
   2035 
   2036 		uasp->usb_as_alts[alternate].alt_general = general;
   2037 
   2038 		/*
   2039 		 * there should be one format descriptor of unknown size.
   2040 		 * the format descriptor contains just bytes, no need to
   2041 		 * parse
   2042 		 */
   2043 		index++;
   2044 		len = altif_data->altif_cvs[index].cvs_buf_len;
   2045 		format = kmem_zalloc(len, KM_SLEEP);
   2046 		bcopy(altif_data->altif_cvs[index].cvs_buf, format, len);
   2047 
   2048 		uasp->usb_as_alts[alternate].alt_format_len = (uchar_t)len;
   2049 
   2050 		/* is this a sane format descriptor */
   2051 		if (!((format->blength >= AUDIO_TYPE1_FORMAT_SIZE) &&
   2052 		    format->bDescriptorSubType == USB_AUDIO_AS_FORMAT_TYPE)) {
   2053 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
   2054 			    uasp->usb_as_log_handle,
   2055 			    "invalid format cs interface descr");
   2056 
   2057 			kmem_free(format, len);
   2058 
   2059 			continue;
   2060 		}
   2061 
   2062 		uasp->usb_as_alts[alternate].alt_format = format;
   2063 
   2064 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2065 		    "format (%d.%d): len = %d "
   2066 		    "type = 0x%x subtype = 0x%x format = 0x%x\n\t"
   2067 		    "#channels = 0x%x subframe = 0x%x resolution = 0x%x\n\t"
   2068 		    "sample freq type = 0x%x",
   2069 		    interface, alternate, len,
   2070 		    format->bDescriptorType,
   2071 		    format->bDescriptorSubType,
   2072 		    format->bFormatType,
   2073 		    format->bNrChannels,
   2074 		    format->bSubFrameSize,
   2075 		    format->bBitResolution,
   2076 		    format->bSamFreqType);
   2077 
   2078 		if (format->bSamFreqType == 0) {
   2079 			/* continuous sample rate limits */
   2080 			n_srs = 2;
   2081 			uasp->usb_as_alts[alternate].alt_continuous_sr++;
   2082 		} else {
   2083 			n_srs = format->bSamFreqType;
   2084 		}
   2085 
   2086 		uasp->usb_as_alts[alternate].alt_n_sample_rates =
   2087 		    (uchar_t)n_srs;
   2088 
   2089 		uasp->usb_as_alts[alternate].alt_sample_rates =
   2090 		    kmem_zalloc(n_srs * (sizeof (uint_t)), KM_SLEEP);
   2091 
   2092 		/* go thru all sample rates (3 bytes) each */
   2093 		for (i = 0, n = 0; n < n_srs; i += 3, n++) {
   2094 			sr = ((format->bSamFreqs[i+2] << 16) & 0xff0000) |
   2095 			    ((format->bSamFreqs[i+1] << 8) & 0xff00) |
   2096 			    (format->bSamFreqs[i] & 0xff);
   2097 
   2098 			USB_DPRINTF_L3(PRINT_MASK_ATTA,
   2099 			    uasp->usb_as_log_handle,
   2100 			    "sr = %d", sr);
   2101 
   2102 			uasp->usb_as_alts[alternate].
   2103 			    alt_sample_rates[n] = sr;
   2104 		}
   2105 
   2106 		if ((ep_data = usb_lookup_ep_data(uasp->usb_as_dip,
   2107 		    dev_data, interface, alternate, 0,
   2108 		    USB_EP_ATTR_ISOCH, USB_EP_DIR_IN)) == NULL) {
   2109 			if ((ep_data = usb_lookup_ep_data(uasp->usb_as_dip,
   2110 			    dev_data, interface, alternate, 0,
   2111 			    USB_EP_ATTR_ISOCH, USB_EP_DIR_OUT)) == NULL) {
   2112 
   2113 				USB_DPRINTF_L2(PRINT_MASK_ATTA,
   2114 				    uasp->usb_as_log_handle,
   2115 				    "no endpoint descriptor found");
   2116 
   2117 				continue;
   2118 			}
   2119 		}
   2120 		ep = &ep_data->ep_descr;
   2121 
   2122 		uasp->usb_as_alts[alternate].alt_ep =
   2123 		    kmem_zalloc(sizeof (usb_ep_descr_t), KM_SLEEP);
   2124 		*(uasp->usb_as_alts[alternate].alt_ep) = *ep;
   2125 
   2126 		USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2127 		    "endpoint (%d.%d):\n\t"
   2128 		    "len = 0x%x type = 0x%x add = 0x%x "
   2129 		    "attr = 0x%x mps = 0x%x\n\t"
   2130 		    "int = 0x%x",
   2131 		    interface, alternate,
   2132 		    ep->bLength, ep->bDescriptorType, ep->bEndpointAddress,
   2133 		    ep->bmAttributes, ep->wMaxPacketSize, ep->bInterval);
   2134 
   2135 		uasp->usb_as_alts[alternate].alt_mode  =
   2136 		    (ep->bEndpointAddress & USB_EP_DIR_IN) ?
   2137 		    USB_AUDIO_RECORD : USB_AUDIO_PLAY;
   2138 
   2139 		if (ep_data->ep_n_cvs == 0) {
   2140 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
   2141 			    uasp->usb_as_log_handle,
   2142 			    "no cv ep descriptor");
   2143 
   2144 			continue;
   2145 		}
   2146 
   2147 		cs_ep = kmem_zalloc(sizeof (*cs_ep), KM_SLEEP);
   2148 		len = usb_parse_data(AS_ISOC_EP_DESCR_FORMAT,
   2149 		    ep_data->ep_cvs[0].cvs_buf,
   2150 		    ep_data->ep_cvs[0].cvs_buf_len,
   2151 		    (void *)cs_ep, sizeof (*cs_ep));
   2152 
   2153 		if ((len < AS_ISOC_EP_DESCR_SIZE) ||
   2154 		    (cs_ep->bDescriptorType != USB_AUDIO_CS_ENDPOINT)) {
   2155 			USB_DPRINTF_L2(PRINT_MASK_ATTA,
   2156 			    uasp->usb_as_log_handle,
   2157 			    "cs endpoint descriptor invalid (%d)", len);
   2158 			kmem_free(cs_ep, sizeof (*cs_ep));
   2159 
   2160 			continue;
   2161 		}
   2162 
   2163 		USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2164 		    "cs isoc endpoint (%d.%d):\n\t"
   2165 		    "type=0x%x sub=0x%x attr=0x%x units=0x%x delay=%x",
   2166 		    interface, alternate,
   2167 		    cs_ep->bDescriptorType,
   2168 		    cs_ep->bDescriptorSubType,
   2169 		    cs_ep->bmAttributes,
   2170 		    cs_ep->bLockDelayUnits,
   2171 		    cs_ep->wLockDelay);
   2172 
   2173 		uasp->usb_as_alts[alternate].alt_cs_ep = cs_ep;
   2174 
   2175 		/* we are done */
   2176 		uasp->usb_as_alts[alternate].alt_valid++;
   2177 	}
   2178 
   2179 done:
   2180 	usb_as_prepare_registration_data(uasp);
   2181 
   2182 	return (rval);
   2183 }
   2184 
   2185 
   2186 /*
   2187  * usb_as_free_alts:
   2188  *	cleanup alternate list and deallocate all descriptors
   2189  */
   2190 static void
   2191 usb_as_free_alts(usb_as_state_t *uasp)
   2192 {
   2193 	int	alt;
   2194 	usb_as_alt_descr_t *altp;
   2195 
   2196 	if (uasp->usb_as_alts) {
   2197 		for (alt = 0; alt < uasp->usb_as_n_alternates; alt++) {
   2198 			altp = &uasp->usb_as_alts[alt];
   2199 			if (altp) {
   2200 				if (altp->alt_sample_rates) {
   2201 					kmem_free(altp->alt_sample_rates,
   2202 					    altp->alt_n_sample_rates *
   2203 					    sizeof (uint_t));
   2204 				}
   2205 				if (altp->alt_if) {
   2206 					kmem_free(altp->alt_if,
   2207 					    sizeof (usb_if_descr_t));
   2208 				}
   2209 				if (altp->alt_general) {
   2210 					kmem_free(altp->alt_general,
   2211 					    sizeof (usb_audio_as_if_descr_t));
   2212 				}
   2213 				if (altp->alt_format) {
   2214 					kmem_free(altp->alt_format,
   2215 					    altp->alt_format_len);
   2216 				}
   2217 				if (altp->alt_ep) {
   2218 					kmem_free(altp->alt_ep,
   2219 					    sizeof (usb_ep_descr_t));
   2220 				}
   2221 				if (altp->alt_cs_ep) {
   2222 					kmem_free(altp->alt_cs_ep,
   2223 					    sizeof (*altp->alt_cs_ep));
   2224 				}
   2225 			}
   2226 		}
   2227 		kmem_free(uasp->usb_as_alts, (uasp->usb_as_n_alternates) *
   2228 		    sizeof (usb_as_alt_descr_t));
   2229 	}
   2230 }
   2231 
   2232 
   2233 /*
   2234  * usb_as_prepare_registration_data
   2235  */
   2236 static void
   2237 usb_as_prepare_registration_data(usb_as_state_t   *uasp)
   2238 {
   2239 	usb_as_registration_t *reg = &uasp->usb_as_reg;
   2240 	usb_audio_type1_format_descr_t	*format;
   2241 	uchar_t n_alternates = uasp->usb_as_n_alternates;
   2242 	uchar_t channels[3];
   2243 	int alt, n;
   2244 
   2245 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2246 	    "usb_as_prepare_registration_data:");
   2247 
   2248 	/* there has to be at least two alternates, ie 0 and 1	*/
   2249 	if (n_alternates < 2) {
   2250 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2251 		    "not enough alternates %d", n_alternates);
   2252 
   2253 		return;
   2254 	}
   2255 
   2256 	reg->reg_ifno = uasp->usb_as_ifno;
   2257 	reg->reg_mode = uasp->usb_as_alts[1].alt_mode;
   2258 
   2259 	/* all endpoints need to have the same direction */
   2260 	for (alt = 2; alt < n_alternates; alt++) {
   2261 		if (!uasp->usb_as_alts[alt].alt_valid) {
   2262 			continue;
   2263 		}
   2264 		if (uasp->usb_as_alts[alt].alt_mode !=
   2265 		    reg->reg_mode) {
   2266 			USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2267 			    "alternates have different direction");
   2268 
   2269 			return;
   2270 		}
   2271 	}
   2272 
   2273 	/* copy over sample rate table	but zero it first */
   2274 	bzero(reg->reg_srs, sizeof (reg->reg_srs));
   2275 	bcopy(usb_as_default_srs, reg->reg_srs, sizeof (usb_as_default_srs));
   2276 
   2277 	channels[1] = channels[2] = 0;
   2278 
   2279 	/*
   2280 	 * we assume that alternate 0 is not interesting (no bandwidth),
   2281 	 * we check all formats and use the formats that we can support
   2282 	 */
   2283 	for (alt = 1, n = 0; alt < n_alternates; alt++) {
   2284 		if (!uasp->usb_as_alts[alt].alt_valid) {
   2285 			continue;
   2286 		}
   2287 
   2288 		format = uasp->usb_as_alts[alt].alt_format;
   2289 		if (uasp->usb_as_alts[alt].alt_valid &&
   2290 		    (n < USB_AS_N_FORMATS) &&
   2291 		    (usb_as_valid_format(uasp, alt,
   2292 		    reg->reg_srs,
   2293 		    (sizeof (reg->reg_srs)/
   2294 		    sizeof (uint_t)) - 1)) == USB_SUCCESS) {
   2295 			reg->reg_formats[n].fmt_termlink =
   2296 			    uasp->usb_as_alts[alt].alt_general->
   2297 			    bTerminalLink;
   2298 			reg->reg_formats[n].fmt_alt = (uchar_t)alt;
   2299 			reg->reg_formats[n].fmt_chns =
   2300 			    format->bNrChannels;
   2301 			reg->reg_formats[n].fmt_precision =
   2302 			    format->bBitResolution;
   2303 			reg->reg_formats[n++].fmt_encoding =
   2304 			    format->bFormatType;
   2305 			/* count how many mono and stereo we have */
   2306 			channels[format->bNrChannels]++;
   2307 		}
   2308 	}
   2309 
   2310 	reg->reg_n_formats = (uchar_t)n;
   2311 
   2312 	if (n == 0) {
   2313 		/* no valid formats */
   2314 		USB_DPRINTF_L2(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2315 		    "zero valid formats");
   2316 
   2317 		return;
   2318 	}
   2319 
   2320 	/* dump what we have so far */
   2321 	for (n = 0; n < reg->reg_n_formats; n++) {
   2322 		USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2323 		    "regformats[%d]: termlink = %d, alt=%d chns=%d"
   2324 		    " prec=%d enc=%d", n,
   2325 		    reg->reg_formats[n].fmt_termlink,
   2326 		    reg->reg_formats[n].fmt_alt,
   2327 		    reg->reg_formats[n].fmt_chns,
   2328 		    reg->reg_formats[n].fmt_precision,
   2329 		    reg->reg_formats[n].fmt_encoding);
   2330 	}
   2331 
   2332 	/*
   2333 	 * Fill out channels
   2334 	 * Note that we assumed all alternates have the same number
   2335 	 * of channels.
   2336 	 */
   2337 	n = 0;
   2338 	if (channels[1]) {
   2339 		reg->reg_channels[n++] = 1;
   2340 	}
   2341 	if (channels[2]) {
   2342 		reg->reg_channels[n] = 2;
   2343 	}
   2344 
   2345 	USB_DPRINTF_L3(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2346 	    "channels %d %d", reg->reg_channels[0], reg->reg_channels[1]);
   2347 
   2348 
   2349 
   2350 	reg->reg_valid++;
   2351 }
   2352 
   2353 
   2354 /*
   2355  * usb_as_valid_format:
   2356  *	check if this format can be supported
   2357  */
   2358 static int
   2359 usb_as_valid_format(usb_as_state_t *uasp, uint_t alternate,
   2360 	uint_t *srs, uint_t n_srs)
   2361 {
   2362 	int n, i, j;
   2363 	usb_as_alt_descr_t *alt_descr = &uasp->usb_as_alts[alternate];
   2364 	usb_audio_type1_format_descr_t	*format = alt_descr->alt_format;
   2365 
   2366 	USB_DPRINTF_L4(PRINT_MASK_PM, uasp->usb_as_log_handle,
   2367 	    "usb_as_valid_format: %d %d %d %d %d",
   2368 	    format->bNrChannels, format->bSubFrameSize,
   2369 	    format->bBitResolution, format->bSamFreqType,
   2370 	    format->bFormatType);
   2371 	USB_DPRINTF_L4(PRINT_MASK_PM, uasp->usb_as_log_handle,
   2372 	    "alt=%d n_srs=%d", alternate, n_srs);
   2373 
   2374 	switch (format->bNrChannels) {
   2375 	case 1:
   2376 	case 2:
   2377 		break;
   2378 	default:
   2379 
   2380 		return (USB_FAILURE);
   2381 	}
   2382 
   2383 	switch (format->bSubFrameSize) {
   2384 	case 1:
   2385 	case 2:
   2386 		break;
   2387 	default:
   2388 
   2389 		return (USB_FAILURE);
   2390 	}
   2391 
   2392 	switch (format->bBitResolution) {
   2393 	case 8:
   2394 	case 16:
   2395 		break;
   2396 	default:
   2397 
   2398 		return (USB_FAILURE);
   2399 	}
   2400 
   2401 	switch (format->bFormatType) {
   2402 	case USB_AUDIO_FORMAT_TYPE1_PCM:
   2403 		break;
   2404 	default:
   2405 
   2406 		return (USB_FAILURE);
   2407 	}
   2408 
   2409 	switch (format->bSamFreqType) {
   2410 	case 0:
   2411 		/* continuous */
   2412 
   2413 		break;
   2414 	default:
   2415 		/* count the number of sample rates we still have */
   2416 		for (j = n = 0; j < n_srs; n++) {
   2417 			if (srs[n] == 0) {
   2418 
   2419 				break;
   2420 			} else {
   2421 				j++;
   2422 			}
   2423 		}
   2424 
   2425 		/* check if our preferred sample rates are supported */
   2426 		for (n = 0; n < n_srs; n++) {
   2427 			uint_t sr = srs[n];
   2428 
   2429 			if (sr == 0) {
   2430 				break;
   2431 			}
   2432 
   2433 			USB_DPRINTF_L3(PRINT_MASK_PM, uasp->usb_as_log_handle,
   2434 			    "checking sr=%d", sr);
   2435 			for (i = 0; i < alt_descr->alt_n_sample_rates; i++) {
   2436 				if (sr == alt_descr->alt_sample_rates[i]) {
   2437 					break;
   2438 				}
   2439 			}
   2440 
   2441 			if (i == alt_descr->alt_n_sample_rates) {
   2442 				/*
   2443 				 * remove this sample rate except if it is
   2444 				 * the last one
   2445 				 */
   2446 				if (j > 1) {
   2447 					srs[n] = 0;
   2448 				} else {
   2449 
   2450 					return (USB_FAILURE);
   2451 				}
   2452 			}
   2453 		}
   2454 
   2455 		USB_DPRINTF_L3(PRINT_MASK_PM, uasp->usb_as_log_handle,
   2456 		    "before srs (%d): %d %d %d %d %d %d %d %d %d %d %d %d",
   2457 		    n_srs,
   2458 		    srs[0], srs[1], srs[2], srs[3], srs[4], srs[5], srs[6],
   2459 		    srs[7], srs[8], srs[9], srs[10], srs[11]);
   2460 
   2461 
   2462 		/* now compact srs table, eliminating zero entries */
   2463 		for (i = n = 0; n < n_srs; n++) {
   2464 			if (srs[n]) {
   2465 				/* move up & remove from the list */
   2466 				srs[i] = srs[n];
   2467 				if (i++ != n) {
   2468 					srs[n] = 0;
   2469 				}
   2470 			}
   2471 		}
   2472 
   2473 		/* last entry must always be zero */
   2474 		srs[i] = 0;
   2475 
   2476 		USB_DPRINTF_L3(PRINT_MASK_PM, uasp->usb_as_log_handle,
   2477 		    "before srs (%d): %d %d %d %d %d %d %d %d %d %d %d %d",
   2478 		    n_srs,
   2479 		    srs[0], srs[1], srs[2], srs[3], srs[4], srs[5], srs[6],
   2480 		    srs[7], srs[8], srs[9], srs[10], srs[11]);
   2481 
   2482 		break;
   2483 	}
   2484 	return (USB_SUCCESS);
   2485 }
   2486 
   2487 
   2488 
   2489 
   2490 /*
   2491  * Event Management
   2492  *
   2493  * usb_as_disconnect_event_cb:
   2494  *	The device has been disconnected.
   2495  */
   2496 static int
   2497 usb_as_disconnect_event_cb(dev_info_t *dip)
   2498 {
   2499 	usb_as_state_t *uasp = (usb_as_state_t *)ddi_get_soft_state(
   2500 	    usb_as_statep, ddi_get_instance(dip));
   2501 
   2502 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uasp->usb_as_log_handle,
   2503 	    "usb_as_disconnect_event_cb: dip=0x%p", (void *)dip);
   2504 
   2505 	(void) usb_serialize_access(uasp->usb_as_ser_acc, USB_WAIT, 0);
   2506 
   2507 	mutex_enter(&uasp->usb_as_mutex);
   2508 	uasp->usb_as_dev_state = USB_DEV_DISCONNECTED;
   2509 	mutex_exit(&uasp->usb_as_mutex);
   2510 
   2511 	usb_release_access(uasp->usb_as_ser_acc);
   2512 
   2513 	return (USB_SUCCESS);
   2514 }
   2515 
   2516 
   2517 /*
   2518  * usb_as_cpr_suspend:
   2519  */
   2520 static int
   2521 usb_as_cpr_suspend(dev_info_t *dip)
   2522 {
   2523 	usb_as_state_t *uasp = (usb_as_state_t *)ddi_get_soft_state(
   2524 	    usb_as_statep, ddi_get_instance(dip));
   2525 
   2526 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uasp->usb_as_log_handle,
   2527 	    "usb_as_cpr_suspend: Begin");
   2528 
   2529 	(void) usb_serialize_access(uasp->usb_as_ser_acc, USB_WAIT, 0);
   2530 
   2531 	mutex_enter(&uasp->usb_as_mutex);
   2532 	uasp->usb_as_dev_state = USB_DEV_SUSPENDED;
   2533 	mutex_exit(&uasp->usb_as_mutex);
   2534 
   2535 	usb_release_access(uasp->usb_as_ser_acc);
   2536 
   2537 	USB_DPRINTF_L4(PRINT_MASK_ALL, uasp->usb_as_log_handle,
   2538 	    "usb_as_cpr_suspend: End");
   2539 
   2540 	return (USB_SUCCESS);
   2541 }
   2542 
   2543 
   2544 /*
   2545  * usb_as_reconnect_event_cb:
   2546  *	The device was disconnected but this instance not detached, probably
   2547  *	because the device was busy.
   2548  *	if the same device, continue with restoring state
   2549  */
   2550 static int
   2551 usb_as_reconnect_event_cb(dev_info_t *dip)
   2552 {
   2553 	usb_as_state_t *uasp = (usb_as_state_t *)ddi_get_soft_state(
   2554 	    usb_as_statep, ddi_get_instance(dip));
   2555 
   2556 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uasp->usb_as_log_handle,
   2557 	    "usb_as_reconnect_event_cb: dip=0x%p", (void *)dip);
   2558 
   2559 	(void) usb_serialize_access(uasp->usb_as_ser_acc, USB_WAIT, 0);
   2560 
   2561 	mutex_enter(&uasp->usb_as_mutex);
   2562 	usb_as_restore_device_state(dip, uasp);
   2563 	mutex_exit(&uasp->usb_as_mutex);
   2564 
   2565 	usb_release_access(uasp->usb_as_ser_acc);
   2566 
   2567 	return (USB_SUCCESS);
   2568 }
   2569 
   2570 
   2571 /*
   2572  * usb_as_cpr_resume:
   2573  *	recover this device from suspended state
   2574  */
   2575 static void
   2576 usb_as_cpr_resume(dev_info_t *dip)
   2577 {
   2578 	usb_as_state_t *uasp = (usb_as_state_t *)ddi_get_soft_state(
   2579 	    usb_as_statep, ddi_get_instance(dip));
   2580 
   2581 	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uasp->usb_as_log_handle,
   2582 	    "usb_as_cpr_resume: dip=0x%p", (void *)dip);
   2583 
   2584 	(void) usb_serialize_access(uasp->usb_as_ser_acc, USB_WAIT, 0);
   2585 
   2586 	mutex_enter(&uasp->usb_as_mutex);
   2587 	usb_as_restore_device_state(dip, uasp);
   2588 	mutex_exit(&uasp->usb_as_mutex);
   2589 
   2590 	usb_release_access(uasp->usb_as_ser_acc);
   2591 }
   2592 
   2593 
   2594 /*
   2595  * usb_as_restore_device_state:
   2596  *	Set original configuration of the device
   2597  *	enable wrq - this starts new transactions on the control pipe
   2598  */
   2599 static void
   2600 usb_as_restore_device_state(dev_info_t *dip, usb_as_state_t *uasp)
   2601 {
   2602 	usb_as_power_t	*uaspm;
   2603 
   2604 	USB_DPRINTF_L4(PRINT_MASK_ATTA, uasp->usb_as_log_handle,
   2605 	    "usb_as_restore_device_state:");
   2606 
   2607 	ASSERT(mutex_owned(&uasp->usb_as_mutex));
   2608 
   2609 	uaspm = uasp->usb_as_pm;
   2610 
   2611 	/* Check if we are talking to the same device */
   2612 	mutex_exit(&uasp->usb_as_mutex);
   2613 	usb_as_pm_busy_component(uasp);
   2614 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
   2615 
   2616 	if (usb_check_same_device(dip, uasp->usb_as_log_handle, USB_LOG_L0,
   2617 	    PRINT_MASK_ALL, USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
   2618 		usb_as_pm_idle_component(uasp);
   2619 
   2620 		/* change the device state from suspended to disconnected */
   2621 		mutex_enter(&uasp->usb_as_mutex);
   2622 		uasp->usb_as_dev_state = USB_DEV_DISCONNECTED;
   2623 
   2624 		return;
   2625 	}
   2626 	mutex_enter(&uasp->usb_as_mutex);
   2627 
   2628 	if (uaspm) {
   2629 		if (uaspm->aspm_wakeup_enabled) {
   2630 			mutex_exit(&uasp->usb_as_mutex);
   2631 			if (usb_handle_remote_wakeup(uasp->usb_as_dip,
   2632 			    USB_REMOTE_WAKEUP_ENABLE)) {
   2633 				USB_DPRINTF_L2(PRINT_MASK_ALL,
   2634 				    uasp->usb_as_log_handle,
   2635 				    "enable remote wake up failed");
   2636 			}
   2637 			mutex_enter(&uasp->usb_as_mutex);
   2638 		}
   2639 	}
   2640 	uasp->usb_as_dev_state = USB_DEV_ONLINE;
   2641 
   2642 	mutex_exit(&uasp->usb_as_mutex);
   2643 	usb_as_pm_idle_component(uasp);
   2644 	mutex_enter(&uasp->usb_as_mutex);
   2645 }
   2646 
   2647 
   2648 static void
   2649 usb_as_pm_busy_component(usb_as_state_t *usb_as_statep)
   2650 {
   2651 	ASSERT(!mutex_owned(&usb_as_statep->usb_as_mutex));
   2652 
   2653 	if (usb_as_statep->usb_as_pm != NULL) {
   2654 		mutex_enter(&usb_as_statep->usb_as_mutex);
   2655 		usb_as_statep->usb_as_pm->aspm_pm_busy++;
   2656 
   2657 		USB_DPRINTF_L4(PRINT_MASK_PM, usb_as_statep->usb_as_log_handle,
   2658 		    "usb_as_pm_busy_component: %d",
   2659 		    usb_as_statep->usb_as_pm->aspm_pm_busy);
   2660 
   2661 		mutex_exit(&usb_as_statep->usb_as_mutex);
   2662 
   2663 		if (pm_busy_component(usb_as_statep->usb_as_dip, 0) !=
   2664 		    DDI_SUCCESS) {
   2665 			mutex_enter(&usb_as_statep->usb_as_mutex);
   2666 			usb_as_statep->usb_as_pm->aspm_pm_busy--;
   2667 
   2668 			USB_DPRINTF_L2(PRINT_MASK_PM,
   2669 			    usb_as_statep->usb_as_log_handle,
   2670 			    "usb_as_pm_busy_component failed: %d",
   2671 			    usb_as_statep->usb_as_pm->aspm_pm_busy);
   2672 
   2673 			mutex_exit(&usb_as_statep->usb_as_mutex);
   2674 		}
   2675 	}
   2676 }
   2677 
   2678 
   2679 static void
   2680 usb_as_pm_idle_component(usb_as_state_t *usb_as_statep)
   2681 {
   2682 	ASSERT(!mutex_owned(&usb_as_statep->usb_as_mutex));
   2683 
   2684 	if (usb_as_statep->usb_as_pm != NULL) {
   2685 		if (pm_idle_component(usb_as_statep->usb_as_dip, 0) ==
   2686 		    DDI_SUCCESS) {
   2687 			mutex_enter(&usb_as_statep->usb_as_mutex);
   2688 			ASSERT(usb_as_statep->usb_as_pm->aspm_pm_busy > 0);
   2689 			usb_as_statep->usb_as_pm->aspm_pm_busy--;
   2690 
   2691 			USB_DPRINTF_L4(PRINT_MASK_PM,
   2692 			    usb_as_statep->usb_as_log_handle,
   2693 			    "usb_as_pm_idle_component: %d",
   2694 			    usb_as_statep->usb_as_pm->aspm_pm_busy);
   2695 
   2696 			mutex_exit(&usb_as_statep->usb_as_mutex);
   2697 		}
   2698 	}
   2699 }
   2700