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