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