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