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