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