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