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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * AUDIO CONTROL Driver: 28 * 29 * usb_ac is a multiplexor that sits on top of usb_as and hid and is 30 * responsible for (1) providing the entry points to audio mixer framework, 31 * (2) passing control commands to and from usb_as and hid and (3) processing 32 * control messages from hid/usb_ah that it can handle. 33 * 34 * 1. Mixer entry points are: usb_ac_setup(), usb_ac_teardown(), 35 * usb_ac_set_config(), usb_ac_set_format(), usb_ac_start_play(), 36 * usb_ac_pause_play(), usb_ac_stop_play, usb_ac_start_record(), 37 * usb_ac_stop_record(). 38 * 2. usb_ac is a streams driver that passes streams messages down to 39 * usb_as that selects the correct alternate with passed format 40 * parameters, sets sample frequency, starts play/record, stops 41 * play/record, pause play/record, open/close isoc pipe. 42 * 3. usb_ac handles the set_config command through the default pipe 43 * of sound control interface of the audio device in a synchronous 44 * manner. 45 * 46 * Serialization: A competing thread can't be allowed to interfere with 47 * (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 takes control, it 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_ac: Raise power during attach. If a device is not at full 57 * power, raise power in the entry points. After the command is over, 58 * pm_idle_component() is called. The power is lowered in detach(). 59 */ 60 #include <sys/usb/usba/usbai_version.h> 61 #include <sys/usb/usba.h> 62 #include <sys/sunndi.h> 63 #include <sys/strsubr.h> 64 #include <sys/strsun.h> 65 #include <sys/ddi.h> 66 #include <sys/sunddi.h> 67 #include <sys/sunldi.h> 68 69 #include <sys/audio/audio_driver.h> 70 71 #include <sys/usb/clients/audio/usb_audio.h> 72 #include <sys/usb/clients/audio/usb_mixer.h> 73 #include <sys/usb/clients/audio/usb_ac/usb_ac.h> 74 75 /* for getting the minor node info from hid */ 76 #include <sys/usb/clients/hid/hidminor.h> 77 #include <sys/usb/clients/audio/usb_as/usb_as.h> 78 79 80 /* debug support */ 81 uint_t usb_ac_errlevel = USB_LOG_L4; 82 uint_t usb_ac_errmask = (uint_t)-1; 83 uint_t usb_ac_instance_debug = (uint_t)-1; 84 85 /* 86 * wait period in seconds for the HID message processing thread 87 * used primarily to check when the stream has closed 88 */ 89 uint_t usb_ac_wait_hid = 1; 90 91 /* 92 * table for converting term types of input and output terminals 93 * to OSS port types (pretty rough mapping) 94 */ 95 static const char *usb_audio_dtypes[] = { 96 AUDIO_PORT_LINEIN, 97 AUDIO_PORT_LINEOUT, 98 AUDIO_PORT_SPEAKER, 99 AUDIO_PORT_HEADPHONES, 100 AUDIO_PORT_HANDSET, 101 AUDIO_PORT_CD, 102 AUDIO_PORT_MIC, 103 AUDIO_PORT_PHONE, 104 AUDIO_PORT_SPDIFIN, 105 AUDIO_PORT_OTHER, 106 NULL, 107 }; 108 enum { 109 USB_PORT_LINEIN = 0, 110 USB_PORT_LINEOUT, 111 USB_PORT_SPEAKER, 112 USB_PORT_HEADPHONES, 113 USB_PORT_HANDSET, 114 USB_PORT_CD, 115 USB_PORT_MIC, 116 USB_PORT_PHONE, 117 USB_PORT_SPDIFIN, 118 USB_PORT_UNKNOWN 119 }; 120 121 static struct { 122 ushort_t term_type; 123 uint_t port_type; 124 } usb_ac_term_type_map[] = { 125 126 /* Input Terminal Types */ 127 { USB_AUDIO_TERM_TYPE_MICROPHONE, USB_PORT_MIC }, 128 { USB_AUDIO_TERM_TYPE_DT_MICROPHONE, USB_PORT_MIC }, 129 { USB_AUDIO_TERM_TYPE_PERS_MICROPHONE, USB_PORT_MIC }, 130 { USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE, USB_PORT_MIC }, 131 { USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY, USB_PORT_MIC }, 132 { USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY, USB_PORT_MIC }, 133 134 /* Output Terminal Types */ 135 { USB_AUDIO_TERM_TYPE_SPEAKER, USB_PORT_SPEAKER }, 136 { USB_AUDIO_TERM_TYPE_HEADPHONES, USB_PORT_HEADPHONES }, 137 { USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO, USB_PORT_LINEOUT }, 138 { USB_AUDIO_TERM_TYPE_DT_SPEAKER, USB_PORT_SPEAKER }, 139 { USB_AUDIO_TERM_TYPE_ROOM_SPEAKER, USB_PORT_SPEAKER }, 140 { USB_AUDIO_TERM_TYPE_COMM_SPEAKER, USB_PORT_SPEAKER }, 141 { USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER, USB_PORT_SPEAKER }, 142 143 /* Bi-directional Terminal Types */ 144 { USB_AUDIO_TERM_TYPE_HANDSET, USB_PORT_HANDSET }, 145 146 /* Telephony Terminal Types */ 147 { USB_AUDIO_TERM_TYPE_PHONE_LINE, USB_PORT_PHONE}, 148 { USB_AUDIO_TERM_TYPE_TELEPHONE, USB_PORT_PHONE}, 149 { USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE, USB_PORT_PHONE }, 150 151 /* External Terminal Types */ 152 { USB_AUDIO_TERM_TYPE_SPDIF_IF, USB_PORT_SPDIFIN }, 153 /* Embedded Function Terminal Types */ 154 { USB_AUDIO_TERM_TYPE_CD_PLAYER, USB_PORT_CD }, 155 { 0, 0 } 156 }; 157 158 159 /* 160 * Module linkage routines for the kernel 161 */ 162 static int usb_ac_attach(dev_info_t *, ddi_attach_cmd_t); 163 static int usb_ac_detach(dev_info_t *, ddi_detach_cmd_t); 164 static int usb_ac_power(dev_info_t *, int, int); 165 166 static uint_t usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t, 167 uint_t); 168 169 /* module entry points */ 170 int usb_ac_open(dev_info_t *); 171 void usb_ac_close(dev_info_t *); 172 173 /* descriptor handling */ 174 static int usb_ac_handle_descriptors(usb_ac_state_t *); 175 static void usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t); 176 static void usb_ac_alloc_unit(usb_ac_state_t *, uint_t); 177 static void usb_ac_free_all_units(usb_ac_state_t *); 178 static void usb_ac_setup_connections(usb_ac_state_t *); 179 static void usb_ac_map_termtype_to_port(usb_ac_state_t *, uint_t); 180 181 /* power management */ 182 static int usb_ac_pwrlvl0(usb_ac_state_t *); 183 static int usb_ac_pwrlvl1(usb_ac_state_t *); 184 static int usb_ac_pwrlvl2(usb_ac_state_t *); 185 static int usb_ac_pwrlvl3(usb_ac_state_t *); 186 static void usb_ac_create_pm_components(dev_info_t *, usb_ac_state_t *); 187 static void usb_ac_pm_busy_component(usb_ac_state_t *); 188 static void usb_ac_pm_idle_component(usb_ac_state_t *); 189 190 /* event handling */ 191 static int usb_ac_disconnect_event_cb(dev_info_t *); 192 static int usb_ac_reconnect_event_cb(dev_info_t *); 193 static int usb_ac_cpr_suspend(dev_info_t *); 194 static void usb_ac_cpr_resume(dev_info_t *); 195 196 static usb_event_t usb_ac_events = { 197 usb_ac_disconnect_event_cb, 198 usb_ac_reconnect_event_cb, 199 NULL, NULL 200 }; 201 202 /* misc. support */ 203 static void usb_ac_restore_device_state(dev_info_t *, usb_ac_state_t *); 204 static int usb_ac_cleanup(dev_info_t *, usb_ac_state_t *); 205 static void usb_ac_serialize_access(usb_ac_state_t *); 206 static void usb_ac_release_access(usb_ac_state_t *); 207 208 static void usb_ac_push_unit_id(usb_ac_state_t *, uint_t); 209 static void usb_ac_pop_unit_id(usb_ac_state_t *, uint_t); 210 static void usb_ac_show_traverse_path(usb_ac_state_t *); 211 static int usb_ac_check_path(usb_ac_state_t *, uint_t); 212 213 static uint_t usb_ac_traverse_connections(usb_ac_state_t *, uint_t, uint_t, 214 uint_t, uint_t, uint_t, uint_t, 215 uint_t *, uint_t, uint_t *, 216 int (*func)(usb_ac_state_t *, uint_t, uint_t, 217 uint_t, uint_t, uint_t, uint_t *)); 218 static uint_t usb_ac_set_port(usb_ac_state_t *, uint_t, uint_t); 219 static uint_t usb_ac_set_control(usb_ac_state_t *, uint_t, uint_t, 220 uint_t, uint_t, uint_t, 221 uint_t *, uint_t, 222 int (*func)(usb_ac_state_t *, uint_t, uint_t, 223 uint_t, uint_t, uint_t, uint_t *)); 224 static uint_t usb_ac_set_monitor_gain_control(usb_ac_state_t *, uint_t, 225 uint_t, uint_t, uint_t, uint_t, 226 uint_t *, uint_t, 227 int (*func)(usb_ac_state_t *, uint_t, uint_t, 228 uint_t, uint_t, uint_t, uint_t *)); 229 static uint_t usb_ac_traverse_all_units(usb_ac_state_t *, uint_t, uint_t, 230 uint_t, uint_t, uint_t, uint_t *, 231 uint_t, uint_t *, 232 int (*func)(usb_ac_state_t *, uint_t, uint_t, 233 uint_t, uint_t, uint_t, uint_t *)); 234 static int usb_ac_update_port(usb_ac_state_t *, uint_t, 235 uint_t, uint_t, uint_t, uint_t, uint_t *); 236 static int usb_ac_set_selector(usb_ac_state_t *, uint_t, 237 uint_t, uint_t, uint_t, uint_t, uint_t *); 238 static int usb_ac_feature_unit_check(usb_ac_state_t *, uint_t, 239 uint_t, uint_t, uint_t, uint_t, uint_t *); 240 static int usb_ac_set_gain(usb_ac_state_t *, uint_t, 241 uint_t, uint_t, uint_t, uint_t, uint_t *); 242 static int usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t, 243 uint_t, uint_t, uint_t, uint_t, uint_t *); 244 static int usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir, 245 int); 246 static int usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int, 247 int, short *); 248 static int usb_ac_send_as_cmd(usb_ac_state_t *, usb_audio_eng_t *, 249 int, void *); 250 static int usb_ac_set_format(usb_ac_state_t *, usb_audio_eng_t *); 251 static int usb_ac_do_setup(usb_ac_state_t *, usb_audio_eng_t *); 252 253 /* usb audio basic function entries */ 254 static int usb_ac_setup(usb_ac_state_t *, usb_audio_eng_t *); 255 static void usb_ac_teardown(usb_ac_state_t *, usb_audio_eng_t *); 256 static int usb_ac_start_play(usb_ac_state_t *, usb_audio_eng_t *); 257 static int usb_ac_start_record(usb_ac_state_t *, usb_audio_eng_t *); 258 static void usb_ac_stop_record(usb_ac_state_t *, usb_audio_eng_t *); 259 static int usb_ac_restore_audio_state(usb_ac_state_t *, int); 260 261 static int usb_ac_ctrl_restore(usb_ac_state_t *); 262 /* 263 * Mux 264 */ 265 static int usb_ac_mux_walk_siblings(usb_ac_state_t *); 266 static void usb_ac_print_reg_data(usb_ac_state_t *, 267 usb_as_registration_t *); 268 static int usb_ac_get_reg_data(usb_ac_state_t *, ldi_handle_t, int); 269 static int usb_ac_setup_plumbed(usb_ac_state_t *, int, int); 270 static int usb_ac_mixer_registration(usb_ac_state_t *); 271 static void usb_ac_hold_siblings(usb_ac_state_t *); 272 static int usb_ac_online_siblings(usb_ac_state_t *); 273 static void usb_ac_rele_siblings(usb_ac_state_t *); 274 static int usb_ac_mux_plumbing(usb_ac_state_t *); 275 static void usb_ac_mux_plumbing_tq(void *); 276 static int usb_ac_mux_unplumbing(usb_ac_state_t *); 277 static void usb_ac_mux_unplumbing_tq(void *); 278 static int usb_ac_plumb(usb_ac_plumbed_t *); 279 static void usb_ac_unplumb(usb_ac_plumbed_t *); 280 static void usb_ac_reader(void *); 281 static int usb_ac_read_msg(usb_ac_plumbed_t *, mblk_t *); 282 static int usb_ac_do_plumbing(usb_ac_state_t *); 283 static int usb_ac_do_unplumbing(usb_ac_state_t *); 284 285 286 static int usb_change_phy_vol(usb_ac_state_t *, int); 287 static void usb_restore_engine(usb_ac_state_t *); 288 289 /* anchor for soft state structures */ 290 void *usb_ac_statep; 291 292 /* 293 * DDI Structures 294 */ 295 296 /* Device operations structure */ 297 static struct dev_ops usb_ac_dev_ops = { 298 DEVO_REV, /* devo_rev */ 299 0, /* devo_refcnt */ 300 NULL, /* devo_getinfo */ 301 nulldev, /* devo_identify - obsolete */ 302 nulldev, /* devo_probe - not needed */ 303 usb_ac_attach, /* devo_attach */ 304 usb_ac_detach, /* devo_detach */ 305 nodev, /* devo_reset */ 306 NULL, /* devi_cb_ops */ 307 NULL, /* devo_busb_ac_ops */ 308 usb_ac_power, /* devo_power */ 309 ddi_quiesce_not_needed, /* devo_quiesce */ 310 }; 311 312 /* Linkage structure for loadable drivers */ 313 static struct modldrv usb_ac_modldrv = { 314 &mod_driverops, /* drv_modops */ 315 "USB Audio Control Driver", /* drv_linkinfo */ 316 &usb_ac_dev_ops /* drv_dev_ops */ 317 }; 318 319 /* Module linkage structure */ 320 static struct modlinkage usb_ac_modlinkage = { 321 MODREV_1, /* ml_rev */ 322 { (void *)&usb_ac_modldrv, NULL } /* ml_linkage */ 323 }; 324 325 static int usb_audio_register(usb_ac_state_t *); 326 static int usb_audio_unregister(usb_ac_state_t *); 327 328 static int usb_engine_open(void *, int, unsigned *, caddr_t *); 329 static void usb_engine_close(void *); 330 static uint64_t usb_engine_count(void *); 331 static int usb_engine_start(void *); 332 static void usb_engine_stop(void *); 333 static int usb_engine_format(void *); 334 static int usb_engine_channels(void *); 335 static int usb_engine_rate(void *); 336 static void usb_engine_sync(void *, unsigned); 337 static unsigned usb_engine_qlen(void *); 338 339 /* engine buffer size in terms of fragments */ 340 341 audio_engine_ops_t usb_engine_ops = { 342 AUDIO_ENGINE_VERSION, 343 usb_engine_open, 344 usb_engine_close, 345 usb_engine_start, 346 usb_engine_stop, 347 usb_engine_count, 348 usb_engine_format, 349 usb_engine_channels, 350 usb_engine_rate, 351 usb_engine_sync, 352 usb_engine_qlen, 353 }; 354 355 356 357 _NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t)) 358 359 /* standard entry points */ 360 int 361 _init(void) 362 { 363 int rval; 364 365 /* initialize the soft state */ 366 if ((rval = ddi_soft_state_init(&usb_ac_statep, 367 sizeof (usb_ac_state_t), 1)) != DDI_SUCCESS) { 368 return (rval); 369 } 370 371 audio_init_ops(&usb_ac_dev_ops, "usb_ac"); 372 373 if ((rval = mod_install(&usb_ac_modlinkage)) != 0) { 374 ddi_soft_state_fini(&usb_ac_statep); 375 audio_fini_ops(&usb_ac_dev_ops); 376 } 377 378 return (rval); 379 } 380 381 int 382 _fini(void) 383 { 384 int rval; 385 386 if ((rval = mod_remove(&usb_ac_modlinkage)) == 0) { 387 /* Free the soft state internal structures */ 388 ddi_soft_state_fini(&usb_ac_statep); 389 audio_fini_ops(&usb_ac_dev_ops); 390 } 391 392 return (rval); 393 } 394 395 int 396 _info(struct modinfo *modinfop) 397 { 398 return (mod_info(&usb_ac_modlinkage, modinfop)); 399 } 400 401 extern uint_t nproc; 402 #define INIT_PROCESS_CNT 3 403 404 static int 405 usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 406 { 407 usb_ac_state_t *uacp = NULL; 408 int instance = ddi_get_instance(dip); 409 410 switch (cmd) { 411 case DDI_ATTACH: 412 break; 413 case DDI_RESUME: 414 usb_ac_cpr_resume(dip); 415 416 return (DDI_SUCCESS); 417 default: 418 return (DDI_FAILURE); 419 } 420 421 /* 422 * wait until all processes are started from main. 423 * USB enumerates early in boot (ie. consconfig time). 424 * If the plumbing takes place early, the file descriptors 425 * are owned by the init process and can never be closed anymore 426 * Consequently, hot removal is not possible and the dips 427 * never go away. By waiting some time, e.g. INIT_PROCESS_CNT, 428 * the problem is avoided. 429 */ 430 if (nproc < INIT_PROCESS_CNT) { 431 USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL, 432 "usb_ac%d attach too early", instance); 433 434 return (DDI_FAILURE); 435 } 436 437 /* 438 * Allocate soft state information. 439 */ 440 if (ddi_soft_state_zalloc(usb_ac_statep, instance) != DDI_SUCCESS) { 441 442 goto fail; 443 } 444 445 /* 446 * get soft state space and initialize 447 */ 448 uacp = (usb_ac_state_t *)ddi_get_soft_state(usb_ac_statep, instance); 449 if (uacp == NULL) { 450 451 goto fail; 452 } 453 454 /* get log handle */ 455 uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac", 456 &usb_ac_errlevel, 457 &usb_ac_errmask, &usb_ac_instance_debug, 458 0); 459 460 uacp->usb_ac_instance = instance; 461 uacp->usb_ac_dip = dip; 462 463 (void) snprintf(uacp->dstr, sizeof (uacp->dstr), "%s#%d", 464 ddi_driver_name(dip), instance); 465 466 if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) { 467 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 468 "usb_client_attach failed"); 469 470 usb_free_log_hdl(uacp->usb_ac_log_handle); 471 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance); 472 473 return (DDI_FAILURE); 474 } 475 476 if (usb_get_dev_data(dip, &uacp->usb_ac_dev_data, 477 USB_PARSE_LVL_IF, 0) != USB_SUCCESS) { 478 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 479 "usb_get_dev_data failed"); 480 481 usb_client_detach(dip, NULL); 482 usb_free_log_hdl(uacp->usb_ac_log_handle); 483 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance); 484 485 return (DDI_FAILURE); 486 } 487 488 /* initialize mutex & cv */ 489 mutex_init(&uacp->usb_ac_mutex, NULL, MUTEX_DRIVER, 490 uacp->usb_ac_dev_data->dev_iblock_cookie); 491 492 uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph; 493 494 /* parse all class specific descriptors */ 495 if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) { 496 497 goto fail; 498 } 499 500 /* we no longer need the descr tree */ 501 usb_free_descr_tree(dip, uacp->usb_ac_dev_data); 502 503 uacp->usb_ac_ser_acc = usb_init_serialization(dip, 504 USB_INIT_SER_CHECK_SAME_THREAD); 505 506 mutex_enter(&uacp->usb_ac_mutex); 507 508 /* we are online */ 509 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 510 511 /* 512 * safe guard the postattach to be executed 513 * only two states arepossible: plumbed / unplumbed 514 */ 515 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED; 516 uacp->usb_ac_current_plumbed_index = -1; 517 518 mutex_exit(&uacp->usb_ac_mutex); 519 520 /* create components to power manage this device */ 521 usb_ac_create_pm_components(dip, uacp); 522 523 /* Register for events */ 524 if (usb_register_event_cbs(dip, &usb_ac_events, 0) != USB_SUCCESS) { 525 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 526 "usb_ac_attach: couldn't register for events"); 527 528 goto fail; 529 } 530 531 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 532 "usb_ac_attach: End"); 533 534 /* report device */ 535 ddi_report_dev(dip); 536 537 if (usb_ac_do_plumbing(uacp) != USB_SUCCESS) 538 goto fail; 539 540 return (DDI_SUCCESS); 541 542 fail: 543 if (uacp) { 544 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 545 "attach failed"); 546 547 /* wait for plumbing thread to finish */ 548 if (uacp->tqp != NULL) { 549 ddi_taskq_wait(uacp->tqp); 550 ddi_taskq_destroy(uacp->tqp); 551 uacp->tqp = NULL; 552 } 553 (void) usb_ac_cleanup(dip, uacp); 554 } 555 556 return (DDI_FAILURE); 557 } 558 559 560 static int 561 usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 562 { 563 int instance = ddi_get_instance(dip); 564 usb_ac_state_t *uacp; 565 int rval = USB_FAILURE; 566 567 uacp = ddi_get_soft_state(usb_ac_statep, instance); 568 569 switch (cmd) { 570 case DDI_DETACH: 571 USB_DPRINTF_L4(PRINT_MASK_ATTA, 572 uacp->usb_ac_log_handle, "usb_ac_detach: detach"); 573 574 /* wait for plumbing thread to finish */ 575 if (uacp->tqp != NULL) 576 ddi_taskq_wait(uacp->tqp); 577 578 mutex_enter(&uacp->usb_ac_mutex); 579 580 /* do not allow detach if still busy */ 581 if (uacp->usb_ac_busy_count) { 582 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 583 "usb_ac_detach:still busy, usb_ac_busy_count = %d", 584 uacp->usb_ac_busy_count); 585 586 mutex_exit(&uacp->usb_ac_mutex); 587 return (USB_FAILURE); 588 } 589 mutex_exit(&uacp->usb_ac_mutex); 590 591 (void) usb_audio_unregister(uacp); 592 593 594 595 /* 596 * unplumb to stop activity from other modules, then 597 * cleanup, which will also teardown audio framework state 598 */ 599 if (usb_ac_do_unplumbing(uacp) == USB_SUCCESS) 600 rval = usb_ac_cleanup(dip, uacp); 601 602 if (rval != USB_SUCCESS) { 603 USB_DPRINTF_L2(PRINT_MASK_ATTA, 604 uacp->usb_ac_log_handle, "detach failed: %s%d", 605 ddi_driver_name(dip), instance); 606 } 607 608 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 609 case DDI_SUSPEND: 610 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 611 "usb_ac_detach: suspending"); 612 613 rval = usb_ac_cpr_suspend(dip); 614 615 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 616 default: 617 618 return (DDI_FAILURE); 619 } 620 } 621 622 623 /* 624 * usb_ac_cleanup: 625 * cleanup on attach failure and detach 626 */ 627 static int 628 usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp) 629 { 630 usb_ac_power_t *uacpm; 631 int rval = USB_FAILURE; 632 633 634 mutex_enter(&uacp->usb_ac_mutex); 635 uacpm = uacp->usb_ac_pm; 636 637 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 638 "usb_ac_cleanup:begain"); 639 640 ASSERT(uacp->usb_ac_busy_count == 0); 641 642 ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED); 643 644 mutex_exit(&uacp->usb_ac_mutex); 645 646 /* 647 * Disable the event callbacks, after this point, event 648 * callbacks will never get called. Note we shouldn't hold 649 * the mutex while unregistering events because there may be a 650 * competing event callback thread. Event callbacks are done 651 * with ndi mutex held and this can cause a potential deadlock. 652 */ 653 usb_unregister_event_cbs(dip, &usb_ac_events); 654 655 mutex_enter(&uacp->usb_ac_mutex); 656 657 if (uacpm && (uacp->usb_ac_dev_state != USB_DEV_DISCONNECTED)) { 658 if (uacpm->acpm_wakeup_enabled) { 659 mutex_exit(&uacp->usb_ac_mutex); 660 usb_ac_pm_busy_component(uacp); 661 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 662 663 rval = usb_handle_remote_wakeup(dip, 664 USB_REMOTE_WAKEUP_DISABLE); 665 if (rval != USB_SUCCESS) { 666 USB_DPRINTF_L2(PRINT_MASK_PM, 667 uacp->usb_ac_log_handle, 668 "usb_ac_cleanup: disable remote " 669 "wakeup failed, rval=%d", rval); 670 } 671 usb_ac_pm_idle_component(uacp); 672 } else { 673 mutex_exit(&uacp->usb_ac_mutex); 674 } 675 676 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF); 677 678 mutex_enter(&uacp->usb_ac_mutex); 679 } 680 681 if (uacpm) { 682 kmem_free(uacpm, sizeof (usb_ac_power_t)); 683 uacp->usb_ac_pm = NULL; 684 } 685 686 usb_client_detach(dip, uacp->usb_ac_dev_data); 687 688 /* free descriptors */ 689 usb_ac_free_all_units(uacp); 690 691 mutex_exit(&uacp->usb_ac_mutex); 692 693 mutex_destroy(&uacp->usb_ac_mutex); 694 695 usb_fini_serialization(uacp->usb_ac_ser_acc); 696 697 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 698 "usb_ac_cleanup: Ending"); 699 700 usb_free_log_hdl(uacp->usb_ac_log_handle); 701 kmem_free(uacp->usb_ac_connections, uacp->usb_ac_connections_len); 702 kmem_free(uacp->usb_ac_connections_a, uacp->usb_ac_connections_a_len); 703 kmem_free(uacp->usb_ac_unit_type, uacp->usb_ac_max_unit); 704 kmem_free(uacp->usb_ac_traverse_path, uacp->usb_ac_max_unit); 705 706 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance); 707 708 ddi_prop_remove_all(dip); 709 710 return (USB_SUCCESS); 711 } 712 713 714 int 715 usb_ac_open(dev_info_t *dip) 716 { 717 int inst = ddi_get_instance(dip); 718 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst); 719 720 mutex_enter(&uacp->usb_ac_mutex); 721 722 uacp->usb_ac_busy_count++; 723 724 mutex_exit(&uacp->usb_ac_mutex); 725 726 usb_ac_pm_busy_component(uacp); 727 (void) pm_raise_power(uacp->usb_ac_dip, 0, USB_DEV_OS_FULL_PWR); 728 729 return (0); 730 } 731 732 733 void 734 usb_ac_close(dev_info_t *dip) 735 { 736 int inst = ddi_get_instance(dip); 737 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst); 738 739 mutex_enter(&uacp->usb_ac_mutex); 740 741 if (uacp->usb_ac_busy_count > 0) 742 uacp->usb_ac_busy_count--; 743 744 mutex_exit(&uacp->usb_ac_mutex); 745 746 usb_ac_pm_idle_component(uacp); 747 } 748 749 750 /* 751 * usb_ac_read_msg: 752 * Handle asynchronous response from opened streams 753 */ 754 static int 755 usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp) 756 { 757 usb_ac_state_t *uacp = plumb_infop->acp_uacp; 758 int error = DDI_SUCCESS; 759 int val; 760 char val1; 761 struct iocblk *iocp; 762 763 764 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 765 766 /* 767 * typically an M_CTL is used between modules but in order to pass 768 * through the streamhead, an M_PROTO type must be used instead 769 */ 770 switch (mp->b_datap->db_type) { 771 case M_PROTO: 772 case M_ERROR: 773 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 774 "M_CTL/M_ERROR"); 775 776 switch (plumb_infop->acp_driver) { 777 case USB_AH_PLUMBED: 778 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 779 "message from hid, instance=%d", 780 ddi_get_instance(plumb_infop->acp_dip)); 781 782 iocp = (struct iocblk *)(void *)mp->b_rptr; 783 ASSERT(mp->b_cont != NULL); 784 785 if (uacp->usb_ac_registered_with_mixer) { 786 787 val1 = *((char *)mp->b_cont->b_rptr); 788 val = (int)val1; 789 790 USB_DPRINTF_L4(PRINT_MASK_ALL, 791 uacp->usb_ac_log_handle, "val1=0x%x(%d)," 792 "val=0x%x(%d)", val1, val1, val, val); 793 794 switch (iocp->ioc_cmd) { 795 /* Handle relative volume change */ 796 case USB_AUDIO_VOL_CHANGE: 797 /* prevent unplumbing */ 798 uacp->usb_ac_busy_count++; 799 if (uacp->usb_ac_plumbing_state == 800 USB_AC_STATE_PLUMBED) { 801 mutex_exit(&uacp->usb_ac_mutex); 802 (void) usb_change_phy_vol( 803 uacp, val); 804 mutex_enter(&uacp-> 805 usb_ac_mutex); 806 } 807 uacp->usb_ac_busy_count--; 808 /* FALLTHRU */ 809 case USB_AUDIO_MUTE: 810 default: 811 freemsg(mp); 812 break; 813 } 814 } else { 815 freemsg(mp); 816 } 817 818 break; 819 default: 820 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 821 "message from unknown module(%s)", 822 ddi_driver_name(plumb_infop->acp_dip)); 823 freemsg(mp); 824 } 825 826 break; 827 default: 828 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 829 "Unknown type=%d", mp->b_datap->db_type); 830 freemsg(mp); 831 } 832 833 834 return (error); 835 } 836 837 838 /* 839 * Power Management 840 * usb_ac_power: 841 * power entry point 842 */ 843 static int 844 usb_ac_power(dev_info_t *dip, int comp, int level) 845 { 846 _NOTE(ARGUNUSED(comp)); 847 int instance = ddi_get_instance(dip); 848 usb_ac_state_t *uacp; 849 usb_ac_power_t *uacpm; 850 int rval = DDI_FAILURE; 851 852 uacp = ddi_get_soft_state(usb_ac_statep, instance); 853 854 mutex_enter(&uacp->usb_ac_mutex); 855 uacpm = uacp->usb_ac_pm; 856 857 if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) { 858 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 859 "usb_ac_power: illegal level=%d pwr_states=%d", 860 level, uacpm->acpm_pwr_states); 861 862 goto done; 863 } 864 865 switch (level) { 866 case USB_DEV_OS_PWR_OFF: 867 rval = usb_ac_pwrlvl0(uacp); 868 break; 869 case USB_DEV_OS_PWR_1: 870 rval = usb_ac_pwrlvl1(uacp); 871 break; 872 case USB_DEV_OS_PWR_2: 873 rval = usb_ac_pwrlvl2(uacp); 874 break; 875 case USB_DEV_OS_FULL_PWR: 876 rval = usb_ac_pwrlvl3(uacp); 877 break; 878 } 879 880 done: 881 mutex_exit(&uacp->usb_ac_mutex); 882 883 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 884 } 885 886 887 /* 888 * functions to handle power transition for various levels 889 * These functions act as place holders to issue USB commands 890 * to the devices to change their power levels 891 * Level 0 = Device is powered off 892 * Level 3 = Device if full powered 893 * Level 1,2 = Intermediate power level of the device as implemented 894 * by the hardware. 895 * Note that Level 0 is OS power-off and Level 3 is OS full-power. 896 */ 897 static int 898 usb_ac_pwrlvl0(usb_ac_state_t *uacp) 899 { 900 usb_ac_power_t *uacpm; 901 int rval; 902 903 uacpm = uacp->usb_ac_pm; 904 905 switch (uacp->usb_ac_dev_state) { 906 case USB_DEV_ONLINE: 907 /* Deny the powerdown request if the device is busy */ 908 if (uacpm->acpm_pm_busy != 0) { 909 910 return (USB_FAILURE); 911 } 912 913 /* Issue USB D3 command to the device here */ 914 rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip); 915 ASSERT(rval == USB_SUCCESS); 916 917 uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN; 918 uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF; 919 920 /* FALLTHRU */ 921 case USB_DEV_DISCONNECTED: 922 case USB_DEV_SUSPENDED: 923 case USB_DEV_PWRED_DOWN: 924 default: 925 return (USB_SUCCESS); 926 } 927 } 928 929 930 /* ARGSUSED */ 931 static int 932 usb_ac_pwrlvl1(usb_ac_state_t *uacp) 933 { 934 int rval; 935 936 /* Issue USB D2 command to the device here */ 937 rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip); 938 ASSERT(rval == USB_SUCCESS); 939 940 return (USB_FAILURE); 941 } 942 943 944 /* ARGSUSED */ 945 static int 946 usb_ac_pwrlvl2(usb_ac_state_t *uacp) 947 { 948 int rval; 949 950 rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip); 951 ASSERT(rval == USB_SUCCESS); 952 953 return (USB_FAILURE); 954 } 955 956 957 static int 958 usb_ac_pwrlvl3(usb_ac_state_t *uacp) 959 { 960 usb_ac_power_t *uacpm; 961 int rval; 962 963 uacpm = uacp->usb_ac_pm; 964 965 switch (uacp->usb_ac_dev_state) { 966 case USB_DEV_PWRED_DOWN: 967 /* Issue USB D0 command to the device here */ 968 rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip); 969 ASSERT(rval == USB_SUCCESS); 970 971 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 972 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR; 973 /* FALLTHRU */ 974 case USB_DEV_ONLINE: 975 /* we are already in full power */ 976 977 /* FALLTHRU */ 978 case USB_DEV_DISCONNECTED: 979 case USB_DEV_SUSPENDED: 980 981 return (USB_SUCCESS); 982 default: 983 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 984 "usb_ac_pwerlvl3: Illegal dev_state"); 985 986 return (USB_FAILURE); 987 } 988 } 989 990 991 static void 992 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp) 993 { 994 usb_ac_power_t *uacpm; 995 uint_t pwr_states; 996 997 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 998 "usb_ac_create_pm_components: begin"); 999 1000 /* Allocate the state structure */ 1001 uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP); 1002 uacp->usb_ac_pm = uacpm; 1003 uacpm->acpm_state = uacp; 1004 uacpm->acpm_capabilities = 0; 1005 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR; 1006 1007 if (usb_create_pm_components(dip, &pwr_states) == 1008 USB_SUCCESS) { 1009 if (usb_handle_remote_wakeup(dip, 1010 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) { 1011 uacpm->acpm_wakeup_enabled = 1; 1012 1013 USB_DPRINTF_L4(PRINT_MASK_PM, 1014 uacp->usb_ac_log_handle, 1015 "remote Wakeup enabled"); 1016 } 1017 uacpm->acpm_pwr_states = (uint8_t)pwr_states; 1018 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 1019 } else { 1020 if (uacpm) { 1021 kmem_free(uacpm, sizeof (usb_ac_power_t)); 1022 uacp->usb_ac_pm = NULL; 1023 } 1024 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1025 "pm not enabled"); 1026 } 1027 1028 } 1029 1030 /* 1031 * usb_ac_get_featureID: 1032 * find out if there is at least one feature unit that supports 1033 * the request controls. 1034 * Return featureID or USB_AC_ID_NONE. 1035 */ 1036 static uint_t 1037 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir, 1038 uint_t channel, uint_t control) 1039 { 1040 uint_t count = 0; 1041 1042 return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT, 1043 channel, control, USB_AC_FIND_ONE, &count, 0, 1044 usb_ac_feature_unit_check)); 1045 } 1046 1047 1048 /* 1049 * usb_ac_feature_unit_check: 1050 * check if a feature unit can support the required channel 1051 * and control combination. Return USB_SUCCESS or USB_FAILURE. 1052 * Called for each matching unit from usb_ac_traverse_connections. 1053 */ 1054 /*ARGSUSED*/ 1055 static int 1056 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID, 1057 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 1058 { 1059 usb_audio_feature_unit_descr1_t *feature_descrp; 1060 int n_channel_controls; 1061 1062 1063 ASSERT(featureID < uacp->usb_ac_max_unit); 1064 1065 /* 1066 * check if this control is supported on this channel 1067 */ 1068 feature_descrp = (usb_audio_feature_unit_descr1_t *) 1069 uacp->usb_ac_units[featureID].acu_descriptor; 1070 ASSERT(feature_descrp->bUnitID == featureID); 1071 1072 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1073 "bControlSize=%d", feature_descrp->bControlSize); 1074 1075 if (feature_descrp->bControlSize == 0) { 1076 featureID = USB_AC_ID_NONE; 1077 } else { 1078 uint_t index; 1079 1080 n_channel_controls = (feature_descrp->bLength - 1081 offsetof(usb_audio_feature_unit_descr1_t, 1082 bmaControls))/feature_descrp->bControlSize; 1083 1084 USB_DPRINTF_L3(PRINT_MASK_ALL, 1085 uacp->usb_ac_log_handle, 1086 "#controls: %d index=%d", n_channel_controls, 1087 feature_descrp->bControlSize * channel); 1088 1089 if (channel > n_channel_controls) { 1090 featureID = USB_AC_ID_NONE; 1091 } else { 1092 /* 1093 * we only support MUTE and VOLUME 1094 * which are in the first byte 1095 */ 1096 index = feature_descrp->bControlSize * 1097 channel; 1098 1099 USB_DPRINTF_L3(PRINT_MASK_ALL, 1100 uacp->usb_ac_log_handle, 1101 "control: 0x%x", 1102 feature_descrp->bmaControls[index]); 1103 1104 if ((feature_descrp->bmaControls[index] & 1105 control) == 0) { 1106 featureID = USB_AC_ID_NONE; 1107 } 1108 } 1109 } 1110 1111 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1112 "usb_ac_feature_unit_check: dir=%d featureID=0x%x", 1113 dir, featureID); 1114 1115 return ((featureID != USB_AC_ID_NONE) ? 1116 USB_SUCCESS : USB_FAILURE); 1117 } 1118 1119 1120 /* 1121 * Descriptor Management 1122 * 1123 * usb_ac_handle_descriptors: 1124 * extract interesting descriptors from the config cloud 1125 */ 1126 static int 1127 usb_ac_handle_descriptors(usb_ac_state_t *uacp) 1128 { 1129 int len, index; 1130 int rval = USB_FAILURE; 1131 usb_audio_cs_if_descr_t descr; 1132 usb_client_dev_data_t *dev_data = uacp->usb_ac_dev_data; 1133 usb_alt_if_data_t *altif_data; 1134 usb_cvs_data_t *cvs; 1135 1136 1137 altif_data = &dev_data->dev_curr_cfg-> 1138 cfg_if[dev_data->dev_curr_if].if_alt[0]; 1139 1140 uacp->usb_ac_ifno = dev_data->dev_curr_if; 1141 uacp->usb_ac_if_descr = altif_data->altif_descr; 1142 1143 /* find USB_AUDIO_CS_INTERFACE type descriptor */ 1144 for (index = 0; index < altif_data->altif_n_cvs; index++) { 1145 cvs = &altif_data->altif_cvs[index]; 1146 if (cvs->cvs_buf == NULL) { 1147 continue; 1148 } 1149 if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) { 1150 break; 1151 } 1152 } 1153 1154 if (index == altif_data->altif_n_cvs) { 1155 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1156 "usb_ac_handle_descriptors:cannot find descriptor type %d", 1157 USB_AUDIO_CS_INTERFACE); 1158 1159 return (rval); 1160 } 1161 1162 len = usb_parse_data( 1163 CS_AC_IF_HEADER_FORMAT, 1164 cvs->cvs_buf, cvs->cvs_buf_len, 1165 (void *)&descr, sizeof (usb_audio_cs_if_descr_t)); 1166 1167 /* is this a sane header descriptor */ 1168 if (!((len >= CS_AC_IF_HEADER_SIZE) && 1169 (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) && 1170 (descr.bDescriptorSubType == USB_AUDIO_HEADER))) { 1171 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1172 "invalid header"); 1173 1174 return (rval); 1175 } 1176 1177 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1178 "index %d, header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t" 1179 "total=0x%x InCol=0x%x", 1180 index, 1181 descr.bDescriptorType, 1182 descr.bDescriptorSubType, 1183 descr.bcdADC, 1184 descr.wTotalLength, 1185 descr.blnCollection); 1186 1187 /* 1188 * we read descriptors by index and store them in ID array. 1189 * the actual parsing is done in usb_ac_add_unit_descriptor() 1190 */ 1191 for (index++; index < altif_data->altif_n_cvs; index++) { 1192 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1193 "index=%d", index); 1194 1195 cvs = &altif_data->altif_cvs[index]; 1196 if (cvs->cvs_buf == NULL) { 1197 continue; 1198 } 1199 1200 /* add to ID array */ 1201 usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf, 1202 cvs->cvs_buf_len); 1203 } 1204 rval = USB_SUCCESS; 1205 1206 usb_ac_setup_connections(uacp); 1207 1208 /* determine port types */ 1209 usb_ac_map_termtype_to_port(uacp, USB_AUDIO_PLAY); 1210 usb_ac_map_termtype_to_port(uacp, USB_AUDIO_RECORD); 1211 1212 1213 return (rval); 1214 } 1215 1216 1217 /* 1218 * usb_ac_setup_connections: 1219 * build a matrix reflecting all connections 1220 */ 1221 static void 1222 usb_ac_setup_connections(usb_ac_state_t *uacp) 1223 { 1224 usb_ac_unit_list_t *units = uacp->usb_ac_units; 1225 uchar_t *a, **p, i, unit; 1226 size_t a_len, p_len; 1227 1228 /* allocate array for unit types for quick reference */ 1229 uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit, 1230 KM_SLEEP); 1231 /* allocate array for traversal path */ 1232 uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit, 1233 KM_SLEEP); 1234 1235 1236 /* allocate the connection matrix and set it up */ 1237 a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit; 1238 p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *); 1239 1240 /* trick to create a 2 dimensional array */ 1241 a = kmem_zalloc(a_len, KM_SLEEP); 1242 p = kmem_zalloc(p_len, KM_SLEEP); 1243 for (i = 0; i < uacp->usb_ac_max_unit; i++) { 1244 p[i] = a + i * uacp->usb_ac_max_unit; 1245 } 1246 uacp->usb_ac_connections = p; 1247 uacp->usb_ac_connections_len = p_len; 1248 uacp->usb_ac_connections_a = a; 1249 uacp->usb_ac_connections_a_len = a_len; 1250 1251 /* traverse all units and set connections */ 1252 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) { 1253 1254 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1255 "--------traversing unit=0x%x type=0x%x--------", 1256 unit, units[unit].acu_type); 1257 1258 /* store type in the first unused column */ 1259 uacp->usb_ac_unit_type[unit] = units[unit].acu_type; 1260 1261 /* save the Unit ID in the unit it points to */ 1262 switch (units[unit].acu_type) { 1263 case USB_AUDIO_FEATURE_UNIT: 1264 { 1265 usb_audio_feature_unit_descr1_t *d = 1266 units[unit].acu_descriptor; 1267 1268 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1269 "USB_AUDIO_FEATURE_UNIT:sourceID=0x%x type=0x%x", 1270 d->bSourceID, units[d->bSourceID].acu_type); 1271 1272 if (d->bSourceID != 0) { 1273 ASSERT(p[unit][d->bSourceID] == B_FALSE); 1274 p[unit][d->bSourceID] = B_TRUE; 1275 } 1276 1277 break; 1278 } 1279 case USB_AUDIO_OUTPUT_TERMINAL: 1280 { 1281 usb_audio_output_term_descr_t *d = 1282 units[unit].acu_descriptor; 1283 1284 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1285 "USB_AUDIO_OUTPUT_TERMINAL:sourceID=0x%x type=0x%x", 1286 d->bSourceID, units[d->bSourceID].acu_type); 1287 1288 if (d->bSourceID != 0) { 1289 ASSERT(p[unit][d->bSourceID] == B_FALSE); 1290 p[unit][d->bSourceID] = B_TRUE; 1291 } 1292 1293 break; 1294 } 1295 case USB_AUDIO_MIXER_UNIT: 1296 { 1297 usb_audio_mixer_unit_descr1_t *d = 1298 units[unit].acu_descriptor; 1299 int n_sourceID = d->bNrInPins; 1300 int id; 1301 1302 for (id = 0; id < n_sourceID; id++) { 1303 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1304 uacp->usb_ac_log_handle, 1305 "USB_AUDIO_MIXER_UNIT:sourceID=0x%x" 1306 "type=0x%x c=%d", 1307 d->baSourceID[id], 1308 units[d->baSourceID[id]].acu_type, 1309 p[unit][d->baSourceID[id]]); 1310 1311 if (d->baSourceID[id] != 0) { 1312 ASSERT(p[unit][d->baSourceID[id]] == 1313 B_FALSE); 1314 p[unit][d->baSourceID[id]] = B_TRUE; 1315 } 1316 } 1317 1318 break; 1319 } 1320 case USB_AUDIO_SELECTOR_UNIT: 1321 { 1322 usb_audio_selector_unit_descr1_t *d = 1323 units[unit].acu_descriptor; 1324 int n_sourceID = d->bNrInPins; 1325 int id; 1326 1327 for (id = 0; id < n_sourceID; id++) { 1328 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1329 uacp->usb_ac_log_handle, 1330 "USB_AUDIO_SELECTOR_UNIT:sourceID=0x%x" 1331 " type=0x%x", d->baSourceID[id], 1332 units[d->baSourceID[id]].acu_type); 1333 1334 if (d->baSourceID[id] != 0) { 1335 ASSERT(p[unit][d->baSourceID[id]] == 1336 B_FALSE); 1337 p[unit][d->baSourceID[id]] = B_TRUE; 1338 } 1339 } 1340 1341 break; 1342 } 1343 case USB_AUDIO_PROCESSING_UNIT: 1344 { 1345 usb_audio_mixer_unit_descr1_t *d = 1346 units[unit].acu_descriptor; 1347 int n_sourceID = d->bNrInPins; 1348 int id; 1349 1350 for (id = 0; id < n_sourceID; id++) { 1351 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1352 uacp->usb_ac_log_handle, 1353 "USB_AUDIO_PROCESSING_UNIT:sourceID=0x%x" 1354 " type=0x%x", d->baSourceID[id], 1355 units[d->baSourceID[id]].acu_type); 1356 1357 if (d->baSourceID[id] != 0) { 1358 ASSERT(p[unit][d->baSourceID[id]] == 1359 B_FALSE); 1360 p[unit][d->baSourceID[id]] = B_TRUE; 1361 } 1362 } 1363 1364 break; 1365 } 1366 case USB_AUDIO_EXTENSION_UNIT: 1367 { 1368 usb_audio_extension_unit_descr1_t *d = 1369 units[unit].acu_descriptor; 1370 int n_sourceID = d->bNrInPins; 1371 int id; 1372 1373 for (id = 0; id < n_sourceID; id++) { 1374 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1375 uacp->usb_ac_log_handle, 1376 "USB_AUDIO_EXTENSION_UNIT:sourceID=0x%x" 1377 "type=0x%x", d->baSourceID[id], 1378 units[d->baSourceID[id]].acu_type); 1379 1380 if (d->baSourceID[id] != 0) { 1381 ASSERT(p[unit][d->baSourceID[id]] == 1382 B_TRUE); 1383 p[unit][d->baSourceID[id]] = B_FALSE; 1384 } 1385 } 1386 1387 break; 1388 } 1389 case USB_AUDIO_INPUT_TERMINAL: 1390 1391 break; 1392 default: 1393 /* 1394 * Ignore the rest because they are not support yet 1395 */ 1396 break; 1397 } 1398 } 1399 1400 #ifdef DEBUG 1401 /* display topology in log buffer */ 1402 { 1403 uint_t i, j, l; 1404 char *buf; 1405 1406 l = uacp->usb_ac_max_unit * 5; 1407 1408 buf = kmem_alloc(l, KM_SLEEP); 1409 1410 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1411 "unit types:"); 1412 1413 /* two strings so they won't be replaced accidentily by tab */ 1414 (void) sprintf(&buf[0], " "" "); 1415 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1416 (void) sprintf(&buf[2 + (i*3)], "%02d ", i); 1417 } 1418 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1419 1420 (void) sprintf(&buf[0], " +-------"); 1421 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1422 (void) sprintf(&buf[5+((i-1)*3)], "---"); 1423 } 1424 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1425 1426 (void) sprintf(&buf[0], " "" "); 1427 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1428 (void) sprintf(&buf[2 + (i*3)], "%02d ", 1429 uacp->usb_ac_unit_type[i]); 1430 } 1431 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1432 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " "); 1433 1434 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1435 "adjacency matrix:"); 1436 (void) sprintf(&buf[0], " "" "); 1437 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1438 (void) sprintf(&buf[2 + (i*3)], "%02d ", i); 1439 } 1440 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1441 1442 (void) sprintf(&buf[0], " +-------"); 1443 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1444 (void) sprintf(&buf[5+((i-1)*3)], "---"); 1445 } 1446 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1447 1448 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1449 (void) sprintf(&buf[0], "%02d| "" ", i); 1450 for (j = 1; j < uacp->usb_ac_max_unit; j++) { 1451 (void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]); 1452 } 1453 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1454 } 1455 kmem_free(buf, l); 1456 } 1457 #endif 1458 } 1459 1460 1461 /* 1462 * usb_ac_add_unit_descriptor: 1463 * take the parsed descriptor in the buffer and store it in the ID unit 1464 * array. we grow the unit array if the ID exceeds the current max 1465 */ 1466 static void 1467 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer, 1468 size_t buflen) 1469 { 1470 void *descr; 1471 int len; 1472 char *format; 1473 size_t size; 1474 1475 1476 /* doubling the length should allow for padding */ 1477 len = 2 * buffer[0]; 1478 descr = kmem_zalloc(len, KM_SLEEP); 1479 1480 switch (buffer[2]) { 1481 case USB_AUDIO_INPUT_TERMINAL: 1482 format = CS_AC_INPUT_TERM_FORMAT; 1483 size = CS_AC_INPUT_TERM_SIZE; 1484 1485 break; 1486 case USB_AUDIO_OUTPUT_TERMINAL: 1487 format = CS_AC_OUTPUT_TERM_FORMAT; 1488 size = CS_AC_OUTPUT_TERM_SIZE; 1489 1490 break; 1491 case USB_AUDIO_MIXER_UNIT: 1492 format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c"; 1493 size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1; 1494 1495 break; 1496 case USB_AUDIO_SELECTOR_UNIT: 1497 format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c"; 1498 size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1; 1499 1500 break; 1501 case USB_AUDIO_FEATURE_UNIT: 1502 format = CS_AC_FEATURE_UNIT_FORMAT "255c"; 1503 size = CS_AC_FEATURE_UNIT_SIZE; 1504 1505 break; 1506 case USB_AUDIO_PROCESSING_UNIT: 1507 format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c"; 1508 size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1; 1509 1510 break; 1511 case USB_AUDIO_EXTENSION_UNIT: 1512 format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c"; 1513 size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1; 1514 1515 break; 1516 default: 1517 USB_DPRINTF_L2(PRINT_MASK_ATTA, 1518 uacp->usb_ac_log_handle, 1519 "unsupported descriptor %d", buffer[2]); 1520 1521 /* ignore this descriptor */ 1522 kmem_free(descr, len); 1523 1524 return; 1525 } 1526 1527 if (usb_parse_data(format, buffer, buflen, descr, len) < size) { 1528 /* ignore this descriptor */ 1529 kmem_free(descr, len); 1530 1531 return; 1532 } 1533 1534 switch (buffer[2]) { 1535 case USB_AUDIO_INPUT_TERMINAL: 1536 { 1537 usb_audio_input_term_descr_t *d = 1538 (usb_audio_input_term_descr_t *)descr; 1539 1540 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1541 uacp->usb_ac_log_handle, 1542 "usb_ac_units[%d] ---input term: type=0x%x sub=0x%x" 1543 "termid=0x%x\n\t" 1544 "termtype=0x%x assoc=0x%x #ch=%d " 1545 "chconf=0x%x ich=0x%x iterm=0x%x", 1546 d->bTerminalID, 1547 d->bDescriptorType, d->bDescriptorSubType, 1548 d->bTerminalID, d->wTerminalType, 1549 d->bAssocTerminal, d->bNrChannels, 1550 d->wChannelConfig, d->iChannelNames, 1551 d->iTerminal); 1552 1553 usb_ac_alloc_unit(uacp, d->bTerminalID); 1554 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr; 1555 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2]; 1556 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len; 1557 1558 break; 1559 } 1560 case USB_AUDIO_OUTPUT_TERMINAL: 1561 { 1562 usb_audio_output_term_descr_t *d = 1563 (usb_audio_output_term_descr_t *)descr; 1564 1565 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1566 uacp->usb_ac_log_handle, 1567 "usb_ac_units[%d] ---output term: type=0x%x sub=0x%x" 1568 " termid=0x%x\n\t" 1569 "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x", 1570 d->bTerminalID, 1571 d->bDescriptorType, d->bDescriptorSubType, 1572 d->bTerminalID, d->wTerminalType, 1573 d->bAssocTerminal, d->bSourceID, 1574 d->iTerminal); 1575 1576 usb_ac_alloc_unit(uacp, d->bTerminalID); 1577 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr; 1578 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2]; 1579 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len; 1580 1581 break; 1582 } 1583 case USB_AUDIO_MIXER_UNIT: 1584 { 1585 usb_audio_mixer_unit_descr1_t *d = 1586 (usb_audio_mixer_unit_descr1_t *)descr; 1587 1588 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1589 uacp->usb_ac_log_handle, 1590 "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x" 1591 " unitid=0x%x\n\t" 1592 "#pins=0x%x sourceid[0]=0x%x", 1593 d->bUnitID, 1594 d->bDescriptorType, d->bDescriptorSubType, 1595 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 1596 usb_ac_alloc_unit(uacp, d->bUnitID); 1597 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 1598 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 1599 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 1600 1601 break; 1602 } 1603 case USB_AUDIO_SELECTOR_UNIT: 1604 { 1605 usb_audio_selector_unit_descr1_t *d = 1606 (usb_audio_selector_unit_descr1_t *)descr; 1607 1608 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1609 uacp->usb_ac_log_handle, 1610 "usb_ac_units[%d] ---selector unit: type=0x%x sub=0x%x" 1611 " unitid=0x%x\n\t" 1612 "#pins=0x%x sourceid[0]=0x%x", 1613 d->bUnitID, 1614 d->bDescriptorType, d->bDescriptorSubType, 1615 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 1616 usb_ac_alloc_unit(uacp, d->bUnitID); 1617 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 1618 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 1619 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 1620 1621 break; 1622 } 1623 case USB_AUDIO_FEATURE_UNIT: 1624 { 1625 usb_audio_feature_unit_descr1_t *d = 1626 (usb_audio_feature_unit_descr1_t *)descr; 1627 1628 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1629 uacp->usb_ac_log_handle, 1630 "usb_ac_units[%d] ---feature unit: type=0x%x sub=0x%x" 1631 " unitid=0x%x\n\t" 1632 "sourceid=0x%x size=0x%x", 1633 d->bUnitID, 1634 d->bDescriptorType, d->bDescriptorSubType, 1635 d->bUnitID, d->bSourceID, d->bControlSize); 1636 1637 usb_ac_alloc_unit(uacp, d->bUnitID); 1638 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 1639 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 1640 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 1641 1642 break; 1643 } 1644 case USB_AUDIO_PROCESSING_UNIT: 1645 { 1646 usb_audio_processing_unit_descr1_t *d = 1647 (usb_audio_processing_unit_descr1_t *)descr; 1648 1649 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1650 uacp->usb_ac_log_handle, 1651 "usb_ac_units[%d] ---processing unit: type=0x%x sub=0x%x" 1652 " unitid=0x%x\n\t" 1653 "#pins=0x%x sourceid[0]=0x%x", 1654 d->bUnitID, 1655 d->bDescriptorType, d->bDescriptorSubType, 1656 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 1657 usb_ac_alloc_unit(uacp, d->bUnitID); 1658 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 1659 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 1660 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 1661 1662 break; 1663 } 1664 case USB_AUDIO_EXTENSION_UNIT: 1665 { 1666 usb_audio_extension_unit_descr1_t *d = 1667 (usb_audio_extension_unit_descr1_t *)descr; 1668 1669 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1670 uacp->usb_ac_log_handle, 1671 "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x" 1672 " unitid=0x%x\n\t" 1673 "#pins=0x%x sourceid[0]=0x%x", 1674 d->bUnitID, 1675 d->bDescriptorType, d->bDescriptorSubType, 1676 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 1677 usb_ac_alloc_unit(uacp, d->bUnitID); 1678 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 1679 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 1680 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 1681 1682 break; 1683 } 1684 default: 1685 break; 1686 } 1687 } 1688 1689 1690 /* 1691 * usb_ac_alloc_unit: 1692 * check if the unit ID is less than max_unit in which case no 1693 * extra entries are needed. If more entries are needed, copy over 1694 * the existing array into a new larger array 1695 */ 1696 static void 1697 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit) 1698 { 1699 usb_ac_unit_list_t *old = NULL; 1700 uint_t max_unit; 1701 1702 1703 if (uacp->usb_ac_units) { 1704 if (unit < uacp->usb_ac_max_unit) { 1705 /* existing array is big enough */ 1706 1707 return; 1708 } 1709 old = uacp->usb_ac_units; 1710 max_unit = uacp->usb_ac_max_unit; 1711 } 1712 1713 /* allocate two extra ones */ 1714 unit += 2; 1715 uacp->usb_ac_max_unit = unit; 1716 uacp->usb_ac_units = kmem_zalloc(unit * 1717 sizeof (usb_ac_unit_list_t), KM_SLEEP); 1718 1719 if (old) { 1720 size_t len = max_unit * sizeof (usb_ac_unit_list_t); 1721 bcopy(old, uacp->usb_ac_units, len); 1722 1723 kmem_free(old, len); 1724 } 1725 } 1726 1727 1728 /* 1729 * usb_ac_free_all_units: 1730 * free the entire unit list 1731 */ 1732 static void 1733 usb_ac_free_all_units(usb_ac_state_t *uacp) 1734 { 1735 uint_t unit; 1736 usb_ac_unit_list_t *unitp; 1737 1738 if (uacp->usb_ac_units == NULL) { 1739 1740 return; 1741 } 1742 1743 1744 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) { 1745 unitp = &uacp->usb_ac_units[unit]; 1746 if (unitp) { 1747 if (unitp->acu_descriptor) { 1748 kmem_free(unitp->acu_descriptor, 1749 unitp->acu_descr_length); 1750 } 1751 } 1752 } 1753 1754 kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit * 1755 sizeof (usb_ac_unit_list_t)); 1756 } 1757 1758 1759 /* 1760 * usb_ac_lookup_port_type: 1761 * map term type to port type 1762 * default just return LINE_IN + LINE_OUT 1763 */ 1764 static int 1765 usb_ac_lookup_port_type(ushort_t termtype) 1766 { 1767 uint_t i; 1768 1769 /* 1770 * Looking for a input/ouput terminal type to match the port 1771 * type, it should not be common streaming type 1772 */ 1773 ASSERT(termtype != USB_AUDIO_TERM_TYPE_STREAMING); 1774 1775 for (i = 0; ; i++) { 1776 if (usb_ac_term_type_map[i].term_type == 0) { 1777 1778 break; 1779 } 1780 1781 if (usb_ac_term_type_map[i].term_type == termtype) { 1782 1783 return (usb_ac_term_type_map[i].port_type); 1784 } 1785 } 1786 1787 return (USB_PORT_UNKNOWN); 1788 } 1789 1790 1791 /* 1792 * usb_ac_update_port: 1793 * called for each terminal 1794 */ 1795 /*ARGSUSED*/ 1796 static int 1797 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id, 1798 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 1799 { 1800 if (dir & USB_AUDIO_PLAY) { 1801 usb_audio_output_term_descr_t *d = 1802 (usb_audio_output_term_descr_t *) 1803 uacp->usb_ac_units[id].acu_descriptor; 1804 uint_t port_type = 1805 usb_ac_lookup_port_type(d->wTerminalType); 1806 1807 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1808 "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s", 1809 dir, d->wTerminalType, usb_audio_dtypes[port_type]); 1810 1811 uacp->usb_ac_output_ports |= (1U << port_type); 1812 } else { 1813 usb_audio_input_term_descr_t *d = 1814 (usb_audio_input_term_descr_t *) 1815 uacp->usb_ac_units[id].acu_descriptor; 1816 uint_t port_type = 1817 usb_ac_lookup_port_type(d->wTerminalType); 1818 1819 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1820 "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s", 1821 dir, d->wTerminalType, usb_audio_dtypes[port_type]); 1822 1823 uacp->usb_ac_input_ports |= (1U << port_type); 1824 1825 } 1826 1827 return (USB_SUCCESS); 1828 } 1829 1830 1831 /* 1832 * usb_ac_map_termtype_to_port: 1833 * starting from a streaming termtype find all 1834 * input or output terminals and OR into uacp->usb_ac_input_ports 1835 * or uacp->usb_ac_output_ports; 1836 */ 1837 static void 1838 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir) 1839 { 1840 uint_t count = 0; 1841 uint_t depth = 0; 1842 uint_t search_type = (dir & USB_AUDIO_PLAY) ? 1843 USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL; 1844 1845 1846 (void) usb_ac_traverse_all_units(uacp, dir, search_type, 0, 1847 0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port); 1848 1849 ASSERT(depth == 0); 1850 } 1851 1852 1853 /* 1854 * usb_ac_set_port: 1855 * find a selector port (record side only) and set the 1856 * input to the matching pin 1857 */ 1858 static uint_t 1859 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port) 1860 { 1861 uint_t count = 0; 1862 uint_t id; 1863 uint_t depth = 0; 1864 1865 1866 /* we only support the selector for the record side */ 1867 if (dir & USB_AUDIO_RECORD) { 1868 id = usb_ac_traverse_all_units(uacp, dir, 1869 USB_AUDIO_SELECTOR_UNIT, 0, 1870 0, USB_AC_FIND_ONE, &count, port, &depth, 1871 usb_ac_set_selector); 1872 1873 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1874 "usb_ac_set_port: id=%d count=%d port=%d", 1875 id, count, port); 1876 1877 ASSERT(depth == 0); 1878 } 1879 1880 return (USB_SUCCESS); 1881 } 1882 1883 1884 /* 1885 * usb_ac_match_port: 1886 * given the requested port type, find a correspondig term type 1887 * Called from usb_ac_traverse_all_units() 1888 */ 1889 /*ARGSUSED*/ 1890 static int 1891 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id, 1892 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 1893 { 1894 uint_t port_type; 1895 1896 1897 if (dir & USB_AUDIO_PLAY) { 1898 usb_audio_output_term_descr_t *d = 1899 (usb_audio_output_term_descr_t *) 1900 uacp->usb_ac_units[id].acu_descriptor; 1901 port_type = usb_ac_lookup_port_type(d->wTerminalType); 1902 1903 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1904 "usb_ac_match_port: " 1905 "dir=%d type=0x%x port_type=%d port=%d", 1906 dir, d->wTerminalType, port_type, arg1); 1907 } else { 1908 usb_audio_output_term_descr_t *d = 1909 (usb_audio_output_term_descr_t *) 1910 uacp->usb_ac_units[id].acu_descriptor; 1911 port_type = usb_ac_lookup_port_type(d->wTerminalType); 1912 1913 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1914 "usb_ac_match_port: " 1915 "dir=%d type=0x%x port_type=%d port=%d", 1916 dir, d->wTerminalType, port_type, arg1); 1917 } 1918 1919 return (((1U << port_type) & arg1) ? USB_SUCCESS : USB_FAILURE); 1920 } 1921 1922 1923 /* 1924 * usb_ac_set_selector: 1925 * Called from usb_ac_traverse_all_units() 1926 * Find the correct pin and set selector to this pin 1927 */ 1928 /*ARGSUSED*/ 1929 static int 1930 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id, 1931 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 1932 { 1933 uint_t count = 0; 1934 uint_t unit = USB_AC_ID_NONE; 1935 uint_t pin; 1936 uint_t search_target = 1937 (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL : 1938 USB_AUDIO_INPUT_TERMINAL; 1939 usb_audio_selector_unit_descr1_t *d = 1940 (usb_audio_selector_unit_descr1_t *) 1941 uacp->usb_ac_units[id].acu_descriptor; 1942 int n_sourceID = d->bNrInPins; 1943 int rval = USB_FAILURE; 1944 1945 1946 /* 1947 * for each pin, find a term type that matches the 1948 * requested port type 1949 */ 1950 for (pin = 0; pin < n_sourceID; pin++) { 1951 if (d->baSourceID[pin] == 0) { 1952 1953 break; 1954 } 1955 unit = d->baSourceID[pin]; 1956 1957 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1958 "usb_ac_set_selector: pin=%d unit=%d", pin, unit); 1959 1960 if (uacp->usb_ac_unit_type[unit] == search_target) { 1961 if (usb_ac_match_port(uacp, unit, dir, channel, 1962 control, arg1, depth) == USB_SUCCESS) { 1963 1964 break; 1965 } else { 1966 unit = USB_AC_ID_NONE; 1967 1968 continue; 1969 } 1970 } 1971 1972 /* find units connected to this unit */ 1973 unit = usb_ac_traverse_connections(uacp, unit, 1974 dir, search_target, channel, control, 1975 USB_AC_FIND_ONE, &count, arg1, depth, 1976 usb_ac_match_port); 1977 1978 if (unit != USB_AC_ID_NONE) { 1979 1980 break; 1981 } 1982 } 1983 1984 1985 if (unit != USB_AC_ID_NONE) { 1986 mblk_t *data; 1987 usb_cr_t cr; 1988 usb_cb_flags_t cb_flags; 1989 1990 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1991 "usb_ac_set_selector: found id=%d at pin %d", unit, pin); 1992 1993 mutex_exit(&uacp->usb_ac_mutex); 1994 1995 data = allocb(1, BPRI_HI); 1996 if (!data) { 1997 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1998 "usb_ac_set_selector: allocate data failed"); 1999 mutex_enter(&uacp->usb_ac_mutex); 2000 2001 return (USB_FAILURE); 2002 } 2003 2004 /* pins are 1-based */ 2005 *(data->b_rptr) = (char)++pin; 2006 2007 if (usb_pipe_sync_ctrl_xfer( 2008 uacp->usb_ac_dip, 2009 uacp->usb_ac_default_ph, 2010 USB_DEV_REQ_HOST_TO_DEV | 2011 USB_DEV_REQ_TYPE_CLASS | 2012 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 2013 USB_AUDIO_SET_CUR, /* bRequest */ 2014 0, /* wValue */ 2015 /* feature unit and id */ 2016 (id << 8)| uacp->usb_ac_ifno, /* wIndex */ 2017 1, /* wLength */ 2018 &data, 2019 USB_ATTRS_NONE, 2020 &cr, &cb_flags, 2021 USB_FLAGS_SLEEP) == USB_SUCCESS) { 2022 USB_DPRINTF_L3(PRINT_MASK_ALL, 2023 uacp->usb_ac_log_handle, 2024 "set current selection: %d", *data->b_rptr); 2025 2026 rval = USB_SUCCESS; 2027 } else { 2028 USB_DPRINTF_L2(PRINT_MASK_ALL, 2029 uacp->usb_ac_log_handle, 2030 "set current pin selection failed"); 2031 } 2032 freemsg(data); 2033 2034 mutex_enter(&uacp->usb_ac_mutex); 2035 } else { 2036 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2037 "usb_ac_set_selector: nothing found"); 2038 } 2039 2040 return (rval); 2041 } 2042 2043 2044 /* 2045 * usb_ac_set_control: 2046 * apply func to all units of search_target type for both the 2047 * requested channel and master channel 2048 */ 2049 static uint_t 2050 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target, 2051 uint_t channel, uint_t control, uint_t all_or_one, 2052 uint_t *count, uint_t arg1, 2053 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2054 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2055 { 2056 uint_t id; 2057 uint_t depth = 0; 2058 2059 id = usb_ac_traverse_all_units(uacp, dir, search_target, channel, 2060 control, all_or_one, count, arg1, &depth, func); 2061 2062 if ((channel != 0) && 2063 (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) || 2064 (all_or_one == USB_AC_FIND_ALL))) { 2065 /* try master channel */ 2066 channel = 0; 2067 id = usb_ac_traverse_all_units(uacp, dir, search_target, 2068 channel, control, all_or_one, count, arg1, 2069 &depth, func); 2070 } 2071 2072 ASSERT(depth == 0); 2073 2074 return (id); 2075 } 2076 2077 2078 /* 2079 * usb_ac_traverse_all_units: 2080 * traverse all units starting with all IT or OT depending on direction. 2081 * If no unit is found for the particular channel, try master channel 2082 * If a matching unit is found, apply the function passed by 2083 * the caller 2084 */ 2085 static uint_t 2086 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir, 2087 uint_t search_target, uint_t channel, uint_t control, 2088 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth, 2089 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2090 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2091 { 2092 uint_t unit, start_type, id; 2093 2094 start_type = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL : 2095 USB_AUDIO_OUTPUT_TERMINAL; 2096 2097 /* keep track of recursion */ 2098 if ((*depth)++ > USB_AC_MAX_DEPTH) { 2099 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2100 "Unit topology too complex, giving up"); 2101 2102 return (USB_AC_ID_NONE); 2103 } 2104 2105 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2106 /* is this an IT or OT? */ 2107 if (uacp->usb_ac_unit_type[unit] != start_type) { 2108 2109 continue; 2110 } 2111 2112 /* start at streaming term types */ 2113 if (dir & USB_AUDIO_PLAY) { 2114 usb_audio_input_term_descr_t *d = 2115 uacp->usb_ac_units[unit].acu_descriptor; 2116 if (d->wTerminalType != 2117 USB_AUDIO_TERM_TYPE_STREAMING) { 2118 2119 continue; 2120 } 2121 } else { 2122 usb_audio_output_term_descr_t *d = 2123 uacp->usb_ac_units[unit].acu_descriptor; 2124 if (d->wTerminalType != 2125 USB_AUDIO_TERM_TYPE_STREAMING) { 2126 2127 continue; 2128 } 2129 } 2130 2131 /* find units connected to this unit */ 2132 id = usb_ac_traverse_connections(uacp, unit, dir, 2133 search_target, channel, control, all_or_one, count, 2134 arg1, depth, func); 2135 2136 if ((all_or_one == USB_AC_FIND_ONE) && 2137 (id != USB_AC_ID_NONE)) { 2138 unit = id; 2139 2140 break; 2141 } 2142 } 2143 2144 (*depth)--; 2145 2146 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE); 2147 } 2148 2149 2150 /* 2151 * usb_ac_set_monitor_gain_control: 2152 * search for a feature unit between output terminal (OT) and 2153 * input terminal. We are looking for a path between 2154 * for example a microphone and a speaker through a feature unit 2155 * and mixer 2156 */ 2157 static uint_t 2158 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir, 2159 uint_t search_target, uint_t channel, uint_t control, 2160 uint_t all_or_one, uint_t *count, uint_t arg1, 2161 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2162 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2163 { 2164 uint_t unit, id; 2165 uint_t depth = 0; 2166 2167 2168 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2169 usb_audio_output_term_descr_t *d = 2170 uacp->usb_ac_units[unit].acu_descriptor; 2171 2172 /* is this an OT and not stream type? */ 2173 if ((uacp->usb_ac_unit_type[unit] == 2174 USB_AUDIO_OUTPUT_TERMINAL) && 2175 (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) { 2176 2177 /* find units connected to this unit */ 2178 id = usb_ac_traverse_connections(uacp, unit, dir, 2179 search_target, channel, control, all_or_one, count, 2180 arg1, &depth, func); 2181 2182 if ((all_or_one == USB_AC_FIND_ONE) && 2183 (id != USB_AC_ID_NONE)) { 2184 2185 break; 2186 } 2187 } 2188 } 2189 2190 ASSERT(depth == 0); 2191 2192 return (id); 2193 } 2194 2195 2196 /* 2197 * usb_ac_push/pop_unit 2198 * add/remove unit ID to the traverse path 2199 */ 2200 static void 2201 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit) 2202 { 2203 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] = 2204 (uchar_t)unit; 2205 ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit); 2206 } 2207 2208 2209 /* ARGSUSED */ 2210 static void 2211 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit) 2212 { 2213 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0; 2214 } 2215 2216 2217 /* 2218 * usb_ac_show_traverse_path: 2219 * display entire path, just for debugging 2220 */ 2221 static void 2222 usb_ac_show_traverse_path(usb_ac_state_t *uacp) 2223 { 2224 int i; 2225 2226 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) { 2227 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2228 "traverse path %d: unit=%d type=%d", 2229 i, uacp->usb_ac_traverse_path[i], 2230 uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]); 2231 } 2232 } 2233 2234 2235 /* 2236 * usb_ac_check_path: 2237 * check for a specified type in the traverse path 2238 */ 2239 static int 2240 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type) 2241 { 2242 int i; 2243 2244 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) { 2245 uint_t unit = uacp->usb_ac_traverse_path[i]; 2246 2247 if (uacp->usb_ac_unit_type[unit] == type) { 2248 2249 return (USB_SUCCESS); 2250 } 2251 } 2252 2253 return (USB_FAILURE); 2254 } 2255 2256 2257 /* 2258 * usb_ac_traverse_connections: 2259 * traverse all units and for each unit with the right type, call 2260 * func. If the func returns a success and search == USB_AC_FIND_ONE, 2261 * we are done. If all is set then we continue until we terminate 2262 * and input or output terminal. 2263 * For audio play, we traverse columns starting from an input terminal 2264 * to an output terminal while for record we traverse rows from output 2265 * terminal to input terminal. 2266 */ 2267 static uint_t 2268 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir, 2269 uint_t search_target, uint_t channel, uint_t control, 2270 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth, 2271 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2272 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2273 { 2274 uint_t unit, id; 2275 uint_t done = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL : 2276 USB_AUDIO_INPUT_TERMINAL; 2277 2278 2279 /* keep track of recursion depth */ 2280 if ((*depth)++ > USB_AC_MAX_DEPTH) { 2281 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2282 "Unit topology too complex, giving up"); 2283 2284 return (USB_AC_ID_NONE); 2285 } 2286 2287 usb_ac_push_unit_id(uacp, start_unit); 2288 2289 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2290 uint_t entry = (dir & USB_AUDIO_PLAY) ? 2291 uacp->usb_ac_connections[unit][start_unit] : 2292 uacp->usb_ac_connections[start_unit][unit]; 2293 2294 if (entry) { 2295 USB_DPRINTF_L3(PRINT_MASK_ALL, 2296 uacp->usb_ac_log_handle, 2297 "start=%d unit=%d entry=%d type=%d " 2298 "done=%d found=%d", 2299 start_unit, unit, entry, search_target, done, 2300 uacp->usb_ac_unit_type[unit]); 2301 2302 /* did we find a matching type? */ 2303 if (uacp->usb_ac_unit_type[unit] == search_target) { 2304 USB_DPRINTF_L3(PRINT_MASK_ALL, 2305 uacp->usb_ac_log_handle, 2306 "match: dir=%d unit=%d type=%d", 2307 dir, unit, search_target); 2308 2309 /* yes, no apply function to this unit */ 2310 if (func(uacp, unit, dir, channel, 2311 control, arg1, depth) == USB_SUCCESS) { 2312 (*count)++; 2313 2314 USB_DPRINTF_L3(PRINT_MASK_ALL, 2315 uacp->usb_ac_log_handle, 2316 "func returned success, " 2317 "unit=%d all=%d", unit, 2318 all_or_one); 2319 2320 /* are we done? */ 2321 if (all_or_one == USB_AC_FIND_ONE) { 2322 2323 break; 2324 } 2325 } 2326 } 2327 2328 /* did we find the terminating unit */ 2329 if (uacp->usb_ac_unit_type[unit] == done) { 2330 2331 continue; 2332 } 2333 id = usb_ac_traverse_connections(uacp, unit, dir, 2334 search_target, channel, control, 2335 all_or_one, count, arg1, depth, func); 2336 if ((id != USB_AC_ID_NONE) && 2337 (all_or_one == USB_AC_FIND_ONE)) { 2338 unit = id; 2339 2340 break; 2341 } 2342 } 2343 } 2344 2345 (*depth)--; 2346 usb_ac_pop_unit_id(uacp, start_unit); 2347 2348 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE); 2349 } 2350 2351 2352 /* 2353 * Event Management 2354 * 2355 * usb_ac_disconnect_event_cb: 2356 * The device has been disconnected. we either wait for 2357 * detach or a reconnect event. 2358 */ 2359 static int 2360 usb_ac_disconnect_event_cb(dev_info_t *dip) 2361 { 2362 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2363 usb_ac_statep, ddi_get_instance(dip)); 2364 2365 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2366 "usb_ac_disconnect_event_cb:start"); 2367 2368 usb_ac_serialize_access(uacp); 2369 mutex_enter(&uacp->usb_ac_mutex); 2370 2371 /* setting to disconnect state will prevent replumbing */ 2372 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED; 2373 2374 if (uacp->usb_ac_busy_count) { 2375 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2376 "device was disconnected while busy. " 2377 "Data may have been lost"); 2378 } 2379 mutex_exit(&uacp->usb_ac_mutex); 2380 2381 usb_ac_release_access(uacp); 2382 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2383 "usb_ac_disconnect_event_cb:done"); 2384 2385 2386 return (USB_SUCCESS); 2387 } 2388 2389 2390 /* 2391 * usb_ac_cpr_suspend: 2392 */ 2393 static int 2394 usb_ac_cpr_suspend(dev_info_t *dip) 2395 { 2396 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2397 usb_ac_statep, ddi_get_instance(dip)); 2398 2399 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2400 "usb_ac_cpr_suspend: Begin"); 2401 2402 mutex_enter(&uacp->usb_ac_mutex); 2403 uacp->usb_ac_dev_state = USB_DEV_SUSPENDED; 2404 mutex_exit(&uacp->usb_ac_mutex); 2405 2406 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2407 "usb_ac_cpr_suspend: End"); 2408 2409 return (USB_SUCCESS); 2410 } 2411 2412 2413 2414 /* 2415 * usb_ac_reconnect_event_cb: 2416 * The device was disconnected but this instance not detached, probably 2417 * because the device was busy. 2418 * if the same device, continue with restoring state 2419 * We should either be in the unplumbed state or the plumbed open 2420 * state. 2421 */ 2422 static int 2423 usb_ac_reconnect_event_cb(dev_info_t *dip) 2424 { 2425 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2426 usb_ac_statep, ddi_get_instance(dip)); 2427 2428 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2429 "usb_ac_reconnect_event_cb:begain"); 2430 2431 mutex_enter(&uacp->usb_ac_mutex); 2432 mutex_exit(&uacp->usb_ac_mutex); 2433 2434 usb_ac_serialize_access(uacp); 2435 2436 /* check the plumbing state */ 2437 mutex_enter(&uacp->usb_ac_mutex); 2438 uacp->usb_ac_busy_count++; 2439 if (uacp->usb_ac_plumbing_state == 2440 USB_AC_STATE_PLUMBED) { 2441 mutex_exit(&uacp->usb_ac_mutex); 2442 usb_ac_restore_device_state(dip, uacp); 2443 mutex_enter(&uacp->usb_ac_mutex); 2444 } 2445 uacp->usb_ac_busy_count--; 2446 2447 if (uacp->usb_ac_busy_count) { 2448 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2449 "busy device has been reconnected"); 2450 } 2451 2452 mutex_exit(&uacp->usb_ac_mutex); 2453 2454 usb_ac_release_access(uacp); 2455 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2456 "usb_ac_reconnect_event_cb:done"); 2457 2458 return (USB_SUCCESS); 2459 } 2460 2461 2462 /* 2463 * usb_ac_cpr_resume: 2464 * Restore device state 2465 */ 2466 static void 2467 usb_ac_cpr_resume(dev_info_t *dip) 2468 { 2469 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2470 usb_ac_statep, ddi_get_instance(dip)); 2471 2472 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2473 "usb_ac_cpr_resume"); 2474 2475 usb_ac_serialize_access(uacp); 2476 2477 usb_ac_restore_device_state(dip, uacp); 2478 2479 usb_ac_release_access(uacp); 2480 } 2481 2482 2483 /* 2484 * usb_ac_restore_device_state: 2485 * Set original configuration of the device 2486 * enable wrq - this starts new transactions on the control pipe 2487 */ 2488 static void 2489 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp) 2490 { 2491 usb_ac_power_t *uacpm; 2492 int rval; 2493 2494 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2495 "usb_ac_restore_device_state:"); 2496 2497 usb_ac_pm_busy_component(uacp); 2498 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 2499 2500 /* Check if we are talking to the same device */ 2501 if (usb_check_same_device(dip, uacp->usb_ac_log_handle, 2502 USB_LOG_L0, PRINT_MASK_ALL, 2503 USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) { 2504 usb_ac_pm_idle_component(uacp); 2505 2506 /* change the device state from suspended to disconnected */ 2507 mutex_enter(&uacp->usb_ac_mutex); 2508 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED; 2509 mutex_exit(&uacp->usb_ac_mutex); 2510 2511 return; 2512 } 2513 2514 mutex_enter(&uacp->usb_ac_mutex); 2515 uacpm = uacp->usb_ac_pm; 2516 if (uacpm) { 2517 if (uacpm->acpm_wakeup_enabled) { 2518 mutex_exit(&uacp->usb_ac_mutex); 2519 2520 if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip, 2521 USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) { 2522 2523 USB_DPRINTF_L4(PRINT_MASK_ATTA, 2524 uacp->usb_ac_log_handle, 2525 "usb_ac_restore_device_state: " 2526 "remote wakeup " 2527 "enable failed, rval=%d", rval); 2528 } 2529 2530 mutex_enter(&uacp->usb_ac_mutex); 2531 } 2532 } 2533 2534 /* prevent unplumbing */ 2535 uacp->usb_ac_busy_count++; 2536 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 2537 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) { 2538 (void) usb_ac_restore_audio_state(uacp, 0); 2539 } 2540 uacp->usb_ac_busy_count--; 2541 mutex_exit(&uacp->usb_ac_mutex); 2542 usb_ac_pm_idle_component(uacp); 2543 } 2544 2545 2546 /* 2547 * usb_ac_am_restore_state 2548 */ 2549 static void 2550 usb_ac_am_restore_state(void *arg) 2551 { 2552 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 2553 2554 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2555 "usb_ac_am_restore_state: Begin"); 2556 2557 usb_ac_serialize_access(uacp); 2558 2559 mutex_enter(&uacp->usb_ac_mutex); 2560 2561 if (uacp->usb_ac_plumbing_state == 2562 USB_AC_STATE_PLUMBED_RESTORING) { 2563 mutex_exit(&uacp->usb_ac_mutex); 2564 2565 /* 2566 * allow hid and usb_as to restore themselves 2567 * (some handshake would have been preferable though) 2568 */ 2569 delay(USB_AC_RESTORE_DELAY); 2570 2571 usb_restore_engine(uacp); 2572 2573 mutex_enter(&uacp->usb_ac_mutex); 2574 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 2575 } 2576 2577 /* allow unplumbing */ 2578 uacp->usb_ac_busy_count--; 2579 mutex_exit(&uacp->usb_ac_mutex); 2580 2581 usb_ac_release_access(uacp); 2582 2583 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2584 "usb_ac_am_restore_state: End"); 2585 } 2586 2587 2588 /* 2589 * usb_ac_restore_audio_state: 2590 */ 2591 static int 2592 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag) 2593 { 2594 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 2595 2596 2597 switch (uacp->usb_ac_plumbing_state) { 2598 case USB_AC_STATE_PLUMBED: 2599 uacp->usb_ac_plumbing_state = 2600 USB_AC_STATE_PLUMBED_RESTORING; 2601 2602 break; 2603 case USB_AC_STATE_UNPLUMBED: 2604 2605 return (USB_SUCCESS); 2606 case USB_AC_STATE_PLUMBED_RESTORING: 2607 default: 2608 2609 return (USB_FAILURE); 2610 } 2611 2612 /* 2613 * increment busy_count again, it will be decremented 2614 * in usb_ac_am_restore_state 2615 */ 2616 uacp->usb_ac_busy_count++; 2617 2618 if (flag & USB_FLAGS_SLEEP) { 2619 mutex_exit(&uacp->usb_ac_mutex); 2620 usb_ac_am_restore_state((void *)uacp); 2621 mutex_enter(&uacp->usb_ac_mutex); 2622 } else { 2623 mutex_exit(&uacp->usb_ac_mutex); 2624 if (usb_async_req(uacp->usb_ac_dip, 2625 usb_ac_am_restore_state, 2626 (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) { 2627 2628 mutex_enter(&uacp->usb_ac_mutex); 2629 uacp->usb_ac_busy_count--; 2630 2631 return (USB_FAILURE); 2632 } 2633 mutex_enter(&uacp->usb_ac_mutex); 2634 } 2635 2636 return (USB_SUCCESS); 2637 } 2638 2639 2640 /* 2641 * Mixer Callback Management 2642 * NOTE: all mixer callbacks are serialized. we cannot be closed while 2643 * we are in the middle of a callback. There needs to be a 2644 * teardown first. We cannot be unplumbed as long as we are 2645 * still open. 2646 * 2647 * usb_ac_setup: 2648 * Send setup to usb_as if the first setup 2649 * Check power is done in usb_ac_send_as_cmd() 2650 */ 2651 static int 2652 usb_ac_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 2653 { 2654 int rval = USB_SUCCESS; 2655 2656 2657 mutex_enter(&uacp->usb_ac_mutex); 2658 2659 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 2660 mutex_exit(&uacp->usb_ac_mutex); 2661 2662 return (USB_FAILURE); 2663 } 2664 mutex_exit(&uacp->usb_ac_mutex); 2665 2666 usb_ac_serialize_access(uacp); 2667 2668 2669 rval = usb_ac_do_setup(uacp, engine); 2670 2671 usb_ac_release_access(uacp); 2672 2673 return (rval); 2674 } 2675 2676 2677 /* 2678 * usb_ac_do_setup: 2679 * Wrapper function for usb_ac_setup which can be called 2680 * either from audio framework for usb_ac_set_format 2681 */ 2682 static int 2683 usb_ac_do_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 2684 { 2685 usb_ac_streams_info_t *streams_infop = NULL; 2686 2687 2688 mutex_enter(&uacp->usb_ac_mutex); 2689 2690 2691 streams_infop = (usb_ac_streams_info_t *)engine->streams; 2692 2693 /* 2694 * Handle multiple setup calls. Pass the setup call to usb_as only 2695 * the first time so isoc pipe will be opened only once 2696 */ 2697 if (streams_infop->acs_setup_teardown_count++) { 2698 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2699 "usb_ac_do_setup: more than one setup, cnt=%d", 2700 streams_infop->acs_setup_teardown_count); 2701 2702 mutex_exit(&uacp->usb_ac_mutex); 2703 2704 return (USB_SUCCESS); 2705 } 2706 2707 /* Send setup command to usb_as */ 2708 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SETUP, 0) != 2709 USB_SUCCESS) { 2710 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2711 "usb_ac_do_setup: failure"); 2712 2713 streams_infop->acs_setup_teardown_count--; 2714 2715 mutex_exit(&uacp->usb_ac_mutex); 2716 2717 return (USB_FAILURE); 2718 } 2719 2720 mutex_exit(&uacp->usb_ac_mutex); 2721 2722 return (USB_SUCCESS); 2723 } 2724 2725 2726 /* 2727 * usb_ac_teardown: 2728 * Send teardown to usb_as if the last teardown 2729 * Check power is done in usb_ac_send_as_cmd() 2730 * NOTE: allow teardown when disconnected 2731 */ 2732 static void 2733 usb_ac_teardown(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 2734 { 2735 2736 usb_ac_streams_info_t *streams_infop = NULL; 2737 2738 usb_ac_serialize_access(uacp); 2739 2740 2741 streams_infop = engine->streams; 2742 2743 2744 mutex_enter(&uacp->usb_ac_mutex); 2745 2746 2747 2748 /* There should be at least one matching setup call */ 2749 ASSERT(streams_infop->acs_setup_teardown_count); 2750 2751 /* 2752 * Handle multiple setup/teardown calls. Pass the call to usb_as 2753 * only this is the last teardown so that isoc pipe is closed 2754 * only once 2755 */ 2756 if (--(streams_infop->acs_setup_teardown_count)) { 2757 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2758 "usb_ac_teardown: more than one setup/teardown, " 2759 "cnt=%d", 2760 streams_infop->acs_setup_teardown_count); 2761 2762 goto done; 2763 } 2764 2765 /* Send teardown command to usb_as */ 2766 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_TEARDOWN, 2767 (void *)NULL) != USB_SUCCESS) { 2768 2769 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2770 "usb_ac_teardown: failure"); 2771 2772 streams_infop->acs_setup_teardown_count++; 2773 2774 2775 goto done; 2776 } 2777 done: 2778 2779 mutex_exit(&uacp->usb_ac_mutex); 2780 2781 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2782 "usb_ac_teardown: End"); 2783 usb_ac_release_access(uacp); 2784 } 2785 2786 2787 /* 2788 * usb_ac_set_monitor_gain: 2789 * called for each output terminal which supports 2790 * from usb_ac_traverse_connections 2791 */ 2792 static int 2793 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit, 2794 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth) 2795 { 2796 usb_audio_output_term_descr_t *d = 2797 uacp->usb_ac_units[unit].acu_descriptor; 2798 2799 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2800 "usb_ac_set_monitor_gain: "); 2801 2802 /* log how we got here */ 2803 usb_ac_push_unit_id(uacp, unit); 2804 usb_ac_show_traverse_path(uacp); 2805 usb_ac_pop_unit_id(uacp, unit); 2806 2807 /* we only care about the ITs connected to real hw inputs */ 2808 switch (d->wTerminalType) { 2809 case USB_AUDIO_TERM_TYPE_STREAMING: 2810 2811 return (USB_FAILURE); 2812 2813 case USB_AUDIO_TERM_TYPE_DT_MICROPHONE: 2814 case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE: 2815 case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE: 2816 case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY: 2817 case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY: 2818 default: 2819 2820 break; 2821 } 2822 2823 /* 2824 * we can only do this if the microphone is mixed into the 2825 * audio output so look for a mixer first 2826 */ 2827 if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) == 2828 USB_SUCCESS) { 2829 int i, id; 2830 2831 /* now look for a feature unit */ 2832 for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0; 2833 i--) { 2834 id = uacp->usb_ac_traverse_path[i]; 2835 2836 switch (uacp->usb_ac_unit_type[id]) { 2837 case USB_AUDIO_MIXER_UNIT: 2838 2839 /* the FU should be before the mixer */ 2840 return (USB_FAILURE); 2841 2842 case USB_AUDIO_FEATURE_UNIT: 2843 /* 2844 * now set the volume 2845 */ 2846 if (usb_ac_set_gain(uacp, id, dir, channel, 2847 control, gain, depth) != USB_SUCCESS) { 2848 2849 /* try master channel */ 2850 if (usb_ac_set_gain(uacp, id, dir, 2851 0, control, gain, depth) != 2852 USB_SUCCESS) { 2853 2854 return (USB_FAILURE); 2855 } 2856 } 2857 2858 return (USB_SUCCESS); 2859 2860 default: 2861 continue; 2862 } 2863 } 2864 } 2865 2866 return (USB_FAILURE); 2867 } 2868 2869 2870 /* 2871 * usb_ac_set_gain is called for each feature unit which supports 2872 * the requested controls from usb_ac_traverse_connections 2873 * we still need to check whether this unit supports the requested 2874 * control. 2875 */ 2876 static int 2877 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID, 2878 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth) 2879 { 2880 short max, min, current; 2881 2882 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2883 "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d", 2884 featureID, dir, channel, control, gain); 2885 2886 if (usb_ac_feature_unit_check(uacp, featureID, 2887 dir, channel, control, gain, depth) != USB_SUCCESS) { 2888 2889 return (USB_FAILURE); 2890 } 2891 2892 if (usb_ac_get_maxmin_volume(uacp, channel, 2893 USB_AUDIO_GET_MAX, dir, featureID, &max) != USB_SUCCESS) { 2894 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2895 "usb_ac_set_gain: getting max gain failed"); 2896 2897 return (USB_FAILURE); 2898 } 2899 2900 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2901 "usb_ac_set_gain: channel %d, max=%d", channel, max); 2902 2903 if (usb_ac_get_maxmin_volume(uacp, channel, 2904 USB_AUDIO_GET_MIN, dir, featureID, &min) != USB_SUCCESS) { 2905 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2906 "usb_ac_set_gain: getting min gain failed"); 2907 2908 return (USB_FAILURE); 2909 } 2910 2911 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2912 "usb_ac_set_gain: channel=%d, min=%d", channel, min); 2913 2914 if (usb_ac_get_maxmin_volume(uacp, channel, 2915 USB_AUDIO_GET_CUR, dir, featureID, ¤t) != USB_SUCCESS) { 2916 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2917 "usb_ac_set_gain: getting cur gain failed"); 2918 2919 return (USB_FAILURE); 2920 } 2921 2922 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2923 "usb_ac_set_gain: channel=%d, cur=%d", channel, current); 2924 2925 /* 2926 * Set the gain for a channel. The audio mixer calculates the 2927 * impact, if any, on the channel's gain. 2928 * 2929 * 0 <= gain <= AUDIO_MAX_GAIN 2930 * 2931 * channel #, 0 == left, 1 == right 2932 */ 2933 2934 if (gain == 0) { 2935 gain = USB_AUDIO_VOLUME_SILENCE; 2936 } else { 2937 gain = max - ((max - min) * (AF_MAX_GAIN - gain))/AF_MAX_GAIN; 2938 } 2939 2940 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2941 "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d", 2942 channel, dir, max, min, gain); 2943 2944 if (usb_ac_set_volume(uacp, channel, gain, dir, 2945 featureID) != USB_SUCCESS) { 2946 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2947 "usb_ac_set_gain: setting volume failed"); 2948 2949 return (USB_FAILURE); 2950 } 2951 2952 /* just curious, read it back, device may round up/down */ 2953 if (usb_ac_get_maxmin_volume(uacp, channel, 2954 USB_AUDIO_GET_CUR, dir, featureID, ¤t) != USB_SUCCESS) { 2955 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2956 "usb_ac_set_gain: getting cur gain failed"); 2957 } 2958 2959 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2960 "usb_ac_set_gain done: " 2961 "id=%d channel=%d, cur=%d gain=%d", featureID, channel, 2962 (ushort_t)current, (ushort_t)gain); 2963 2964 return (USB_SUCCESS); 2965 } 2966 2967 2968 /* 2969 * usb_ac_set_format 2970 * This mixer callback initiates a command to be sent to 2971 * usb_as to select an alternate with the passed characteristics 2972 * and also to set the sample frequency. 2973 * Note that this may be called when a playing is going on in 2974 * the streaming interface. To handle that, first stop 2975 * playing/recording, close the pipe by sending a teardown 2976 * command, send the set_format command down and then reopen 2977 * the pipe. Note : (1) audio framework will restart play/record 2978 * after a set_format command. (2) Check power is done in 2979 * usb_ac_send_as_cmd(). 2980 */ 2981 int 2982 usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 2983 { 2984 usb_ac_streams_info_t *streams_infop = NULL; 2985 usb_audio_formats_t format; 2986 int old_setup_teardown_count = 0; 2987 2988 mutex_enter(&uacp->usb_ac_mutex); 2989 streams_infop = (usb_ac_streams_info_t *)engine->streams; 2990 2991 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 2992 mutex_exit(&uacp->usb_ac_mutex); 2993 2994 return (USB_FAILURE); 2995 } 2996 mutex_exit(&uacp->usb_ac_mutex); 2997 2998 usb_ac_serialize_access(uacp); 2999 mutex_enter(&uacp->usb_ac_mutex); 3000 3001 bzero(&format, sizeof (usb_audio_formats_t)); 3002 3003 /* save format info */ 3004 format.fmt_n_srs = 1; 3005 format.fmt_srs = (uint_t *)&(engine->fmt.sr); 3006 format.fmt_chns = (uchar_t)engine->fmt.ch; 3007 format.fmt_precision = (uchar_t)engine->fmt.prec; 3008 format.fmt_encoding = (uchar_t)engine->fmt.enc; 3009 3010 old_setup_teardown_count = streams_infop->acs_setup_teardown_count; 3011 3012 /* isoc pipe not open and playing is not in progress */ 3013 if (old_setup_teardown_count) { 3014 streams_infop->acs_setup_teardown_count = 1; 3015 3016 mutex_exit(&uacp->usb_ac_mutex); 3017 usb_ac_release_access(uacp); 3018 3019 usb_ac_stop_play(uacp, engine); 3020 usb_ac_teardown(uacp, engine); 3021 3022 usb_ac_serialize_access(uacp); 3023 mutex_enter(&uacp->usb_ac_mutex); 3024 } 3025 3026 /* 3027 * Set format for the streaming interface with lower write queue 3028 * This boils down to set_alternate interface command in 3029 * usb_as and the reply mp contains the currently active 3030 * alternate number that is stored in the as_req structure 3031 */ 3032 if (usb_ac_send_as_cmd(uacp, engine, 3033 USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) { 3034 USB_DPRINTF_L2(PRINT_MASK_ALL, 3035 uacp->usb_ac_log_handle, 3036 "usb_ac_set_format: failed"); 3037 goto fail; 3038 3039 } 3040 int sample = engine->fmt.sr; 3041 3042 /* Set the sample rate */ 3043 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ, 3044 &sample) != USB_SUCCESS) { 3045 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3046 "usb_ac_set_format: setting format failed"); 3047 goto fail; 3048 3049 } 3050 3051 mutex_exit(&uacp->usb_ac_mutex); 3052 3053 usb_ac_release_access(uacp); 3054 3055 /* This should block until successful */ 3056 if (old_setup_teardown_count) { 3057 (void) usb_ac_setup(uacp, engine); 3058 } 3059 3060 mutex_enter(&uacp->usb_ac_mutex); 3061 streams_infop->acs_setup_teardown_count = old_setup_teardown_count; 3062 mutex_exit(&uacp->usb_ac_mutex); 3063 3064 return (USB_SUCCESS); 3065 fail: 3066 streams_infop->acs_setup_teardown_count = old_setup_teardown_count; 3067 mutex_exit(&uacp->usb_ac_mutex); 3068 usb_ac_release_access(uacp); 3069 3070 return (USB_FAILURE); 3071 3072 } 3073 3074 /* 3075 * usb_ac_start_play 3076 * Send a start_play command down to usb_as 3077 * Check power is done in usb_ac_send_as_cmd() 3078 */ 3079 static int 3080 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3081 { 3082 int samples; 3083 usb_audio_play_req_t play_req; 3084 3085 3086 mutex_enter(&uacp->usb_ac_mutex); 3087 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3088 mutex_exit(&uacp->usb_ac_mutex); 3089 3090 return (USB_FAILURE); 3091 } 3092 mutex_exit(&uacp->usb_ac_mutex); 3093 3094 usb_ac_serialize_access(uacp); 3095 3096 mutex_enter(&uacp->usb_ac_mutex); 3097 3098 3099 3100 /* Check for continuous sample rate done in usb_as */ 3101 samples = engine->fmt.sr * engine->fmt.ch / engine->intrate; 3102 if (samples & engine->fmt.ch) { 3103 samples++; 3104 } 3105 3106 play_req.up_samples = samples; 3107 play_req.up_handle = uacp; 3108 3109 /* Send setup command to usb_as */ 3110 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY, 3111 (void *)&play_req) != USB_SUCCESS) { 3112 3113 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3114 "usb_ac_start_play: failure"); 3115 3116 mutex_exit(&uacp->usb_ac_mutex); 3117 3118 usb_ac_release_access(uacp); 3119 3120 return (USB_FAILURE); 3121 } 3122 3123 mutex_exit(&uacp->usb_ac_mutex); 3124 3125 usb_ac_release_access(uacp); 3126 3127 return (USB_SUCCESS); 3128 } 3129 3130 3131 /* 3132 * usb_ac_stop_play: 3133 * Stop the play engine 3134 * called from mixer framework. 3135 */ 3136 void 3137 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3138 { 3139 3140 if (engine == NULL) { 3141 engine = &(uacp->engines[0]); 3142 } 3143 mutex_enter(&uacp->usb_ac_mutex); 3144 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3145 mutex_exit(&uacp->usb_ac_mutex); 3146 3147 return; 3148 } 3149 mutex_exit(&uacp->usb_ac_mutex); 3150 3151 usb_ac_serialize_access(uacp); 3152 mutex_enter(&uacp->usb_ac_mutex); 3153 3154 /* Send setup command to usb_as */ 3155 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY, 3156 (void *)NULL) != USB_SUCCESS) { 3157 3158 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3159 "usb_ac_do_pause_play: failure"); 3160 } 3161 3162 mutex_exit(&uacp->usb_ac_mutex); 3163 usb_ac_release_access(uacp); 3164 } 3165 3166 3167 /* 3168 * usb_ac_start_record: 3169 * Sends a start record command down to usb_as. 3170 * Check power is done in usb_ac_send_as_cmd() 3171 */ 3172 static int 3173 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3174 { 3175 3176 3177 mutex_enter(&uacp->usb_ac_mutex); 3178 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3179 mutex_exit(&uacp->usb_ac_mutex); 3180 3181 return (USB_FAILURE); 3182 } 3183 mutex_exit(&uacp->usb_ac_mutex); 3184 3185 usb_ac_serialize_access(uacp); 3186 mutex_enter(&uacp->usb_ac_mutex); 3187 3188 3189 /* Send setup command to usb_as */ 3190 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD, 3191 (void *)uacp) != USB_SUCCESS) { 3192 3193 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3194 "usb_ac_start_record: failure"); 3195 3196 mutex_exit(&uacp->usb_ac_mutex); 3197 3198 usb_ac_release_access(uacp); 3199 3200 return (USB_FAILURE); 3201 } 3202 3203 mutex_exit(&uacp->usb_ac_mutex); 3204 usb_ac_release_access(uacp); 3205 3206 return (USB_SUCCESS); 3207 } 3208 3209 3210 /* 3211 * usb_ac_stop_record: 3212 * Wrapper function for usb_ac_do_stop_record and is 3213 * called form mixer framework. 3214 */ 3215 static void 3216 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3217 { 3218 3219 usb_ac_serialize_access(uacp); 3220 mutex_enter(&uacp->usb_ac_mutex); 3221 3222 /* Send setup command to usb_as */ 3223 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD, 3224 NULL) != USB_SUCCESS) { 3225 3226 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3227 "usb_ac_do_stop_record: failure"); 3228 } 3229 3230 mutex_exit(&uacp->usb_ac_mutex); 3231 usb_ac_release_access(uacp); 3232 } 3233 3234 3235 /* 3236 * Helper Functions for Mixer callbacks 3237 * 3238 * usb_ac_get_maxmin_volume: 3239 * Send USBA command down to get the maximum or minimum gain balance 3240 * Calculate min or max gain balance and return that. Return 3241 * USB_FAILURE for failure cases 3242 */ 3243 /* ARGSUSED */ 3244 static int 3245 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd, 3246 int dir, int feature_unitID, short *max_or_minp) 3247 { 3248 mblk_t *data = NULL; 3249 usb_cr_t cr; 3250 usb_cb_flags_t cb_flags; 3251 3252 3253 mutex_exit(&uacp->usb_ac_mutex); 3254 3255 if (usb_pipe_sync_ctrl_xfer( 3256 uacp->usb_ac_dip, 3257 uacp->usb_ac_default_ph, 3258 USB_DEV_REQ_DEV_TO_HOST | 3259 USB_DEV_REQ_TYPE_CLASS | 3260 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 3261 cmd, /* bRequest */ 3262 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 3263 /* feature unit and id */ 3264 (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */ 3265 2, /* wLength */ 3266 &data, 3267 USB_ATTRS_NONE, 3268 &cr, &cb_flags, 3269 USB_FLAGS_SLEEP) != USB_SUCCESS) { 3270 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3271 "usb_ac_get_maxmin_volume: failed, " 3272 "cr=%d, cb=0x%x cmd=%d, data=0x%p", 3273 cr, cb_flags, cmd, (void *)data); 3274 3275 freemsg(data); 3276 mutex_enter(&uacp->usb_ac_mutex); 3277 3278 return (USB_FAILURE); 3279 } 3280 3281 mutex_enter(&uacp->usb_ac_mutex); 3282 ASSERT(MBLKL(data) == 2); 3283 3284 *max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr; 3285 3286 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3287 "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp); 3288 3289 freemsg(data); 3290 3291 return (USB_SUCCESS); 3292 } 3293 3294 3295 /* 3296 * usb_ac_set_volume: 3297 * Send USBA command down to set the gain balance 3298 */ 3299 /* ARGSUSED */ 3300 static int 3301 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir, 3302 int feature_unitID) 3303 { 3304 mblk_t *data = NULL; 3305 usb_cr_t cr; 3306 usb_cb_flags_t cb_flags; 3307 int rval = USB_FAILURE; 3308 3309 3310 mutex_exit(&uacp->usb_ac_mutex); 3311 3312 /* Construct the mblk_t from gain for sending to USBA */ 3313 data = allocb(4, BPRI_HI); 3314 if (!data) { 3315 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3316 "usb_ac_set_volume: allocate data failed"); 3317 mutex_enter(&uacp->usb_ac_mutex); 3318 3319 return (USB_FAILURE); 3320 } 3321 3322 3323 3324 *(data->b_wptr++) = (char)gain; 3325 *(data->b_wptr++) = (char)(gain >> 8); 3326 3327 if ((rval = usb_pipe_sync_ctrl_xfer( 3328 uacp->usb_ac_dip, 3329 uacp->usb_ac_default_ph, 3330 USB_DEV_REQ_HOST_TO_DEV | 3331 USB_DEV_REQ_TYPE_CLASS | 3332 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 3333 USB_AUDIO_SET_CUR, /* bRequest */ 3334 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 3335 /* feature unit and id */ 3336 (feature_unitID << 8) | uacp->usb_ac_ifno, /* wIndex */ 3337 2, /* wLength */ 3338 &data, 0, 3339 &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 3340 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3341 "usb_ac_set_volume: failed, cr=%d cb=0x%x", 3342 cr, cb_flags); 3343 } 3344 3345 freemsg(data); 3346 mutex_enter(&uacp->usb_ac_mutex); 3347 3348 return (rval); 3349 } 3350 3351 3352 /* 3353 * usb_ac_set_mute is called for each unit that supports the 3354 * requested control from usb_ac_traverse_connections 3355 */ 3356 int 3357 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir, 3358 uint_t channel, uint_t control, uint_t muteval, uint_t *depth) 3359 { 3360 mblk_t *data; 3361 usb_cr_t cr; 3362 usb_cb_flags_t cb_flags; 3363 int rval = USB_FAILURE; 3364 3365 3366 if (usb_ac_feature_unit_check(uacp, featureID, 3367 dir, channel, control, 0, depth) != USB_SUCCESS) { 3368 3369 return (USB_FAILURE); 3370 } 3371 mutex_exit(&uacp->usb_ac_mutex); 3372 3373 /* Construct the mblk_t for sending to USBA */ 3374 data = allocb(1, BPRI_HI); 3375 3376 if (!data) { 3377 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3378 "usb_ac_set_mute: allocate data failed"); 3379 mutex_enter(&uacp->usb_ac_mutex); 3380 3381 return (USB_FAILURE); 3382 } 3383 3384 3385 *(data->b_wptr++) = (char)muteval; 3386 3387 if ((rval = usb_pipe_sync_ctrl_xfer( 3388 uacp->usb_ac_dip, 3389 uacp->usb_ac_default_ph, 3390 USB_DEV_REQ_HOST_TO_DEV | 3391 USB_DEV_REQ_TYPE_CLASS | 3392 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 3393 USB_AUDIO_SET_CUR, /* bRequest */ 3394 (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */ 3395 /* feature unit and id */ 3396 (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */ 3397 1, /* wLength */ 3398 &data, 3399 0, /* attributes */ 3400 &cr, &cb_flags, 0)) != USB_SUCCESS) { 3401 3402 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3403 "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags); 3404 } 3405 freemsg(data); 3406 3407 mutex_enter(&uacp->usb_ac_mutex); 3408 3409 return (rval); 3410 } 3411 3412 3413 /* 3414 * usb_ac_send_as_cmd: 3415 * Allocate message blk, send a command down to usb_as, 3416 * wait for the reply and free the message 3417 * 3418 * although not really needed to raise power if sending to as 3419 * it seems better to ensure that both interfaces are at full power 3420 */ 3421 static int 3422 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine, 3423 int cmd, void *arg) 3424 { 3425 usb_ac_streams_info_t *streams_infop; 3426 usb_ac_plumbed_t *plumb_infop; 3427 int rv; 3428 int rval; 3429 ldi_handle_t lh; 3430 3431 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3432 streams_infop = engine->streams; 3433 plumb_infop = streams_infop->acs_plumbed; 3434 3435 3436 lh = plumb_infop->acp_lh; 3437 3438 rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval); 3439 if (rv != 0) { 3440 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3441 "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv); 3442 3443 return (USB_FAILURE); 3444 } 3445 3446 return (USB_SUCCESS); 3447 } 3448 3449 3450 /* 3451 * usb_ac_serialize/release_access: 3452 */ 3453 static void 3454 usb_ac_serialize_access(usb_ac_state_t *uacp) 3455 { 3456 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0); 3457 } 3458 3459 static void 3460 usb_ac_release_access(usb_ac_state_t *uacp) 3461 { 3462 usb_release_access(uacp->usb_ac_ser_acc); 3463 } 3464 3465 3466 static void 3467 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep) 3468 { 3469 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 3470 3471 if (usb_ac_statep->usb_ac_pm != NULL) { 3472 mutex_enter(&usb_ac_statep->usb_ac_mutex); 3473 usb_ac_statep->usb_ac_pm->acpm_pm_busy++; 3474 3475 USB_DPRINTF_L4(PRINT_MASK_PM, 3476 usb_ac_statep->usb_ac_log_handle, 3477 "usb_ac_pm_busy_component: %d", 3478 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 3479 3480 mutex_exit(&usb_ac_statep->usb_ac_mutex); 3481 3482 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) != 3483 DDI_SUCCESS) { 3484 mutex_enter(&usb_ac_statep->usb_ac_mutex); 3485 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 3486 3487 USB_DPRINTF_L2(PRINT_MASK_PM, 3488 usb_ac_statep->usb_ac_log_handle, 3489 "usb_ac_pm_busy_component failed: %d", 3490 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 3491 3492 mutex_exit(&usb_ac_statep->usb_ac_mutex); 3493 } 3494 } 3495 } 3496 3497 3498 static void 3499 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep) 3500 { 3501 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 3502 3503 if (usb_ac_statep->usb_ac_pm != NULL) { 3504 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) == 3505 DDI_SUCCESS) { 3506 mutex_enter(&usb_ac_statep->usb_ac_mutex); 3507 ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0); 3508 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 3509 3510 USB_DPRINTF_L4(PRINT_MASK_PM, 3511 usb_ac_statep->usb_ac_log_handle, 3512 "usb_ac_pm_idle_component: %d", 3513 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 3514 3515 mutex_exit(&usb_ac_statep->usb_ac_mutex); 3516 } 3517 } 3518 } 3519 3520 3521 /* 3522 * handle read from plumbed drivers 3523 */ 3524 static void 3525 usb_ac_reader(void *argp) 3526 { 3527 usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp; 3528 usb_ac_state_t *uacp = acp->acp_uacp; 3529 ldi_handle_t lh; 3530 mblk_t *mp; 3531 int rv; 3532 timestruc_t tv = {0}; 3533 3534 mutex_enter(&uacp->usb_ac_mutex); 3535 lh = acp->acp_lh; 3536 tv.tv_sec = usb_ac_wait_hid; 3537 3538 while (acp->acp_flags & ACP_ENABLED) { 3539 mp = NULL; 3540 3541 mutex_exit(&uacp->usb_ac_mutex); 3542 3543 rv = ldi_getmsg(lh, &mp, &tv); 3544 3545 mutex_enter(&uacp->usb_ac_mutex); 3546 3547 if (rv == ENODEV) { 3548 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3549 "Device is not availabe"); 3550 break; 3551 } 3552 3553 3554 if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0) 3555 rv = usb_ac_read_msg(acp, mp); 3556 3557 } 3558 mutex_exit(&uacp->usb_ac_mutex); 3559 } 3560 3561 3562 /* 3563 * setup threads to read from the other usb modules that may send unsolicited 3564 * or asynchronous messages, which is only hid currently 3565 */ 3566 static int 3567 usb_ac_plumb(usb_ac_plumbed_t *acp) 3568 { 3569 usb_ac_state_t *uacp = acp->acp_uacp; 3570 dev_info_t *dip; 3571 dev_info_t *acp_dip; 3572 int acp_inst; 3573 char *acp_name; 3574 char tq_nm[128]; 3575 int rv = USB_FAILURE; 3576 3577 mutex_enter(&uacp->usb_ac_mutex); 3578 3579 dip = uacp->usb_ac_dip; 3580 3581 acp_dip = acp->acp_dip; 3582 acp_inst = ddi_get_instance(acp_dip); 3583 acp_name = (char *)ddi_driver_name(acp_dip); 3584 3585 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3586 "usb_ac_plumb:begin"); 3587 3588 if (strcmp(acp_name, "hid") != 0) { 3589 rv = USB_SUCCESS; 3590 goto OUT; 3591 } 3592 3593 (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq", 3594 ddi_driver_name(acp_dip), acp_inst); 3595 3596 acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0); 3597 if (acp->acp_tqp == NULL) 3598 goto OUT; 3599 3600 if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp, 3601 DDI_SLEEP) != DDI_SUCCESS) 3602 goto OUT; 3603 3604 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3605 "usb_ac_plumb: dispatched reader"); 3606 3607 rv = USB_SUCCESS; 3608 3609 OUT: 3610 mutex_exit(&uacp->usb_ac_mutex); 3611 3612 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3613 "usb_ac_plumb: done, rv=%d", rv); 3614 3615 return (rv); 3616 } 3617 3618 3619 static void 3620 usb_ac_mux_plumbing_tq(void *arg) 3621 { 3622 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 3623 3624 if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS) 3625 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3626 "usb_ac_mux_plumbing_tq:failed"); 3627 } 3628 3629 3630 static int 3631 usb_ac_do_plumbing(usb_ac_state_t *uacp) 3632 { 3633 dev_info_t *dip = uacp->usb_ac_dip; 3634 int inst = ddi_get_instance(dip); 3635 char tq_nm[128]; 3636 int rv = USB_FAILURE; 3637 3638 (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq", 3639 ddi_driver_name(dip), inst); 3640 3641 uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0); 3642 if (uacp->tqp == NULL) { 3643 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3644 "usb_ac_do_plumbing: ddi_taskq_create failed"); 3645 goto OUT; 3646 } 3647 3648 if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp, 3649 DDI_SLEEP) != DDI_SUCCESS) { 3650 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3651 "usb_ac_do_plumbing: ddi_taskq_dispatch failed"); 3652 goto OUT; 3653 } 3654 3655 rv = USB_SUCCESS; 3656 3657 OUT: 3658 return (rv); 3659 } 3660 3661 3662 3663 static void 3664 usb_ac_mux_unplumbing_tq(void *arg) 3665 { 3666 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 3667 3668 if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS) 3669 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3670 "usb_ac_mux_unplumbing:failed"); 3671 } 3672 3673 3674 static int 3675 usb_ac_do_unplumbing(usb_ac_state_t *uacp) 3676 { 3677 int rv = USB_FAILURE; 3678 3679 if (uacp->tqp == NULL) 3680 return (USB_SUCCESS); 3681 3682 if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq, 3683 (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) { 3684 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3685 "usb_ac_do_unplumbing: ddi_taskq_dispatch failed"); 3686 goto OUT; 3687 } 3688 3689 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3690 "usb_ac_do_unplumbing: waiting for unplumb thread"); 3691 3692 ddi_taskq_wait(uacp->tqp); 3693 rv = USB_SUCCESS; 3694 3695 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3696 "usb_ac_do_unplumbing: unplumb thread done"); 3697 3698 OUT: 3699 if (uacp->tqp != NULL) { 3700 ddi_taskq_destroy(uacp->tqp); 3701 uacp->tqp = NULL; 3702 } 3703 return (rv); 3704 } 3705 3706 3707 /* 3708 * teardown threads to the other usb modules 3709 * and clear structures as part of unplumbing 3710 */ 3711 static void 3712 usb_ac_unplumb(usb_ac_plumbed_t *acp) 3713 { 3714 usb_ac_streams_info_t *streams_infop; 3715 usb_ac_state_t *uacp = acp->acp_uacp; 3716 3717 3718 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3719 "usb_ac_unplumb: begin"); 3720 3721 if (acp->acp_tqp != NULL) { 3722 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3723 "usb_ac_unplumb: destroying taskq"); 3724 3725 ddi_taskq_destroy(acp->acp_tqp); 3726 } 3727 3728 mutex_enter(&uacp->usb_ac_mutex); 3729 3730 if (acp->acp_driver == USB_AS_PLUMBED) { 3731 /* 3732 * we bzero the streams info and plumbed structure 3733 * since there is no guarantee that the next plumbing 3734 * will be identical 3735 */ 3736 streams_infop = (usb_ac_streams_info_t *)acp->acp_data; 3737 3738 /* bzero the relevant plumbing structure */ 3739 bzero(streams_infop, sizeof (usb_ac_streams_info_t)); 3740 } 3741 bzero(acp, sizeof (usb_ac_plumbed_t)); 3742 3743 mutex_exit(&uacp->usb_ac_mutex); 3744 3745 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3746 "usb_ac_unplumb: done"); 3747 } 3748 3749 3750 /*ARGSUSED*/ 3751 static int 3752 usb_ac_mux_plumbing(usb_ac_state_t *uacp) 3753 { 3754 dev_info_t *dip; 3755 3756 /* get the usb_ac dip */ 3757 dip = uacp->usb_ac_dip; 3758 3759 /* Access to the global variables is synchronized */ 3760 mutex_enter(&uacp->usb_ac_mutex); 3761 3762 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3763 "usb_ac_mux_plumbing:state = %d", 3764 uacp->usb_ac_plumbing_state); 3765 3766 if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) { 3767 mutex_exit(&uacp->usb_ac_mutex); 3768 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3769 "usb_ac_mux_plumbing: audio streams driver" 3770 " already plumbed"); 3771 3772 return (USB_SUCCESS); 3773 } 3774 3775 /* usb_as and hid should be attached but double check */ 3776 if (usb_ac_online_siblings(uacp) != USB_SUCCESS) { 3777 mutex_exit(&uacp->usb_ac_mutex); 3778 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3779 "usb_ac_mux_plumbing:no audio streams driver plumbed"); 3780 3781 return (USB_FAILURE); 3782 } 3783 3784 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3785 "usb_ac_mux_plumbing: raising power"); 3786 mutex_exit(&uacp->usb_ac_mutex); 3787 3788 /* bring the device to full power */ 3789 usb_ac_pm_busy_component(uacp); 3790 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 3791 3792 /* avoid dips disappearing while we are plumbing */ 3793 usb_ac_hold_siblings(uacp); 3794 3795 mutex_enter(&uacp->usb_ac_mutex); 3796 3797 /* 3798 * walk all siblings and create the usb_ac<->usb_as and 3799 * usb_ac<->hid streams. return of 0 indicates no or 3800 * partial/failed plumbing 3801 */ 3802 if (usb_ac_mux_walk_siblings(uacp) == 0) { 3803 /* pretend that we are plumbed so we can unplumb */ 3804 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 3805 3806 mutex_exit(&uacp->usb_ac_mutex); 3807 3808 (void) usb_ac_mux_unplumbing(uacp); 3809 3810 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3811 "usb_ac_mux_plumbing: no audio streams driver plumbed"); 3812 3813 usb_ac_rele_siblings(uacp); 3814 3815 usb_ac_pm_idle_component(uacp); 3816 3817 return (USB_FAILURE); 3818 } 3819 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 3820 3821 /* restore state if we have already registered with the mixer */ 3822 if (uacp->usb_ac_registered_with_mixer) { 3823 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3824 "usb_ac_mux_plumbing:already registered with mixer," 3825 "restoring state"); 3826 3827 (void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP); 3828 3829 } else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) { 3830 mutex_exit(&uacp->usb_ac_mutex); 3831 3832 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3833 "usb_ac_mux_plumbing: mixer registration failed"); 3834 3835 (void) usb_ac_mux_unplumbing(uacp); 3836 3837 usb_ac_rele_siblings(uacp); 3838 3839 usb_ac_pm_idle_component(uacp); 3840 3841 return (USB_FAILURE); 3842 } 3843 3844 mutex_exit(&uacp->usb_ac_mutex); 3845 usb_ac_rele_siblings(uacp); 3846 3847 usb_ac_pm_idle_component(uacp); 3848 3849 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3850 "usb_ac_mux_plumbing:done"); 3851 3852 return (USB_SUCCESS); 3853 } 3854 3855 3856 static int 3857 usb_ac_mux_unplumbing(usb_ac_state_t *uacp) 3858 { 3859 usb_ac_plumbed_t *acp; 3860 ldi_handle_t lh; 3861 dev_info_t *acp_dip; 3862 int inst; 3863 int i; 3864 dev_t devt; 3865 minor_t minor; 3866 int maxlinked = 0; 3867 3868 mutex_enter(&uacp->usb_ac_mutex); 3869 3870 3871 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) { 3872 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3873 "usb_ac_mux_unplumbing: already unplumbed!"); 3874 mutex_exit(&uacp->usb_ac_mutex); 3875 3876 return (USB_SUCCESS); 3877 } 3878 3879 /* usb_ac might not have anything plumbed yet */ 3880 if (uacp->usb_ac_current_plumbed_index == -1) { 3881 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3882 "usb_ac_mux_unplumbing: nothing plumbed"); 3883 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED; 3884 mutex_exit(&uacp->usb_ac_mutex); 3885 3886 return (USB_SUCCESS); 3887 } 3888 3889 /* do not allow detach if still busy */ 3890 if (uacp->usb_ac_busy_count) { 3891 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3892 "usb_ac_mux_unplumbing: mux still busy (%d)", 3893 uacp->usb_ac_busy_count); 3894 mutex_exit(&uacp->usb_ac_mutex); 3895 3896 return (USB_FAILURE); 3897 } 3898 3899 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED; 3900 3901 /* close ac-as and ac-hid streams */ 3902 maxlinked = uacp->usb_ac_current_plumbed_index + 1; 3903 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3904 "usb_ac_mux_unplumbing: maxlinked = %d", maxlinked); 3905 3906 for (i = 0; i < maxlinked; i++) { 3907 /* 3908 * we must save members of usb_ac_plumbed[] before calling 3909 * usb_ac_unplumb() because it clears the structure 3910 */ 3911 acp = &uacp->usb_ac_plumbed[i]; 3912 lh = acp->acp_lh; 3913 acp_dip = acp->acp_dip; 3914 devt = acp->acp_devt; 3915 3916 if (acp_dip == NULL) { 3917 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3918 "usb_ac_mux_unplumbing: [%d] - skipping", i); 3919 continue; 3920 } 3921 3922 minor = getminor(devt); 3923 inst = ddi_get_instance(acp_dip); 3924 3925 uacp->usb_ac_current_plumbed_index = i; 3926 3927 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3928 "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x", i, 3929 ddi_driver_name(acp_dip), inst, minor); 3930 3931 if (lh != NULL) { 3932 3933 acp->acp_flags &= ~ACP_ENABLED; 3934 3935 mutex_exit(&uacp->usb_ac_mutex); 3936 3937 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3938 "usb_ac_mux_unplumbing:[%d] - closing", i); 3939 3940 /* 3941 * ldi_close will cause panic if ldi_getmsg 3942 * is not finished. ddi_taskq_destroy will wait 3943 * for the thread to complete. 3944 */ 3945 usb_ac_unplumb(acp); 3946 (void) ldi_close(lh, FREAD|FWRITE, kcred); 3947 3948 3949 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3950 "usb_ac_mux_unplumbing: [%d] - unplumbed", i); 3951 3952 mutex_enter(&uacp->usb_ac_mutex); 3953 } 3954 } 3955 3956 mutex_exit(&uacp->usb_ac_mutex); 3957 3958 /* Wait till all activity in the default pipe has drained */ 3959 usb_ac_serialize_access(uacp); 3960 usb_ac_release_access(uacp); 3961 3962 mutex_enter(&uacp->usb_ac_mutex); 3963 uacp->usb_ac_current_plumbed_index = -1; 3964 mutex_exit(&uacp->usb_ac_mutex); 3965 3966 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3967 "usb_ac_mux_unplumbing: done"); 3968 3969 return (USB_SUCCESS); 3970 } 3971 3972 3973 /* 3974 * walk all siblings and create the ac<->as and ac<->hid streams 3975 */ 3976 static int 3977 usb_ac_mux_walk_siblings(usb_ac_state_t *uacp) 3978 { 3979 dev_info_t *pdip; 3980 dev_info_t *child_dip; 3981 major_t drv_major; 3982 minor_t drv_minor; 3983 int drv_instance; 3984 char *drv_name; 3985 dev_t drv_devt; 3986 ldi_handle_t drv_lh; 3987 ldi_ident_t li; 3988 int error; 3989 int count = 0; 3990 3991 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3992 3993 pdip = ddi_get_parent(uacp->usb_ac_dip); 3994 child_dip = ddi_get_child(pdip); 3995 3996 while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) { 3997 drv_instance = ddi_get_instance(child_dip); 3998 drv_name = (char *)ddi_driver_name(child_dip); 3999 4000 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4001 "usb_ac_mux_walk_siblings: plumbing %s%d count=%d", 4002 drv_name, drv_instance, count); 4003 4004 /* ignore own dip */ 4005 if (child_dip == uacp->usb_ac_dip) { 4006 child_dip = ddi_get_next_sibling(child_dip); 4007 continue; 4008 } 4009 drv_instance = ddi_get_instance(child_dip); 4010 4011 /* ignore other dip other than usb_as and hid */ 4012 if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) { 4013 uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED; 4014 drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance); 4015 } else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) { 4016 uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED; 4017 drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance); 4018 } else { 4019 drv_minor = drv_instance; 4020 uacp->usb_ac_plumbed[count].acp_driver = 4021 UNKNOWN_PLUMBED; 4022 child_dip = ddi_get_next_sibling(child_dip); 4023 4024 continue; 4025 } 4026 4027 if (!i_ddi_devi_attached(child_dip)) { 4028 child_dip = ddi_get_next_sibling(child_dip); 4029 4030 continue; 4031 } 4032 4033 if (DEVI_IS_DEVICE_REMOVED(child_dip)) { 4034 child_dip = ddi_get_next_sibling(child_dip); 4035 4036 continue; 4037 } 4038 4039 drv_major = ddi_driver_major(child_dip); 4040 4041 uacp->usb_ac_current_plumbed_index = count; 4042 4043 mutex_exit(&uacp->usb_ac_mutex); 4044 4045 drv_devt = makedevice(drv_major, drv_minor); 4046 4047 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4048 "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)", 4049 drv_name, drv_instance, drv_major, drv_minor); 4050 4051 error = ldi_ident_from_dip(uacp->usb_ac_dip, &li); 4052 if (error == 0) { 4053 mutex_enter(&uacp->usb_ac_mutex); 4054 uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED; 4055 mutex_exit(&uacp->usb_ac_mutex); 4056 4057 error = ldi_open_by_dev(&drv_devt, OTYP_CHR, 4058 FREAD|FWRITE, kcred, &drv_lh, li); 4059 ldi_ident_release(li); 4060 } 4061 4062 mutex_enter(&uacp->usb_ac_mutex); 4063 if (error) { 4064 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4065 "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)" 4066 " failed error=%d", drv_major, drv_minor, error); 4067 4068 return (0); 4069 } 4070 4071 uacp->usb_ac_plumbed[count].acp_uacp = uacp; 4072 uacp->usb_ac_plumbed[count].acp_devt = drv_devt; 4073 uacp->usb_ac_plumbed[count].acp_lh = drv_lh; 4074 uacp->usb_ac_plumbed[count].acp_dip = child_dip; 4075 uacp->usb_ac_plumbed[count].acp_ifno = 4076 usb_get_if_number(child_dip); 4077 4078 if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) { 4079 /* get registration data */ 4080 if (usb_ac_get_reg_data(uacp, drv_lh, count) != 4081 USB_SUCCESS) { 4082 4083 USB_DPRINTF_L3(PRINT_MASK_ALL, 4084 uacp->usb_ac_log_handle, 4085 "usb_ac_mux_walk_siblings:" 4086 "usb_ac_get_reg_data failed on %s%d", 4087 drv_name, drv_instance); 4088 4089 uacp->usb_ac_plumbed[count].acp_dip = NULL; 4090 4091 return (0); 4092 } 4093 } else if (uacp->usb_ac_plumbed[count].acp_driver == 4094 USB_AH_PLUMBED) { 4095 int rval; 4096 4097 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4098 "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d", 4099 drv_name, drv_instance); 4100 4101 mutex_exit(&uacp->usb_ac_mutex); 4102 4103 /* push usb_ah module on top of hid */ 4104 error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah", 4105 FKIOCTL, kcred, &rval); 4106 mutex_enter(&uacp->usb_ac_mutex); 4107 4108 if (error) { 4109 USB_DPRINTF_L2(PRINT_MASK_ALL, 4110 uacp->usb_ac_log_handle, 4111 "usb_ac_mux_walk_siblings: ldi_ioctl" 4112 "I_PUSH failed on %s%d, error=%d", 4113 drv_name, drv_instance, error); 4114 4115 uacp->usb_ac_plumbed[count].acp_dip = NULL; 4116 4117 /* skip plumbing the hid driver */ 4118 child_dip = ddi_get_next_sibling(child_dip); 4119 continue; 4120 } 4121 } else { 4122 /* should not be here */ 4123 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4124 "usb_ac_mux_walk_siblings:- unknown module %s%d", 4125 drv_name, drv_instance); 4126 count--; 4127 4128 uacp->usb_ac_plumbed[count].acp_dip = NULL; 4129 4130 /* skip plumbing an unknown module */ 4131 child_dip = ddi_get_next_sibling(child_dip); 4132 continue; 4133 } 4134 4135 mutex_exit(&uacp->usb_ac_mutex); 4136 error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]); 4137 mutex_enter(&uacp->usb_ac_mutex); 4138 4139 if (error != USB_SUCCESS) { 4140 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4141 "usb_ac_mux_walk_siblings: usb_ac_plumb " 4142 "failed for %s%d", drv_name, drv_instance); 4143 4144 return (0); 4145 } 4146 4147 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4148 "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x", 4149 drv_instance, drv_minor); 4150 4151 child_dip = ddi_get_next_sibling(child_dip); 4152 count++; 4153 } 4154 4155 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4156 "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux", 4157 count); 4158 4159 return (count); 4160 } 4161 4162 4163 /* 4164 * Register with mixer only after first plumbing. 4165 * Also do not register if earlier reg data 4166 * couldn't be received from at least one 4167 * streaming interface 4168 */ 4169 4170 static int 4171 usb_ac_mixer_registration(usb_ac_state_t *uacp) 4172 { 4173 usb_as_registration_t *asreg; 4174 int n; 4175 4176 if (uacp->usb_ac_registered_with_mixer) { 4177 return (USB_SUCCESS); 4178 } 4179 4180 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 4181 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) { 4182 break; 4183 } 4184 } 4185 4186 /* Haven't found a streaming interface; fail mixer registration */ 4187 if (n > USB_AC_MAX_AS_PLUMBED) { 4188 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4189 "usb_ac_mixer_registration:- no streaming interface found"); 4190 4191 return (USB_FAILURE); 4192 } 4193 4194 /* 4195 * Fill out streaming interface specific stuff 4196 * Note that we handle only one playing and one recording 4197 * streaming interface at the most 4198 */ 4199 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 4200 int ch, chs, id; 4201 4202 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) { 4203 continue; 4204 } 4205 4206 asreg = &(uacp->usb_ac_streams[n].acs_streams_reg); 4207 if (asreg->reg_valid == 0) { 4208 continue; 4209 } 4210 4211 4212 chs = asreg->reg_formats[0].fmt_chns; 4213 4214 /* check if any channel supports vol. control for this fmt */ 4215 for (ch = 0; ch <= chs; ch++) { 4216 if ((id = usb_ac_get_featureID(uacp, 4217 asreg->reg_mode, ch, 4218 USB_AUDIO_VOLUME_CONTROL)) != -1) { 4219 USB_DPRINTF_L3(PRINT_MASK_ALL, 4220 uacp->usb_ac_log_handle, 4221 "usb_ac_mixer_registration:n= [%d]" 4222 "- dir=%d featureID=%d", 4223 n, asreg->reg_mode, id); 4224 4225 break; 4226 } 4227 } 4228 4229 uacp->usb_ac_streams[n].acs_default_gain = 4230 (id == USB_AC_ID_NONE) ? (AF_MAX_GAIN): (AF_MAX_GAIN*3/4); 4231 4232 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4233 "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d" 4234 "default_gain=%d id=%d", 4235 n, asreg->reg_mode, chs, 4236 uacp->usb_ac_streams[n].acs_default_gain, id); 4237 4238 } 4239 4240 /* the rest */ 4241 4242 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4243 "usb_ac_mixer_registration: calling usb_audio_register"); 4244 4245 mutex_exit(&uacp->usb_ac_mutex); 4246 4247 if (usb_audio_register(uacp) != USB_SUCCESS) { 4248 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4249 "usb_ac_mixer_registration: usb_audio_register failed"); 4250 4251 mutex_enter(&uacp->usb_ac_mutex); 4252 4253 return (USB_FAILURE); 4254 } 4255 4256 mutex_enter(&uacp->usb_ac_mutex); 4257 4258 uacp->usb_ac_registered_with_mixer = 1; 4259 4260 return (USB_SUCCESS); 4261 } 4262 4263 4264 /* 4265 * Get registriations data when driver attach 4266 */ 4267 static int 4268 usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index) 4269 { 4270 int n, error, rval; 4271 usb_as_registration_t *streams_reg; 4272 4273 4274 ASSERT(uacp->usb_ac_registered_with_mixer == 0); 4275 4276 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 4277 /* 4278 * We haven't received registration data 4279 * from n-th streaming interface in the array 4280 */ 4281 if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) { 4282 break; 4283 } 4284 } 4285 4286 if (n >= USB_AC_MAX_AS_PLUMBED) { 4287 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4288 "More than 2 streaming interfaces (play " 4289 "and/or record) currently not supported"); 4290 4291 return (USB_FAILURE); 4292 } 4293 4294 /* take the stream reg struct with the same index */ 4295 streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg; 4296 4297 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4298 "usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d", 4299 (void *)streams_reg, n); 4300 4301 mutex_exit(&uacp->usb_ac_mutex); 4302 4303 if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION, 4304 (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) { 4305 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4306 "usb_ac_get_reg_data: ldi_ioctl failed for" 4307 "mixer registration error=%d", error); 4308 4309 mutex_enter(&uacp->usb_ac_mutex); 4310 4311 return (USB_FAILURE); 4312 } else { 4313 mutex_enter(&uacp->usb_ac_mutex); 4314 4315 rval = usb_ac_setup_plumbed(uacp, index, n); 4316 4317 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4318 "usb_ac_get_reg_data:usb_ac_streams[%d]: " 4319 "received_reg_data=%d type=%s", index, 4320 uacp->usb_ac_streams[n].acs_rcvd_reg_data, 4321 ((streams_reg->reg_mode == USB_AUDIO_PLAY) ? 4322 "play" : "record")); 4323 4324 usb_ac_print_reg_data(uacp, streams_reg); 4325 4326 return (rval); 4327 } 4328 } 4329 4330 4331 /* 4332 * setup plumbed and stream info structure 4333 */ 4334 static int 4335 usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx) 4336 { 4337 uacp->usb_ac_plumbed[plb_idx].acp_data = 4338 &uacp->usb_ac_streams[str_idx]; 4339 uacp->usb_ac_streams[str_idx].acs_plumbed = 4340 &uacp->usb_ac_plumbed[plb_idx]; 4341 uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1; 4342 4343 4344 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4345 "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ", 4346 plb_idx, str_idx); 4347 4348 return (USB_SUCCESS); 4349 } 4350 4351 4352 /* 4353 * function to dump registration data 4354 */ 4355 static void 4356 usb_ac_print_reg_data(usb_ac_state_t *uacp, 4357 usb_as_registration_t *reg) 4358 { 4359 int n; 4360 4361 for (n = 0; n < reg->reg_n_formats; n++) { 4362 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4363 "format%d: alt=%d chns=%d prec=%d enc=%d", n, 4364 reg->reg_formats[n].fmt_alt, 4365 reg->reg_formats[n].fmt_chns, 4366 reg->reg_formats[n].fmt_precision, 4367 reg->reg_formats[n].fmt_encoding); 4368 } 4369 4370 for (n = 0; n < USB_AS_N_FORMATS; n++) { 4371 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4372 "reg_formats[%d] ptr=0x%p", n, 4373 (void *)®->reg_formats[n]); 4374 } 4375 4376 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4377 "usb_ac_print_reg_data: End"); 4378 } 4379 4380 4381 static int 4382 usb_ac_online_siblings(usb_ac_state_t *uacp) 4383 { 4384 dev_info_t *pdip, *child_dip; 4385 int rval = USB_SUCCESS; 4386 4387 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 4388 4389 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4390 "usb_ac_online_siblings:start"); 4391 4392 pdip = ddi_get_parent(uacp->usb_ac_dip); 4393 4394 child_dip = ddi_get_child(pdip); 4395 while (child_dip != NULL) { 4396 4397 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4398 "usb_ac_online_siblings: onlining %s%d ref=%d", 4399 ddi_driver_name(child_dip), 4400 ddi_get_instance(child_dip), 4401 DEVI(child_dip)->devi_ref); 4402 4403 /* Online the child_dip of usb_as and hid, if not already */ 4404 if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) || 4405 (strcmp(ddi_driver_name(child_dip), "hid") == 0)) { 4406 4407 mutex_exit(&uacp->usb_ac_mutex); 4408 if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) != 4409 NDI_SUCCESS) { 4410 USB_DPRINTF_L3(PRINT_MASK_ALL, 4411 uacp->usb_ac_log_handle, 4412 "usb_ac_online_siblings:failed to online" 4413 "device %s%d", ddi_driver_name(child_dip), 4414 ddi_get_instance(child_dip)); 4415 4416 /* only onlining usb_as is fatal */ 4417 if (strcmp(ddi_driver_name(child_dip), 4418 "usb_as") == 0) { 4419 mutex_enter(&uacp->usb_ac_mutex); 4420 rval = USB_FAILURE; 4421 break; 4422 } 4423 } 4424 mutex_enter(&uacp->usb_ac_mutex); 4425 } 4426 child_dip = ddi_get_next_sibling(child_dip); 4427 } 4428 4429 return (rval); 4430 } 4431 4432 4433 /* 4434 * hold all audio children before or after plumbing 4435 * online usb_as and hid, if not already 4436 */ 4437 static void 4438 usb_ac_hold_siblings(usb_ac_state_t *uacp) 4439 { 4440 int circ; 4441 dev_info_t *pdip, *child_dip; 4442 4443 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4444 "usb_ac_hold_siblings:start"); 4445 4446 /* hold all siblings and ourselves */ 4447 pdip = ddi_get_parent(uacp->usb_ac_dip); 4448 4449 /* hold the children */ 4450 ndi_devi_enter(pdip, &circ); 4451 child_dip = ddi_get_child(pdip); 4452 while (child_dip != NULL) { 4453 ndi_hold_devi(child_dip); 4454 4455 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4456 "usb_ac_hold_siblings: held %s%d ref=%d", 4457 ddi_driver_name(child_dip), ddi_get_instance(child_dip), 4458 DEVI(child_dip)->devi_ref); 4459 4460 child_dip = ddi_get_next_sibling(child_dip); 4461 } 4462 ndi_devi_exit(pdip, circ); 4463 } 4464 4465 4466 /* 4467 * release all audio children before or after plumbing 4468 */ 4469 static void 4470 usb_ac_rele_siblings(usb_ac_state_t *uacp) 4471 { 4472 int circ; 4473 dev_info_t *pdip, *child_dip; 4474 4475 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4476 "usb_ac_rele_siblings: start"); 4477 4478 /* release all siblings and ourselves */ 4479 pdip = ddi_get_parent(uacp->usb_ac_dip); 4480 ndi_devi_enter(pdip, &circ); 4481 child_dip = ddi_get_child(pdip); 4482 while (child_dip != NULL) { 4483 ndi_rele_devi(child_dip); 4484 4485 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4486 "usb_ac_rele_siblings: released %s%d ref=%d", 4487 ddi_driver_name(child_dip), ddi_get_instance(child_dip), 4488 DEVI(child_dip)->devi_ref); 4489 4490 child_dip = ddi_get_next_sibling(child_dip); 4491 } 4492 ndi_devi_exit(pdip, circ); 4493 } 4494 static void 4495 usb_restore_engine(usb_ac_state_t *statep) 4496 { 4497 usb_audio_eng_t *engp; 4498 int i; 4499 4500 for (i = 0; i < USB_AC_ENG_MAX; i++) { 4501 4502 mutex_enter(&statep->usb_ac_mutex); 4503 engp = &statep->engines[i]; 4504 mutex_exit(&statep->usb_ac_mutex); 4505 4506 if (engp->af_engp == NULL) 4507 continue; 4508 if (usb_ac_set_format(statep, engp) != USB_SUCCESS) { 4509 USB_DPRINTF_L2(PRINT_MASK_ATTA, 4510 statep->usb_ac_log_handle, 4511 "usb_restore_engine:set format fail, i=%d", i); 4512 return; 4513 } 4514 if (engp->started) { 4515 (void) usb_engine_start(engp); 4516 } 4517 4518 } 4519 4520 (void) usb_ac_ctrl_restore(statep); 4521 } 4522 4523 4524 /* 4525 * get the maximum format specification the device supports 4526 */ 4527 static void 4528 usb_ac_max_fmt(usb_as_registration_t *reg_data, 4529 usb_audio_format_t *fmtp) 4530 { 4531 4532 uint_t ch = 0, sr = 0, prec = 0, enc = 0; 4533 int i; 4534 4535 usb_audio_formats_t *reg_formats = reg_data->reg_formats; 4536 4537 /* format priority: channels, sample rate, precision, encoding */ 4538 for (i = 0; i < reg_data->reg_n_formats; i++) { 4539 uint_t val, fmt_sr; 4540 int n, keep; 4541 4542 val = reg_formats[i].fmt_chns; 4543 if (val < ch) 4544 continue; 4545 if (val > ch) 4546 keep = 1; 4547 4548 for (n = 0, fmt_sr = 0; n < reg_formats[i].fmt_n_srs; n++) { 4549 if (fmt_sr < reg_formats[i].fmt_srs[n]) { 4550 fmt_sr = reg_formats[i].fmt_srs[n]; 4551 } 4552 } 4553 if (!keep && fmt_sr < sr) 4554 continue; 4555 if (fmt_sr > sr) 4556 keep = 1; 4557 4558 val = reg_formats[i].fmt_precision; 4559 if (!keep && (val < prec)) 4560 continue; 4561 if (val > prec) 4562 keep = 1; 4563 4564 val = reg_formats[i].fmt_encoding; 4565 if (!keep && (val < enc)) 4566 continue; 4567 4568 ch = reg_formats[i].fmt_chns; 4569 sr = fmt_sr; 4570 prec = reg_formats[i].fmt_precision; 4571 enc = reg_formats[i].fmt_encoding; 4572 } 4573 4574 fmtp->ch = ch; 4575 fmtp->sr = sr; 4576 fmtp->prec = prec; 4577 fmtp->enc = enc; 4578 } 4579 4580 4581 static void 4582 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp) 4583 { 4584 if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL) 4585 return; 4586 4587 audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp); 4588 audio_engine_free(engp->af_engp); 4589 4590 mutex_enter(&engp->lock); 4591 engp->af_engp = NULL; 4592 engp->streams = NULL; 4593 mutex_exit(&engp->lock); 4594 4595 mutex_destroy(&engp->lock); 4596 cv_destroy(&engp->usb_audio_cv); 4597 } 4598 4599 4600 static int 4601 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t *asinfo) 4602 { 4603 audio_dev_t *af_devp = uacp->usb_ac_audio_dev; 4604 usb_audio_eng_t *engp; 4605 audio_engine_t *af_engp; 4606 int rv = USB_FAILURE; 4607 int dir = asinfo->acs_streams_reg.reg_mode; 4608 uint_t defgain; 4609 4610 if (asinfo->acs_rcvd_reg_data == 0) { 4611 4612 return (USB_SUCCESS); 4613 } 4614 if (dir == USB_AUDIO_PLAY) { 4615 engp = &(uacp->engines[0]); 4616 } else { 4617 engp = &(uacp->engines[1]); 4618 } 4619 4620 cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL); 4621 4622 mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL); 4623 4624 mutex_enter(&engp->lock); 4625 4626 engp->af_eflags = 4627 (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP; 4628 engp->statep = uacp; 4629 4630 /* Set the format for the engine */ 4631 usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt); 4632 4633 /* init the default gain */ 4634 defgain = asinfo->acs_default_gain; 4635 if (engp->fmt.ch == 2) { 4636 engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain); 4637 } else { 4638 engp->af_defgain = defgain; 4639 } 4640 engp->streams = asinfo; 4641 4642 mutex_exit(&engp->lock); 4643 4644 af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags); 4645 if (af_engp == NULL) { 4646 4647 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 4648 "audio_engine_alloc failed"); 4649 goto OUT; 4650 } 4651 ASSERT(engp->af_engp == 0); 4652 4653 mutex_enter(&engp->lock); 4654 engp->af_engp = af_engp; 4655 mutex_exit(&engp->lock); 4656 4657 audio_engine_set_private(af_engp, engp); 4658 audio_dev_add_engine(af_devp, af_engp); 4659 4660 /* 4661 * Set the format for this engine 4662 */ 4663 if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) { 4664 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 4665 "set format failed, dir = %d", dir); 4666 goto OUT; 4667 } 4668 rv = USB_SUCCESS; 4669 4670 OUT: 4671 if (rv != USB_SUCCESS) 4672 usb_ac_rem_eng(uacp, engp); 4673 4674 return (rv); 4675 } 4676 4677 4678 static int 4679 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep) 4680 { 4681 usb_audio_ctrl_t *ctrlp; 4682 int rv = USB_SUCCESS; 4683 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 4684 "usb_ac_ctrl_set_defaults:begin"); 4685 4686 for (int i = 0; i < CTL_NUM; i++) { 4687 ctrlp = statep->controls[i]; 4688 if (!ctrlp) { 4689 continue; 4690 } 4691 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) { 4692 USB_DPRINTF_L2(PRINT_MASK_ATTA, 4693 statep->usb_ac_log_handle, 4694 "usb_ac_ctrl_set_defaults:control write failed"); 4695 rv = USB_FAILURE; 4696 } 4697 4698 } 4699 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 4700 "usb_ac_ctrl_set_defaults:end"); 4701 return (rv); 4702 } 4703 4704 4705 static int 4706 usb_ac_ctrl_restore(usb_ac_state_t *statep) 4707 { 4708 usb_audio_ctrl_t *ctrlp; 4709 int rv = USB_SUCCESS; 4710 4711 for (int i = 0; i < CTL_NUM; i++) { 4712 ctrlp = statep->controls[i]; 4713 if (ctrlp) { 4714 USB_DPRINTF_L3(PRINT_MASK_ATTA, 4715 statep->usb_ac_log_handle, 4716 "usb_ac_ctrl_restore:i = %d", i); 4717 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) { 4718 rv = USB_FAILURE; 4719 } 4720 } 4721 } 4722 return (rv); 4723 } 4724 4725 4726 4727 4728 /* 4729 * moves data between driver buffer and framework/shim buffer 4730 */ 4731 static void 4732 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz) 4733 { 4734 size_t cpsz = sz; 4735 caddr_t *src, *dst; 4736 4737 if (engp->af_eflags & ENGINE_OUTPUT_CAP) { 4738 src = &engp->bufpos; 4739 dst = (caddr_t *)&buf; 4740 } else { 4741 src = (caddr_t *)&buf; 4742 dst = &engp->bufpos; 4743 } 4744 4745 /* 4746 * Wrap. If sz is exactly the remainder of the buffer 4747 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so 4748 * the second memcpy() should have no effect, with bufpos updated 4749 * to the head of the buffer. 4750 */ 4751 if (engp->bufpos + sz >= engp->bufendp) { 4752 cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos; 4753 (void) memcpy(*dst, *src, cpsz); 4754 4755 4756 buf = (caddr_t)buf + cpsz; 4757 engp->bufpos = engp->bufp; 4758 cpsz = sz - cpsz; 4759 } 4760 4761 if (cpsz) { 4762 (void) memcpy(*dst, *src, cpsz); 4763 4764 4765 engp->bufpos += cpsz; 4766 } 4767 engp->bufio_count++; 4768 } 4769 4770 4771 /* 4772 * control read callback 4773 */ 4774 static int 4775 usb_audio_ctrl_read(void *arg, uint64_t *cvalp) 4776 { 4777 usb_audio_ctrl_t *ctrlp = arg; 4778 4779 mutex_enter(&ctrlp->ctrl_mutex); 4780 *cvalp = ctrlp->cval; 4781 mutex_exit(&ctrlp->ctrl_mutex); 4782 4783 return (0); 4784 } 4785 4786 4787 /* 4788 * stereo level control callback 4789 */ 4790 static int 4791 usb_audio_write_stero_rec(void *arg, uint64_t cval) 4792 { 4793 usb_audio_ctrl_t *ctrlp = arg; 4794 usb_ac_state_t *statep = ctrlp->statep; 4795 int rv = EIO; 4796 int left, right; 4797 uint_t count = 0; 4798 4799 4800 left = AUDIO_CTRL_STEREO_LEFT(cval); 4801 right = AUDIO_CTRL_STEREO_RIGHT(cval); 4802 4803 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN || 4804 right < AF_MIN_GAIN || right > AF_MAX_GAIN) { 4805 4806 return (EINVAL); 4807 } 4808 4809 mutex_enter(&ctrlp->ctrl_mutex); 4810 ctrlp->cval = cval; 4811 mutex_exit(&ctrlp->ctrl_mutex); 4812 4813 mutex_enter(&statep->usb_ac_mutex); 4814 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD, 4815 USB_AUDIO_FEATURE_UNIT, 1, 4816 USB_AUDIO_VOLUME_CONTROL, 4817 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain); 4818 4819 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD, 4820 USB_AUDIO_FEATURE_UNIT, 2, 4821 USB_AUDIO_VOLUME_CONTROL, 4822 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain); 4823 rv = 0; 4824 4825 done: 4826 mutex_exit(&statep->usb_ac_mutex); 4827 return (rv); 4828 } 4829 4830 static int 4831 usb_audio_write_ster_vol(void *arg, uint64_t cval) 4832 { 4833 usb_audio_ctrl_t *ctrlp = arg; 4834 usb_ac_state_t *statep = ctrlp->statep; 4835 int rv = EIO; 4836 int left, right; 4837 uint_t count = 0; 4838 4839 left = AUDIO_CTRL_STEREO_LEFT(cval); 4840 right = AUDIO_CTRL_STEREO_RIGHT(cval); 4841 4842 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN || 4843 right < AF_MIN_GAIN || right > AF_MAX_GAIN) { 4844 return (EINVAL); 4845 } 4846 4847 mutex_enter(&ctrlp->ctrl_mutex); 4848 ctrlp->cval = cval; 4849 mutex_exit(&ctrlp->ctrl_mutex); 4850 4851 4852 mutex_enter(&statep->usb_ac_mutex); 4853 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 4854 USB_AUDIO_FEATURE_UNIT, 1, 4855 USB_AUDIO_VOLUME_CONTROL, 4856 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain); 4857 4858 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 4859 USB_AUDIO_FEATURE_UNIT, 2, 4860 USB_AUDIO_VOLUME_CONTROL, 4861 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain); 4862 rv = 0; 4863 4864 OUT: 4865 mutex_exit(&statep->usb_ac_mutex); 4866 return (rv); 4867 } 4868 4869 4870 /* 4871 * mono level control callback 4872 */ 4873 static int 4874 usb_audio_write_mono_vol(void *arg, uint64_t cval) 4875 { 4876 usb_audio_ctrl_t *ctrlp = arg; 4877 usb_ac_state_t *statep = ctrlp->statep; 4878 int rv = EIO; 4879 int gain; 4880 4881 uint_t count = 0; 4882 4883 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) { 4884 return (EINVAL); 4885 } 4886 4887 mutex_enter(&ctrlp->ctrl_mutex); 4888 ctrlp->cval = cval; 4889 mutex_exit(&ctrlp->ctrl_mutex); 4890 4891 gain = (int)(cval); 4892 4893 mutex_enter(&statep->usb_ac_mutex); 4894 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 4895 USB_AUDIO_FEATURE_UNIT, 1, 4896 USB_AUDIO_VOLUME_CONTROL, 4897 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain); 4898 4899 rv = 0; 4900 OUT: 4901 mutex_exit(&statep->usb_ac_mutex); 4902 4903 return (rv); 4904 } 4905 4906 4907 /* 4908 * mono level control callback 4909 */ 4910 static int 4911 usb_audio_write_monitor_gain(void *arg, uint64_t cval) 4912 { 4913 usb_audio_ctrl_t *ctrlp = arg; 4914 usb_ac_state_t *statep = ctrlp->statep; 4915 int rv = EIO; 4916 int gain; 4917 uint_t count = 0; 4918 4919 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) { 4920 4921 return (EINVAL); 4922 } 4923 4924 mutex_enter(&ctrlp->ctrl_mutex); 4925 ctrlp->cval = cval; 4926 mutex_exit(&ctrlp->ctrl_mutex); 4927 4928 gain = (int)(cval); 4929 4930 mutex_enter(&statep->usb_ac_mutex); 4931 (void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD, 4932 USB_AUDIO_INPUT_TERMINAL, 1, 4933 USB_AUDIO_VOLUME_CONTROL, 4934 USB_AC_FIND_ALL, &count, gain, 4935 usb_ac_set_monitor_gain); 4936 4937 rv = 0; 4938 OUT: 4939 mutex_exit(&statep->usb_ac_mutex); 4940 return (rv); 4941 } 4942 4943 static int 4944 usb_audio_write_mono_rec(void *arg, uint64_t cval) 4945 { 4946 usb_audio_ctrl_t *ctrlp = arg; 4947 usb_ac_state_t *statep = ctrlp->statep; 4948 int rv = EIO; 4949 int gain; 4950 4951 uint_t count = 0; 4952 4953 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) { 4954 4955 return (EINVAL); 4956 } 4957 4958 mutex_enter(&ctrlp->ctrl_mutex); 4959 ctrlp->cval = cval; 4960 mutex_exit(&ctrlp->ctrl_mutex); 4961 4962 gain = (int)(cval); 4963 4964 mutex_enter(&statep->usb_ac_mutex); 4965 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD, 4966 USB_AUDIO_FEATURE_UNIT, 1, 4967 USB_AUDIO_VOLUME_CONTROL, 4968 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain); 4969 4970 rv = 0; 4971 4972 mutex_exit(&statep->usb_ac_mutex); 4973 return (rv); 4974 } 4975 4976 static int 4977 usb_audio_write_mic_boost(void *arg, uint64_t cval) 4978 { 4979 usb_audio_ctrl_t *ctrlp = arg; 4980 4981 mutex_enter(&ctrlp->ctrl_mutex); 4982 ctrlp->cval = cval; 4983 mutex_exit(&ctrlp->ctrl_mutex); 4984 /* do nothing here */ 4985 return (0); 4986 } 4987 4988 static int 4989 usb_audio_write_rec_src(void *arg, uint64_t cval) 4990 { 4991 usb_audio_ctrl_t *ctrlp = arg; 4992 usb_ac_state_t *statep = ctrlp->statep; 4993 int rv = 0; 4994 4995 if (cval & ~(statep->usb_ac_input_ports)) 4996 return (EINVAL); 4997 4998 mutex_enter(&ctrlp->ctrl_mutex); 4999 ctrlp->cval = cval; 5000 mutex_exit(&ctrlp->ctrl_mutex); 5001 5002 mutex_enter(&statep->usb_ac_mutex); 5003 if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) { 5004 5005 USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle, 5006 "usb_audio_write_rec_src: failed"); 5007 rv = EINVAL; 5008 } 5009 mutex_exit(&statep->usb_ac_mutex); 5010 rv = 0; 5011 5012 OUT: 5013 return (rv); 5014 5015 } 5016 5017 5018 int 5019 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval) 5020 { 5021 short muteval; 5022 int rval; 5023 5024 uint_t count; 5025 muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF; 5026 count = 0; 5027 /* only support AUDIO_PLAY */ 5028 5029 mutex_enter(&statep->usb_ac_mutex); 5030 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 5031 USB_AUDIO_FEATURE_UNIT, 0, 5032 USB_AUDIO_MUTE_CONTROL, 5033 USB_AC_FIND_ALL, &count, muteval, 5034 usb_ac_set_mute); 5035 mutex_exit(&statep->usb_ac_mutex); 5036 5037 rval = (count == 0) ? USB_SUCCESS : USB_FAILURE; 5038 5039 return (rval); 5040 } 5041 5042 5043 /* 5044 * port selection control callback 5045 */ 5046 /* 5047 * audio control registration related routines 5048 */ 5049 5050 static usb_audio_ctrl_t * 5051 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val) 5052 { 5053 audio_ctrl_desc_t desc; 5054 audio_ctrl_wr_t fn; 5055 usb_audio_ctrl_t *pc; 5056 5057 pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP); 5058 5059 mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL); 5060 5061 bzero(&desc, sizeof (desc)); 5062 5063 switch (num) { 5064 case CTL_VOLUME_MONO: 5065 desc.acd_name = AUDIO_CTRL_ID_VOLUME; 5066 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 5067 desc.acd_minvalue = 0; 5068 desc.acd_maxvalue = AF_MAX_GAIN; 5069 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW 5070 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL; 5071 fn = usb_audio_write_mono_vol; 5072 break; 5073 5074 case CTL_VOLUME_STERO: 5075 desc.acd_name = AUDIO_CTRL_ID_VOLUME; 5076 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 5077 desc.acd_minvalue = 0; 5078 desc.acd_maxvalue = AF_MAX_GAIN; 5079 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW 5080 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL; 5081 fn = usb_audio_write_ster_vol; 5082 5083 break; 5084 5085 case CTL_REC_MONO: 5086 desc.acd_name = AUDIO_CTRL_ID_RECGAIN; 5087 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 5088 desc.acd_minvalue = 0; 5089 desc.acd_maxvalue = AF_MAX_GAIN; 5090 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC 5091 | AUDIO_CTRL_FLAG_RW; 5092 fn = usb_audio_write_mono_rec; 5093 break; 5094 case CTL_REC_STERO: 5095 5096 desc.acd_name = AUDIO_CTRL_ID_RECGAIN; 5097 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 5098 desc.acd_minvalue = 0; 5099 desc.acd_maxvalue = AF_MAX_GAIN; 5100 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC 5101 | AUDIO_CTRL_FLAG_RW; 5102 fn = usb_audio_write_stero_rec; 5103 break; 5104 5105 case CTL_MONITOR_GAIN: 5106 5107 desc.acd_name = AUDIO_CTRL_ID_MONGAIN; 5108 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 5109 desc.acd_minvalue = 0; 5110 desc.acd_maxvalue = AF_MAX_GAIN; 5111 desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR 5112 |AUDIO_CTRL_FLAG_RW; 5113 fn = usb_audio_write_monitor_gain; 5114 break; 5115 5116 case CTL_MIC_BOOST: 5117 5118 desc.acd_name = AUDIO_CTRL_ID_MICBOOST; 5119 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN; 5120 desc.acd_minvalue = 0; 5121 desc.acd_maxvalue = 1; 5122 desc.acd_flags = AUDIO_CTRL_FLAG_RW; 5123 fn = usb_audio_write_mic_boost; 5124 break; 5125 case CTL_REC_SRC: 5126 5127 desc.acd_name = AUDIO_CTRL_ID_RECSRC; 5128 desc.acd_type = AUDIO_CTRL_TYPE_ENUM; 5129 desc.acd_minvalue = statep->usb_ac_input_ports; 5130 desc.acd_maxvalue = statep->usb_ac_input_ports; 5131 desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC; 5132 for (int i = 0; usb_audio_dtypes[i]; i++) { 5133 desc.acd_enum[i] = usb_audio_dtypes[i]; 5134 } 5135 5136 fn = usb_audio_write_rec_src; 5137 break; 5138 5139 5140 5141 default: 5142 5143 break; 5144 } 5145 5146 mutex_enter(&pc->ctrl_mutex); 5147 5148 pc->statep = statep; 5149 pc->cval = val; 5150 pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc, 5151 usb_audio_ctrl_read, fn, pc); 5152 5153 mutex_exit(&pc->ctrl_mutex); 5154 5155 mutex_enter(&statep->usb_ac_mutex); 5156 statep->controls[num] = pc; 5157 mutex_exit(&statep->usb_ac_mutex); 5158 5159 5160 return (pc); 5161 } 5162 5163 5164 static void 5165 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp) 5166 { 5167 kmem_free(ctrlp, sizeof (usb_audio_ctrl_t)); 5168 } 5169 5170 static void 5171 usb_ac_rem_controls(usb_ac_state_t *statep) 5172 { 5173 usb_audio_ctrl_t *ctrlp; 5174 5175 for (int i = 0; i < CTL_NUM; i++) { 5176 ctrlp = statep->controls[i]; 5177 if (ctrlp) { 5178 if (ctrlp->af_ctrlp != NULL) 5179 audio_dev_del_control(ctrlp->af_ctrlp); 5180 5181 usb_audio_ctrl_free(ctrlp); 5182 mutex_enter(&statep->usb_ac_mutex); 5183 statep->controls[i] = NULL; 5184 mutex_exit(&statep->usb_ac_mutex); 5185 } 5186 } 5187 5188 } 5189 5190 5191 static int 5192 usb_ac_add_controls(usb_ac_state_t *statep) 5193 { 5194 int rv = USB_FAILURE; 5195 usb_audio_format_t *format; 5196 5197 5198 if (statep->engines[0].af_engp) { 5199 /* Init controls for play format */ 5200 format = &(statep->engines[0].fmt); 5201 if (format->ch == 2) { 5202 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO, 5203 statep->engines[0].af_defgain); 5204 } else { 5205 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO, 5206 statep->engines[0].af_defgain); 5207 } 5208 5209 } 5210 5211 /* Init controls for rec format */ 5212 if (statep->engines[1].af_engp) { 5213 format = &(statep->engines[1].fmt); 5214 if (format->ch == 2) { 5215 (void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO, 5216 statep->engines[1].af_defgain); 5217 } else { 5218 (void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO, 5219 statep->engines[1].af_defgain); 5220 } 5221 5222 /* Add monitor control */ 5223 { 5224 (void) usb_audio_ctrl_alloc(statep, 5225 CTL_MONITOR_GAIN, 0); 5226 } 5227 5228 /* Add ports control */ 5229 { 5230 (void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC, 5231 statep->usb_ac_input_ports); 5232 } 5233 5234 } 5235 5236 5237 rv = USB_SUCCESS; 5238 5239 OUT: 5240 if (rv != USB_SUCCESS) 5241 usb_ac_rem_controls(statep); 5242 return (rv); 5243 } 5244 5245 5246 5247 5248 5249 /*ARGSUSED*/ 5250 static int 5251 usb_audio_unregister(usb_ac_state_t *statep) 5252 { 5253 int i; 5254 5255 if (statep == NULL) 5256 return (USB_SUCCESS); 5257 5258 if (statep->usb_ac_audio_dev == NULL) 5259 return (USB_SUCCESS); 5260 5261 if ((statep->flags & AF_REGISTERED) && 5262 audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) { 5263 return (USB_FAILURE); 5264 } 5265 mutex_enter(&statep->usb_ac_mutex); 5266 statep->flags &= ~AF_REGISTERED; 5267 mutex_exit(&statep->usb_ac_mutex); 5268 5269 for (i = 0; i < USB_AC_ENG_MAX; i++) 5270 usb_ac_rem_eng(statep, &statep->engines[i]); 5271 5272 usb_ac_rem_controls(statep); 5273 5274 audio_dev_free(statep->usb_ac_audio_dev); 5275 5276 mutex_enter(&statep->usb_ac_mutex); 5277 statep->usb_ac_audio_dev = NULL; 5278 mutex_exit(&statep->usb_ac_mutex); 5279 5280 return (USB_SUCCESS); 5281 } 5282 5283 5284 static int 5285 usb_audio_register(usb_ac_state_t *statep) { 5286 audio_dev_t *af_devp; 5287 int rv = USB_FAILURE; 5288 int n; 5289 5290 af_devp = audio_dev_alloc(statep->usb_ac_dip, 0); 5291 audio_dev_set_description(af_devp, "USB Audio"); 5292 audio_dev_set_version(af_devp, "1.0"); 5293 5294 mutex_enter(&statep->usb_ac_mutex); 5295 statep->usb_ac_audio_dev = af_devp; 5296 mutex_exit(&statep->usb_ac_mutex); 5297 5298 5299 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 5300 if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n])) 5301 != USB_SUCCESS) { 5302 USB_DPRINTF_L2(PRINT_MASK_ATTA, 5303 statep->usb_ac_log_handle, 5304 "usb_audio_register: add engine n =%d failed", n); 5305 goto OUT; 5306 } 5307 } 5308 5309 5310 if (usb_ac_add_controls(statep) != USB_SUCCESS) { 5311 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5312 "usb_audio_register: add controls failed"); 5313 goto OUT; 5314 } 5315 5316 if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) { 5317 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5318 "usb_audio_register: set defaults failed"); 5319 goto OUT; 5320 } 5321 5322 if (audio_dev_register(af_devp) != DDI_SUCCESS) { 5323 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5324 "audio_dev_register() failed"); 5325 goto OUT; 5326 } 5327 mutex_enter(&statep->usb_ac_mutex); 5328 statep->flags |= AF_REGISTERED; 5329 mutex_exit(&statep->usb_ac_mutex); 5330 5331 rv = USB_SUCCESS; 5332 5333 OUT: 5334 if (rv != USB_SUCCESS) { 5335 (void) usb_audio_unregister(statep); 5336 } 5337 return (rv); 5338 } 5339 5340 5341 int 5342 usb_ac_get_audio(void *handle, void *buf, int samples) 5343 { 5344 usb_ac_state_t *statep = (usb_ac_state_t *)(handle); 5345 usb_audio_eng_t *engp = &(statep->engines[0]); 5346 unsigned reqframes = samples >> engp->frsmshift; 5347 unsigned frames; 5348 unsigned i; 5349 size_t sz; 5350 caddr_t bp = buf; 5351 5352 mutex_enter(&engp->lock); 5353 if (!engp->started) { 5354 mutex_exit(&engp->lock); 5355 5356 return (0); 5357 } 5358 engp->busy = B_TRUE; 5359 mutex_exit(&engp->lock); 5360 5361 /* break requests from the driver into fragment sized chunks */ 5362 for (i = 0; i < reqframes; i += frames) { 5363 5364 mutex_enter(&engp->lock); 5365 frames = reqframes - i; 5366 if (frames > engp->fragfr) 5367 frames = engp->fragfr; 5368 5369 sz = (frames << engp->frsmshift) << engp->smszshift; 5370 5371 /* must move data before updating framework */ 5372 usb_eng_bufio(engp, bp, sz); 5373 engp->frames += frames; 5374 bp += sz; 5375 5376 mutex_exit(&engp->lock); 5377 } 5378 5379 mutex_enter(&engp->lock); 5380 engp->io_count++; 5381 engp->busy = B_FALSE; 5382 cv_signal(&engp->usb_audio_cv); 5383 mutex_exit(&engp->lock); 5384 5385 return (samples); 5386 } 5387 5388 5389 5390 void 5391 usb_ac_send_audio(void *handle, void *buf, int samples) 5392 { 5393 usb_ac_state_t *statep = (usb_ac_state_t *)(handle); 5394 usb_audio_eng_t *engp = &(statep->engines[1]); 5395 unsigned reqframes = samples >> engp->frsmshift; 5396 unsigned frames; 5397 unsigned i; 5398 size_t sz; 5399 caddr_t bp = buf; 5400 5401 mutex_enter(&engp->lock); 5402 5403 if (!engp->started) { 5404 5405 mutex_exit(&engp->lock); 5406 return; 5407 } 5408 engp->busy = B_TRUE; 5409 mutex_exit(&engp->lock); 5410 5411 /* break requests from the driver into fragment sized chunks */ 5412 for (i = 0; i < reqframes; i += frames) { 5413 mutex_enter(&engp->lock); 5414 5415 frames = reqframes - i; 5416 if (frames > engp->fragfr) 5417 frames = engp->fragfr; 5418 5419 sz = (frames << engp->frsmshift) << engp->smszshift; 5420 5421 /* must move data before updating framework */ 5422 usb_eng_bufio(engp, bp, sz); 5423 engp->frames += frames; 5424 bp += sz; 5425 5426 mutex_exit(&engp->lock); 5427 } 5428 5429 mutex_enter(&engp->lock); 5430 engp->io_count++; 5431 engp->busy = B_FALSE; 5432 cv_signal(&engp->usb_audio_cv); 5433 mutex_exit(&engp->lock); 5434 } 5435 5436 5437 /* 5438 * ************************************************************************** 5439 * audio framework engine callbacks 5440 */ 5441 static int 5442 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp) 5443 { 5444 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5445 usb_ac_state_t *statep = engp->statep; 5446 int rv = EIO; 5447 5448 _NOTE(ARGUNUSED(flag)); 5449 5450 if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) { 5451 5452 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5453 "usb_ac_open() failed"); 5454 return (EIO); 5455 } 5456 5457 mutex_enter(&engp->lock); 5458 5459 engp->intrate = 150; 5460 engp->sampsz = engp->fmt.prec / 8; 5461 engp->framesz = engp->sampsz * engp->fmt.ch; 5462 5463 engp->frsmshift = engp->fmt.ch / 2; 5464 engp->smszshift = engp->sampsz / 2; 5465 5466 /* 5467 * In order to match the requested number of samples per interrupt 5468 * from SADA drivers when computing the fragment size, 5469 * we need to first truncate the floating point result from 5470 * sample rate * channels / intr rate 5471 * then adjust up to an even number, before multiplying it 5472 * with the sample size 5473 */ 5474 engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate; 5475 if (engp->fragsz & 1) 5476 engp->fragsz++; 5477 engp->fragsz *= engp->sampsz; 5478 engp->fragfr = engp->fragsz / engp->framesz; 5479 5480 engp->nfrags = 10; 5481 engp->bufsz = engp->fragsz * engp->nfrags; 5482 5483 engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP); 5484 engp->bufpos = engp->bufp; 5485 engp->bufendp = engp->bufp + engp->bufsz; 5486 engp->frames = 0; 5487 engp->io_count = 0; 5488 engp->bufio_count = 0; 5489 engp->started = B_FALSE; 5490 engp->busy = B_FALSE; 5491 5492 *nframesp = engp->nfrags * engp->fragfr; 5493 *bufp = engp->bufp; 5494 5495 mutex_exit(&engp->lock); 5496 5497 if (usb_ac_setup(statep, engp) != USB_SUCCESS) { 5498 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5499 "device setup failed"); 5500 goto OUT; 5501 } 5502 5503 5504 5505 mutex_enter(&statep->usb_ac_mutex); 5506 statep->flags |= AD_SETUP; 5507 mutex_exit(&statep->usb_ac_mutex); 5508 5509 rv = 0; 5510 5511 5512 OUT: 5513 if (rv != 0) 5514 usb_engine_close(arg); 5515 5516 return (rv); 5517 } 5518 5519 5520 static void 5521 usb_engine_close(void *arg) 5522 { 5523 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5524 usb_ac_state_t *statep = engp->statep; 5525 5526 mutex_enter(&engp->lock); 5527 while (engp->busy) { 5528 cv_wait(&engp->usb_audio_cv, &engp->lock); 5529 } 5530 5531 mutex_exit(&engp->lock); 5532 5533 if (statep->flags & AD_SETUP) { 5534 usb_ac_teardown(statep, engp); 5535 mutex_enter(&statep->usb_ac_mutex); 5536 statep->flags &= ~AD_SETUP; 5537 mutex_exit(&statep->usb_ac_mutex); 5538 } 5539 mutex_enter(&engp->lock); 5540 5541 if (engp->bufp != NULL) { 5542 kmem_free(engp->bufp, engp->bufsz); 5543 engp->bufp = NULL; 5544 engp->bufpos = NULL; 5545 engp->bufendp = NULL; 5546 } 5547 5548 mutex_exit(&engp->lock); 5549 5550 usb_ac_close(statep->usb_ac_dip); 5551 } 5552 5553 5554 5555 static int 5556 usb_engine_start(void *arg) 5557 { 5558 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5559 int rv = 0; 5560 int (*start)(usb_ac_state_t *, usb_audio_eng_t *); 5561 5562 mutex_enter(&engp->lock); 5563 engp->started = B_TRUE; 5564 mutex_exit(&engp->lock); 5565 5566 usb_ac_state_t *statep = engp->statep; 5567 5568 start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ? 5569 usb_ac_start_play : usb_ac_start_record; 5570 5571 if ((*start)(statep, engp) != USB_SUCCESS) { 5572 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5573 "failed to start %d engine", engp->af_eflags); 5574 rv = EIO; 5575 } 5576 5577 5578 return (rv); 5579 } 5580 5581 5582 static void 5583 usb_engine_stop(void *arg) 5584 { 5585 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5586 5587 mutex_enter(&engp->lock); 5588 engp->started = B_FALSE; 5589 mutex_exit(&engp->lock); 5590 5591 usb_ac_state_t *statep = engp->statep; 5592 void (*stop)(usb_ac_state_t *, usb_audio_eng_t *); 5593 5594 stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ? 5595 usb_ac_stop_play : usb_ac_stop_record; 5596 5597 (*stop)(statep, engp); 5598 } 5599 5600 5601 static uint64_t 5602 usb_engine_count(void *arg) 5603 { 5604 usb_audio_eng_t *engp = arg; 5605 uint64_t val; 5606 5607 mutex_enter(&engp->lock); 5608 val = engp->frames; 5609 mutex_exit(&engp->lock); 5610 5611 return (val); 5612 } 5613 5614 5615 static int 5616 usb_engine_format(void *arg) 5617 { 5618 usb_audio_eng_t *engp = arg; 5619 5620 switch (engp->fmt.enc) { 5621 case USB_AUDIO_FORMAT_TYPE1_MULAW: 5622 return (AUDIO_FORMAT_ULAW); 5623 case USB_AUDIO_FORMAT_TYPE1_ALAW: 5624 return (AUDIO_FORMAT_ALAW); 5625 case USB_AUDIO_FORMAT_TYPE1_PCM8: 5626 return (AUDIO_FORMAT_U8); 5627 5628 case USB_AUDIO_FORMAT_TYPE1_PCM: 5629 break; 5630 default: 5631 return (AUDIO_FORMAT_NONE); 5632 } 5633 5634 switch (engp->fmt.prec) { 5635 case USB_AUDIO_PRECISION_8: 5636 return (AUDIO_FORMAT_S8); 5637 case USB_AUDIO_PRECISION_16: 5638 return (AUDIO_FORMAT_S16_LE); 5639 case USB_AUDIO_PRECISION_24: 5640 return (AUDIO_FORMAT_S24_LE); 5641 case USB_AUDIO_PRECISION_32: 5642 return (AUDIO_FORMAT_S32_LE); 5643 default: 5644 break; 5645 } 5646 return (AUDIO_FORMAT_NONE); 5647 5648 5649 } 5650 5651 static int 5652 usb_engine_channels(void *arg) 5653 { 5654 usb_audio_eng_t *engp = arg; 5655 5656 return (engp->fmt.ch); 5657 } 5658 5659 5660 static int 5661 usb_engine_rate(void *arg) 5662 { 5663 usb_audio_eng_t *engp = arg; 5664 5665 return (engp->fmt.sr); 5666 } 5667 5668 5669 /*ARGSUSED*/ 5670 static void 5671 usb_engine_sync(void *arg, unsigned nframes) 5672 { 5673 /* Do nothing */ 5674 } 5675 5676 5677 static unsigned 5678 usb_engine_qlen(void *arg) 5679 { 5680 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5681 5682 return (engp->fragfr); 5683 } 5684 5685 /* 5686 * ************************************************************************** 5687 * interfaces used by USB audio 5688 */ 5689 5690 /*ARGSUSED*/ 5691 static int 5692 usb_change_phy_vol(usb_ac_state_t *statep, int value) 5693 { 5694 usb_audio_ctrl_t *ctrlp; 5695 uint64_t cval = 0; 5696 int64_t left, right, delta = 0; 5697 5698 ctrlp = statep->controls[CTL_VOLUME_STERO]; 5699 5700 ASSERT(value != 0); 5701 5702 delta = (value < 0)?-1:1; 5703 5704 left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta; 5705 right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta; 5706 5707 if (left > AF_MAX_GAIN) 5708 left = AF_MAX_GAIN; 5709 if (right > AF_MAX_GAIN) 5710 right = AF_MAX_GAIN; 5711 5712 if (left < AF_MIN_GAIN) 5713 left = AF_MIN_GAIN; 5714 if (right < AF_MIN_GAIN) 5715 right = AF_MIN_GAIN; 5716 5717 cval = AUDIO_CTRL_STEREO_VAL(left, right); 5718 5719 if (audio_control_write(ctrlp->af_ctrlp, cval)) { 5720 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5721 "updateing control to value 0x%llx by driver failed", 5722 (long long unsigned)cval); 5723 return (USB_FAILURE); 5724 } 5725 return (USB_SUCCESS); 5726 }