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_n_srs = 1; 3006 format.fmt_srs = (uint_t *)&(engine->fmt.sr); 3007 format.fmt_chns = (uchar_t)engine->fmt.ch; 3008 format.fmt_precision = (uchar_t)engine->fmt.prec; 3009 format.fmt_encoding = (uchar_t)engine->fmt.enc; 3010 3011 old_setup_teardown_count = streams_infop->acs_setup_teardown_count; 3012 3013 /* isoc pipe not open and playing is not in progress */ 3014 if (old_setup_teardown_count) { 3015 streams_infop->acs_setup_teardown_count = 1; 3016 3017 mutex_exit(&uacp->usb_ac_mutex); 3018 usb_ac_release_access(uacp); 3019 3020 usb_ac_stop_play(uacp, engine); 3021 usb_ac_teardown(uacp, engine); 3022 3023 usb_ac_serialize_access(uacp); 3024 mutex_enter(&uacp->usb_ac_mutex); 3025 } 3026 3027 /* 3028 * Set format for the streaming interface with lower write queue 3029 * This boils down to set_alternate interface command in 3030 * usb_as and the reply mp contains the currently active 3031 * alternate number that is stored in the as_req structure 3032 */ 3033 if (usb_ac_send_as_cmd(uacp, engine, 3034 USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) { 3035 USB_DPRINTF_L2(PRINT_MASK_ALL, 3036 uacp->usb_ac_log_handle, 3037 "usb_ac_set_format: failed"); 3038 goto fail; 3039 3040 } 3041 int sample = engine->fmt.sr; 3042 3043 /* Set the sample rate */ 3044 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ, 3045 &sample) != USB_SUCCESS) { 3046 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3047 "usb_ac_set_format: setting format failed"); 3048 goto fail; 3049 3050 } 3051 3052 mutex_exit(&uacp->usb_ac_mutex); 3053 3054 usb_ac_release_access(uacp); 3055 3056 /* This should block until successful */ 3057 if (old_setup_teardown_count) { 3058 (void) usb_ac_setup(uacp, engine); 3059 } 3060 3061 mutex_enter(&uacp->usb_ac_mutex); 3062 streams_infop->acs_setup_teardown_count = old_setup_teardown_count; 3063 mutex_exit(&uacp->usb_ac_mutex); 3064 3065 return (USB_SUCCESS); 3066 fail: 3067 streams_infop->acs_setup_teardown_count = old_setup_teardown_count; 3068 mutex_exit(&uacp->usb_ac_mutex); 3069 usb_ac_release_access(uacp); 3070 3071 return (USB_FAILURE); 3072 3073 } 3074 3075 /* 3076 * usb_ac_start_play 3077 * Send a start_play command down to usb_as 3078 * Check power is done in usb_ac_send_as_cmd() 3079 */ 3080 static int 3081 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3082 { 3083 int samples; 3084 usb_audio_play_req_t play_req; 3085 3086 3087 mutex_enter(&uacp->usb_ac_mutex); 3088 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3089 mutex_exit(&uacp->usb_ac_mutex); 3090 3091 return (USB_FAILURE); 3092 } 3093 mutex_exit(&uacp->usb_ac_mutex); 3094 3095 usb_ac_serialize_access(uacp); 3096 3097 mutex_enter(&uacp->usb_ac_mutex); 3098 3099 3100 3101 /* Check for continuous sample rate done in usb_as */ 3102 samples = engine->fmt.sr * engine->fmt.ch / engine->intrate; 3103 if (samples & engine->fmt.ch) { 3104 samples++; 3105 } 3106 3107 play_req.up_samples = samples; 3108 play_req.up_handle = uacp; 3109 3110 /* Send setup command to usb_as */ 3111 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY, 3112 (void *)&play_req) != USB_SUCCESS) { 3113 3114 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3115 "usb_ac_start_play: failure"); 3116 3117 mutex_exit(&uacp->usb_ac_mutex); 3118 3119 usb_ac_release_access(uacp); 3120 3121 return (USB_FAILURE); 3122 } 3123 3124 mutex_exit(&uacp->usb_ac_mutex); 3125 3126 usb_ac_release_access(uacp); 3127 3128 return (USB_SUCCESS); 3129 } 3130 3131 3132 /* 3133 * usb_ac_stop_play: 3134 * Stop the play engine 3135 * called from mixer framework. 3136 */ 3137 void 3138 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3139 { 3140 3141 if (engine == NULL) { 3142 engine = &(uacp->engines[0]); 3143 } 3144 mutex_enter(&uacp->usb_ac_mutex); 3145 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3146 mutex_exit(&uacp->usb_ac_mutex); 3147 3148 return; 3149 } 3150 mutex_exit(&uacp->usb_ac_mutex); 3151 3152 usb_ac_serialize_access(uacp); 3153 mutex_enter(&uacp->usb_ac_mutex); 3154 3155 /* Send setup command to usb_as */ 3156 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY, 3157 (void *)NULL) != USB_SUCCESS) { 3158 3159 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3160 "usb_ac_do_pause_play: failure"); 3161 } 3162 3163 mutex_exit(&uacp->usb_ac_mutex); 3164 usb_ac_release_access(uacp); 3165 } 3166 3167 3168 /* 3169 * usb_ac_start_record: 3170 * Sends a start record command down to usb_as. 3171 * Check power is done in usb_ac_send_as_cmd() 3172 */ 3173 static int 3174 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3175 { 3176 3177 3178 mutex_enter(&uacp->usb_ac_mutex); 3179 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3180 mutex_exit(&uacp->usb_ac_mutex); 3181 3182 return (USB_FAILURE); 3183 } 3184 mutex_exit(&uacp->usb_ac_mutex); 3185 3186 usb_ac_serialize_access(uacp); 3187 mutex_enter(&uacp->usb_ac_mutex); 3188 3189 3190 /* Send setup command to usb_as */ 3191 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD, 3192 (void *)uacp) != USB_SUCCESS) { 3193 3194 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3195 "usb_ac_start_record: failure"); 3196 3197 mutex_exit(&uacp->usb_ac_mutex); 3198 3199 usb_ac_release_access(uacp); 3200 3201 return (USB_FAILURE); 3202 } 3203 3204 mutex_exit(&uacp->usb_ac_mutex); 3205 usb_ac_release_access(uacp); 3206 3207 return (USB_SUCCESS); 3208 } 3209 3210 3211 /* 3212 * usb_ac_stop_record: 3213 * Wrapper function for usb_ac_do_stop_record and is 3214 * called form mixer framework. 3215 */ 3216 static void 3217 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine) 3218 { 3219 3220 usb_ac_serialize_access(uacp); 3221 mutex_enter(&uacp->usb_ac_mutex); 3222 3223 /* Send setup command to usb_as */ 3224 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD, 3225 NULL) != USB_SUCCESS) { 3226 3227 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3228 "usb_ac_do_stop_record: failure"); 3229 } 3230 3231 mutex_exit(&uacp->usb_ac_mutex); 3232 usb_ac_release_access(uacp); 3233 } 3234 3235 3236 /* 3237 * Helper Functions for Mixer callbacks 3238 * 3239 * usb_ac_get_maxmin_volume: 3240 * Send USBA command down to get the maximum or minimum gain balance 3241 * Calculate min or max gain balance and return that. Return 3242 * USB_FAILURE for failure cases 3243 */ 3244 /* ARGSUSED */ 3245 static int 3246 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd, 3247 int dir, int feature_unitID, short *max_or_minp) 3248 { 3249 mblk_t *data = NULL; 3250 usb_cr_t cr; 3251 usb_cb_flags_t cb_flags; 3252 3253 3254 mutex_exit(&uacp->usb_ac_mutex); 3255 3256 if (usb_pipe_sync_ctrl_xfer( 3257 uacp->usb_ac_dip, 3258 uacp->usb_ac_default_ph, 3259 USB_DEV_REQ_DEV_TO_HOST | 3260 USB_DEV_REQ_TYPE_CLASS | 3261 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 3262 cmd, /* bRequest */ 3263 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 3264 /* feature unit and id */ 3265 (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */ 3266 2, /* wLength */ 3267 &data, 3268 USB_ATTRS_NONE, 3269 &cr, &cb_flags, 3270 USB_FLAGS_SLEEP) != USB_SUCCESS) { 3271 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3272 "usb_ac_get_maxmin_volume: failed, " 3273 "cr=%d, cb=0x%x cmd=%d, data=0x%p", 3274 cr, cb_flags, cmd, (void *)data); 3275 3276 freemsg(data); 3277 mutex_enter(&uacp->usb_ac_mutex); 3278 3279 return (USB_FAILURE); 3280 } 3281 3282 mutex_enter(&uacp->usb_ac_mutex); 3283 ASSERT(MBLKL(data) == 2); 3284 3285 *max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr; 3286 3287 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3288 "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp); 3289 3290 freemsg(data); 3291 3292 return (USB_SUCCESS); 3293 } 3294 3295 3296 /* 3297 * usb_ac_set_volume: 3298 * Send USBA command down to set the gain balance 3299 */ 3300 /* ARGSUSED */ 3301 static int 3302 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir, 3303 int feature_unitID) 3304 { 3305 mblk_t *data = NULL; 3306 usb_cr_t cr; 3307 usb_cb_flags_t cb_flags; 3308 int rval = USB_FAILURE; 3309 3310 3311 mutex_exit(&uacp->usb_ac_mutex); 3312 3313 /* Construct the mblk_t from gain for sending to USBA */ 3314 data = allocb(4, BPRI_HI); 3315 if (!data) { 3316 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3317 "usb_ac_set_volume: allocate data failed"); 3318 mutex_enter(&uacp->usb_ac_mutex); 3319 3320 return (USB_FAILURE); 3321 } 3322 3323 3324 3325 *(data->b_wptr++) = (char)gain; 3326 *(data->b_wptr++) = (char)(gain >> 8); 3327 3328 if ((rval = usb_pipe_sync_ctrl_xfer( 3329 uacp->usb_ac_dip, 3330 uacp->usb_ac_default_ph, 3331 USB_DEV_REQ_HOST_TO_DEV | 3332 USB_DEV_REQ_TYPE_CLASS | 3333 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 3334 USB_AUDIO_SET_CUR, /* bRequest */ 3335 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 3336 /* feature unit and id */ 3337 (feature_unitID << 8) | uacp->usb_ac_ifno, /* wIndex */ 3338 2, /* wLength */ 3339 &data, 0, 3340 &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 3341 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3342 "usb_ac_set_volume: failed, cr=%d cb=0x%x", 3343 cr, cb_flags); 3344 } 3345 3346 freemsg(data); 3347 mutex_enter(&uacp->usb_ac_mutex); 3348 3349 return (rval); 3350 } 3351 3352 3353 /* 3354 * usb_ac_set_mute is called for each unit that supports the 3355 * requested control from usb_ac_traverse_connections 3356 */ 3357 int 3358 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir, 3359 uint_t channel, uint_t control, uint_t muteval, uint_t *depth) 3360 { 3361 mblk_t *data; 3362 usb_cr_t cr; 3363 usb_cb_flags_t cb_flags; 3364 int rval = USB_FAILURE; 3365 3366 3367 if (usb_ac_feature_unit_check(uacp, featureID, 3368 dir, channel, control, 0, depth) != USB_SUCCESS) { 3369 3370 return (USB_FAILURE); 3371 } 3372 mutex_exit(&uacp->usb_ac_mutex); 3373 3374 /* Construct the mblk_t for sending to USBA */ 3375 data = allocb(1, BPRI_HI); 3376 3377 if (!data) { 3378 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3379 "usb_ac_set_mute: allocate data failed"); 3380 mutex_enter(&uacp->usb_ac_mutex); 3381 3382 return (USB_FAILURE); 3383 } 3384 3385 3386 *(data->b_wptr++) = (char)muteval; 3387 3388 if ((rval = usb_pipe_sync_ctrl_xfer( 3389 uacp->usb_ac_dip, 3390 uacp->usb_ac_default_ph, 3391 USB_DEV_REQ_HOST_TO_DEV | 3392 USB_DEV_REQ_TYPE_CLASS | 3393 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 3394 USB_AUDIO_SET_CUR, /* bRequest */ 3395 (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */ 3396 /* feature unit and id */ 3397 (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */ 3398 1, /* wLength */ 3399 &data, 3400 0, /* attributes */ 3401 &cr, &cb_flags, 0)) != USB_SUCCESS) { 3402 3403 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3404 "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags); 3405 } 3406 freemsg(data); 3407 3408 mutex_enter(&uacp->usb_ac_mutex); 3409 3410 return (rval); 3411 } 3412 3413 3414 /* 3415 * usb_ac_send_as_cmd: 3416 * Allocate message blk, send a command down to usb_as, 3417 * wait for the reply and free the message 3418 * 3419 * although not really needed to raise power if sending to as 3420 * it seems better to ensure that both interfaces are at full power 3421 */ 3422 static int 3423 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine, 3424 int cmd, void *arg) 3425 { 3426 usb_ac_streams_info_t *streams_infop; 3427 usb_ac_plumbed_t *plumb_infop; 3428 int rv; 3429 int rval; 3430 ldi_handle_t lh; 3431 3432 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3433 streams_infop = engine->streams; 3434 plumb_infop = streams_infop->acs_plumbed; 3435 3436 3437 lh = plumb_infop->acp_lh; 3438 3439 rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval); 3440 if (rv != 0) { 3441 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3442 "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv); 3443 3444 return (USB_FAILURE); 3445 } 3446 3447 return (USB_SUCCESS); 3448 } 3449 3450 3451 /* 3452 * usb_ac_serialize/release_access: 3453 */ 3454 static void 3455 usb_ac_serialize_access(usb_ac_state_t *uacp) 3456 { 3457 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0); 3458 } 3459 3460 static void 3461 usb_ac_release_access(usb_ac_state_t *uacp) 3462 { 3463 usb_release_access(uacp->usb_ac_ser_acc); 3464 } 3465 3466 3467 static void 3468 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep) 3469 { 3470 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 3471 3472 if (usb_ac_statep->usb_ac_pm != NULL) { 3473 mutex_enter(&usb_ac_statep->usb_ac_mutex); 3474 usb_ac_statep->usb_ac_pm->acpm_pm_busy++; 3475 3476 USB_DPRINTF_L4(PRINT_MASK_PM, 3477 usb_ac_statep->usb_ac_log_handle, 3478 "usb_ac_pm_busy_component: %d", 3479 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 3480 3481 mutex_exit(&usb_ac_statep->usb_ac_mutex); 3482 3483 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) != 3484 DDI_SUCCESS) { 3485 mutex_enter(&usb_ac_statep->usb_ac_mutex); 3486 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 3487 3488 USB_DPRINTF_L2(PRINT_MASK_PM, 3489 usb_ac_statep->usb_ac_log_handle, 3490 "usb_ac_pm_busy_component failed: %d", 3491 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 3492 3493 mutex_exit(&usb_ac_statep->usb_ac_mutex); 3494 } 3495 } 3496 } 3497 3498 3499 static void 3500 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep) 3501 { 3502 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 3503 3504 if (usb_ac_statep->usb_ac_pm != NULL) { 3505 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) == 3506 DDI_SUCCESS) { 3507 mutex_enter(&usb_ac_statep->usb_ac_mutex); 3508 ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0); 3509 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 3510 3511 USB_DPRINTF_L4(PRINT_MASK_PM, 3512 usb_ac_statep->usb_ac_log_handle, 3513 "usb_ac_pm_idle_component: %d", 3514 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 3515 3516 mutex_exit(&usb_ac_statep->usb_ac_mutex); 3517 } 3518 } 3519 } 3520 3521 3522 /* 3523 * handle read from plumbed drivers 3524 */ 3525 static void 3526 usb_ac_reader(void *argp) 3527 { 3528 usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp; 3529 usb_ac_state_t *uacp = acp->acp_uacp; 3530 ldi_handle_t lh; 3531 mblk_t *mp; 3532 int rv; 3533 timestruc_t tv = {0}; 3534 3535 mutex_enter(&uacp->usb_ac_mutex); 3536 lh = acp->acp_lh; 3537 tv.tv_sec = usb_ac_wait_hid; 3538 3539 while (acp->acp_flags & ACP_ENABLED) { 3540 mp = NULL; 3541 3542 mutex_exit(&uacp->usb_ac_mutex); 3543 3544 rv = ldi_getmsg(lh, &mp, &tv); 3545 3546 mutex_enter(&uacp->usb_ac_mutex); 3547 3548 if (rv == ENODEV) { 3549 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3550 "Device is not availabe"); 3551 break; 3552 } 3553 3554 3555 if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0) 3556 rv = usb_ac_read_msg(acp, mp); 3557 3558 } 3559 mutex_exit(&uacp->usb_ac_mutex); 3560 } 3561 3562 3563 /* 3564 * setup threads to read from the other usb modules that may send unsolicited 3565 * or asynchronous messages, which is only hid currently 3566 */ 3567 static int 3568 usb_ac_plumb(usb_ac_plumbed_t *acp) 3569 { 3570 usb_ac_state_t *uacp = acp->acp_uacp; 3571 dev_info_t *dip; 3572 dev_info_t *acp_dip; 3573 int acp_inst; 3574 char *acp_name; 3575 char tq_nm[128]; 3576 int rv = USB_FAILURE; 3577 3578 mutex_enter(&uacp->usb_ac_mutex); 3579 3580 dip = uacp->usb_ac_dip; 3581 3582 acp_dip = acp->acp_dip; 3583 acp_inst = ddi_get_instance(acp_dip); 3584 acp_name = (char *)ddi_driver_name(acp_dip); 3585 3586 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3587 "usb_ac_plumb:begin"); 3588 3589 if (strcmp(acp_name, "hid") != 0) { 3590 rv = USB_SUCCESS; 3591 goto OUT; 3592 } 3593 3594 (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq", 3595 ddi_driver_name(acp_dip), acp_inst); 3596 3597 acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0); 3598 if (acp->acp_tqp == NULL) 3599 goto OUT; 3600 3601 if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp, 3602 DDI_SLEEP) != DDI_SUCCESS) 3603 goto OUT; 3604 3605 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3606 "usb_ac_plumb: dispatched reader"); 3607 3608 rv = USB_SUCCESS; 3609 3610 OUT: 3611 mutex_exit(&uacp->usb_ac_mutex); 3612 3613 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3614 "usb_ac_plumb: done, rv=%d", rv); 3615 3616 return (rv); 3617 } 3618 3619 3620 static void 3621 usb_ac_mux_plumbing_tq(void *arg) 3622 { 3623 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 3624 3625 if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS) 3626 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3627 "usb_ac_mux_plumbing_tq:failed"); 3628 } 3629 3630 3631 static int 3632 usb_ac_do_plumbing(usb_ac_state_t *uacp) 3633 { 3634 dev_info_t *dip = uacp->usb_ac_dip; 3635 int inst = ddi_get_instance(dip); 3636 char tq_nm[128]; 3637 int rv = USB_FAILURE; 3638 3639 (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq", 3640 ddi_driver_name(dip), inst); 3641 3642 uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0); 3643 if (uacp->tqp == NULL) { 3644 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3645 "usb_ac_do_plumbing: ddi_taskq_create failed"); 3646 goto OUT; 3647 } 3648 3649 if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp, 3650 DDI_SLEEP) != DDI_SUCCESS) { 3651 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3652 "usb_ac_do_plumbing: ddi_taskq_dispatch failed"); 3653 goto OUT; 3654 } 3655 3656 rv = USB_SUCCESS; 3657 3658 OUT: 3659 return (rv); 3660 } 3661 3662 3663 3664 static void 3665 usb_ac_mux_unplumbing_tq(void *arg) 3666 { 3667 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 3668 3669 if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS) 3670 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3671 "usb_ac_mux_unplumbing:failed"); 3672 } 3673 3674 3675 static int 3676 usb_ac_do_unplumbing(usb_ac_state_t *uacp) 3677 { 3678 int rv = USB_FAILURE; 3679 3680 if (uacp->tqp == NULL) 3681 return (USB_SUCCESS); 3682 3683 if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq, 3684 (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) { 3685 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3686 "usb_ac_do_unplumbing: ddi_taskq_dispatch failed"); 3687 goto OUT; 3688 } 3689 3690 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3691 "usb_ac_do_unplumbing: waiting for unplumb thread"); 3692 3693 ddi_taskq_wait(uacp->tqp); 3694 rv = USB_SUCCESS; 3695 3696 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3697 "usb_ac_do_unplumbing: unplumb thread done"); 3698 3699 OUT: 3700 if (uacp->tqp != NULL) { 3701 ddi_taskq_destroy(uacp->tqp); 3702 uacp->tqp = NULL; 3703 } 3704 return (rv); 3705 } 3706 3707 3708 /* 3709 * teardown threads to the other usb modules 3710 * and clear structures as part of unplumbing 3711 */ 3712 static void 3713 usb_ac_unplumb(usb_ac_plumbed_t *acp) 3714 { 3715 usb_ac_streams_info_t *streams_infop; 3716 usb_ac_state_t *uacp = acp->acp_uacp; 3717 3718 3719 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3720 "usb_ac_unplumb: begin"); 3721 3722 if (acp->acp_tqp != NULL) { 3723 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3724 "usb_ac_unplumb: destroying taskq"); 3725 3726 ddi_taskq_destroy(acp->acp_tqp); 3727 } 3728 3729 mutex_enter(&uacp->usb_ac_mutex); 3730 3731 if (acp->acp_driver == USB_AS_PLUMBED) { 3732 /* 3733 * we bzero the streams info and plumbed structure 3734 * since there is no guarantee that the next plumbing 3735 * will be identical 3736 */ 3737 streams_infop = (usb_ac_streams_info_t *)acp->acp_data; 3738 3739 /* bzero the relevant plumbing structure */ 3740 bzero(streams_infop, sizeof (usb_ac_streams_info_t)); 3741 } 3742 bzero(acp, sizeof (usb_ac_plumbed_t)); 3743 3744 mutex_exit(&uacp->usb_ac_mutex); 3745 3746 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3747 "usb_ac_unplumb: done"); 3748 } 3749 3750 3751 /*ARGSUSED*/ 3752 static int 3753 usb_ac_mux_plumbing(usb_ac_state_t *uacp) 3754 { 3755 dev_info_t *dip; 3756 3757 /* get the usb_ac dip */ 3758 dip = uacp->usb_ac_dip; 3759 3760 /* Access to the global variables is synchronized */ 3761 mutex_enter(&uacp->usb_ac_mutex); 3762 3763 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3764 "usb_ac_mux_plumbing:state = %d", 3765 uacp->usb_ac_plumbing_state); 3766 3767 if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) { 3768 mutex_exit(&uacp->usb_ac_mutex); 3769 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3770 "usb_ac_mux_plumbing: audio streams driver" 3771 " already plumbed"); 3772 3773 return (USB_SUCCESS); 3774 } 3775 3776 /* usb_as and hid should be attached but double check */ 3777 if (usb_ac_online_siblings(uacp) != USB_SUCCESS) { 3778 mutex_exit(&uacp->usb_ac_mutex); 3779 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3780 "usb_ac_mux_plumbing:no audio streams driver plumbed"); 3781 3782 return (USB_FAILURE); 3783 } 3784 3785 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3786 "usb_ac_mux_plumbing: raising power"); 3787 mutex_exit(&uacp->usb_ac_mutex); 3788 3789 /* bring the device to full power */ 3790 usb_ac_pm_busy_component(uacp); 3791 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 3792 3793 /* avoid dips disappearing while we are plumbing */ 3794 usb_ac_hold_siblings(uacp); 3795 3796 mutex_enter(&uacp->usb_ac_mutex); 3797 3798 /* 3799 * walk all siblings and create the usb_ac<->usb_as and 3800 * usb_ac<->hid streams. return of 0 indicates no or 3801 * partial/failed plumbing 3802 */ 3803 if (usb_ac_mux_walk_siblings(uacp) == 0) { 3804 /* pretend that we are plumbed so we can unplumb */ 3805 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 3806 3807 mutex_exit(&uacp->usb_ac_mutex); 3808 3809 (void) usb_ac_mux_unplumbing(uacp); 3810 3811 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3812 "usb_ac_mux_plumbing: no audio streams driver plumbed"); 3813 3814 usb_ac_rele_siblings(uacp); 3815 3816 usb_ac_pm_idle_component(uacp); 3817 3818 return (USB_FAILURE); 3819 } 3820 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 3821 3822 /* restore state if we have already registered with the mixer */ 3823 if (uacp->usb_ac_registered_with_mixer) { 3824 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3825 "usb_ac_mux_plumbing:already registered with mixer," 3826 "restoring state"); 3827 3828 (void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP); 3829 3830 } else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) { 3831 mutex_exit(&uacp->usb_ac_mutex); 3832 3833 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3834 "usb_ac_mux_plumbing: mixer registration failed"); 3835 3836 (void) usb_ac_mux_unplumbing(uacp); 3837 3838 usb_ac_rele_siblings(uacp); 3839 3840 usb_ac_pm_idle_component(uacp); 3841 3842 return (USB_FAILURE); 3843 } 3844 3845 mutex_exit(&uacp->usb_ac_mutex); 3846 usb_ac_rele_siblings(uacp); 3847 3848 usb_ac_pm_idle_component(uacp); 3849 3850 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3851 "usb_ac_mux_plumbing:done"); 3852 3853 return (USB_SUCCESS); 3854 } 3855 3856 3857 static int 3858 usb_ac_mux_unplumbing(usb_ac_state_t *uacp) 3859 { 3860 usb_ac_plumbed_t *acp; 3861 ldi_handle_t lh; 3862 dev_info_t *acp_dip; 3863 int inst; 3864 int i; 3865 dev_t devt; 3866 minor_t minor; 3867 int maxlinked = 0; 3868 3869 mutex_enter(&uacp->usb_ac_mutex); 3870 3871 3872 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) { 3873 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3874 "usb_ac_mux_unplumbing: already unplumbed!"); 3875 mutex_exit(&uacp->usb_ac_mutex); 3876 3877 return (USB_SUCCESS); 3878 } 3879 3880 /* usb_ac might not have anything plumbed yet */ 3881 if (uacp->usb_ac_current_plumbed_index == -1) { 3882 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3883 "usb_ac_mux_unplumbing: nothing plumbed"); 3884 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED; 3885 mutex_exit(&uacp->usb_ac_mutex); 3886 3887 return (USB_SUCCESS); 3888 } 3889 3890 /* do not allow detach if still busy */ 3891 if (uacp->usb_ac_busy_count) { 3892 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3893 "usb_ac_mux_unplumbing: mux still busy (%d)", 3894 uacp->usb_ac_busy_count); 3895 mutex_exit(&uacp->usb_ac_mutex); 3896 3897 return (USB_FAILURE); 3898 } 3899 3900 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED; 3901 3902 /* close ac-as and ac-hid streams */ 3903 maxlinked = uacp->usb_ac_current_plumbed_index + 1; 3904 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3905 "usb_ac_mux_unplumbing: maxlinked = %d", maxlinked); 3906 3907 for (i = 0; i < maxlinked; i++) { 3908 /* 3909 * we must save members of usb_ac_plumbed[] before calling 3910 * usb_ac_unplumb() because it clears the structure 3911 */ 3912 acp = &uacp->usb_ac_plumbed[i]; 3913 lh = acp->acp_lh; 3914 acp_dip = acp->acp_dip; 3915 devt = acp->acp_devt; 3916 3917 if (acp_dip == NULL) { 3918 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3919 "usb_ac_mux_unplumbing: [%d] - skipping", i); 3920 continue; 3921 } 3922 3923 minor = getminor(devt); 3924 inst = ddi_get_instance(acp_dip); 3925 3926 uacp->usb_ac_current_plumbed_index = i; 3927 3928 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3929 "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x", i, 3930 ddi_driver_name(acp_dip), inst, minor); 3931 3932 if (lh != NULL) { 3933 3934 acp->acp_flags &= ~ACP_ENABLED; 3935 3936 mutex_exit(&uacp->usb_ac_mutex); 3937 3938 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3939 "usb_ac_mux_unplumbing:[%d] - closing", i); 3940 3941 /* 3942 * ldi_close will cause panic if ldi_getmsg 3943 * is not finished. ddi_taskq_destroy will wait 3944 * for the thread to complete. 3945 */ 3946 usb_ac_unplumb(acp); 3947 (void) ldi_close(lh, FREAD|FWRITE, kcred); 3948 3949 3950 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3951 "usb_ac_mux_unplumbing: [%d] - unplumbed", i); 3952 3953 mutex_enter(&uacp->usb_ac_mutex); 3954 } 3955 } 3956 3957 mutex_exit(&uacp->usb_ac_mutex); 3958 3959 /* Wait till all activity in the default pipe has drained */ 3960 usb_ac_serialize_access(uacp); 3961 usb_ac_release_access(uacp); 3962 3963 mutex_enter(&uacp->usb_ac_mutex); 3964 uacp->usb_ac_current_plumbed_index = -1; 3965 mutex_exit(&uacp->usb_ac_mutex); 3966 3967 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3968 "usb_ac_mux_unplumbing: done"); 3969 3970 return (USB_SUCCESS); 3971 } 3972 3973 3974 /* 3975 * walk all siblings and create the ac<->as and ac<->hid streams 3976 */ 3977 static int 3978 usb_ac_mux_walk_siblings(usb_ac_state_t *uacp) 3979 { 3980 dev_info_t *pdip; 3981 dev_info_t *child_dip; 3982 major_t drv_major; 3983 minor_t drv_minor; 3984 int drv_instance; 3985 char *drv_name; 3986 dev_t drv_devt; 3987 ldi_handle_t drv_lh; 3988 ldi_ident_t li; 3989 int error; 3990 int count = 0; 3991 3992 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3993 3994 pdip = ddi_get_parent(uacp->usb_ac_dip); 3995 child_dip = ddi_get_child(pdip); 3996 3997 while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) { 3998 drv_instance = ddi_get_instance(child_dip); 3999 drv_name = (char *)ddi_driver_name(child_dip); 4000 4001 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4002 "usb_ac_mux_walk_siblings: plumbing %s%d count=%d", 4003 drv_name, drv_instance, count); 4004 4005 /* ignore own dip */ 4006 if (child_dip == uacp->usb_ac_dip) { 4007 child_dip = ddi_get_next_sibling(child_dip); 4008 continue; 4009 } 4010 drv_instance = ddi_get_instance(child_dip); 4011 4012 /* ignore other dip other than usb_as and hid */ 4013 if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) { 4014 uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED; 4015 drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance); 4016 } else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) { 4017 uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED; 4018 drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance); 4019 } else { 4020 drv_minor = drv_instance; 4021 uacp->usb_ac_plumbed[count].acp_driver = 4022 UNKNOWN_PLUMBED; 4023 child_dip = ddi_get_next_sibling(child_dip); 4024 4025 continue; 4026 } 4027 4028 if (!i_ddi_devi_attached(child_dip)) { 4029 child_dip = ddi_get_next_sibling(child_dip); 4030 4031 continue; 4032 } 4033 4034 if (DEVI_IS_DEVICE_REMOVED(child_dip)) { 4035 child_dip = ddi_get_next_sibling(child_dip); 4036 4037 continue; 4038 } 4039 4040 drv_major = ddi_driver_major(child_dip); 4041 4042 uacp->usb_ac_current_plumbed_index = count; 4043 4044 mutex_exit(&uacp->usb_ac_mutex); 4045 4046 drv_devt = makedevice(drv_major, drv_minor); 4047 4048 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4049 "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)", 4050 drv_name, drv_instance, drv_major, drv_minor); 4051 4052 error = ldi_ident_from_dip(uacp->usb_ac_dip, &li); 4053 if (error == 0) { 4054 mutex_enter(&uacp->usb_ac_mutex); 4055 uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED; 4056 mutex_exit(&uacp->usb_ac_mutex); 4057 4058 error = ldi_open_by_dev(&drv_devt, OTYP_CHR, 4059 FREAD|FWRITE, kcred, &drv_lh, li); 4060 ldi_ident_release(li); 4061 } 4062 4063 mutex_enter(&uacp->usb_ac_mutex); 4064 if (error) { 4065 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4066 "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)" 4067 " failed error=%d", drv_major, drv_minor, error); 4068 4069 return (0); 4070 } 4071 4072 uacp->usb_ac_plumbed[count].acp_uacp = uacp; 4073 uacp->usb_ac_plumbed[count].acp_devt = drv_devt; 4074 uacp->usb_ac_plumbed[count].acp_lh = drv_lh; 4075 uacp->usb_ac_plumbed[count].acp_dip = child_dip; 4076 uacp->usb_ac_plumbed[count].acp_ifno = 4077 usb_get_if_number(child_dip); 4078 4079 if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) { 4080 /* get registration data */ 4081 if (usb_ac_get_reg_data(uacp, drv_lh, count) != 4082 USB_SUCCESS) { 4083 4084 USB_DPRINTF_L3(PRINT_MASK_ALL, 4085 uacp->usb_ac_log_handle, 4086 "usb_ac_mux_walk_siblings:" 4087 "usb_ac_get_reg_data failed on %s%d", 4088 drv_name, drv_instance); 4089 4090 uacp->usb_ac_plumbed[count].acp_dip = NULL; 4091 4092 return (0); 4093 } 4094 } else if (uacp->usb_ac_plumbed[count].acp_driver == 4095 USB_AH_PLUMBED) { 4096 int rval; 4097 4098 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4099 "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d", 4100 drv_name, drv_instance); 4101 4102 mutex_exit(&uacp->usb_ac_mutex); 4103 4104 /* push usb_ah module on top of hid */ 4105 error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah", 4106 FKIOCTL, kcred, &rval); 4107 mutex_enter(&uacp->usb_ac_mutex); 4108 4109 if (error) { 4110 USB_DPRINTF_L2(PRINT_MASK_ALL, 4111 uacp->usb_ac_log_handle, 4112 "usb_ac_mux_walk_siblings: ldi_ioctl" 4113 "I_PUSH failed on %s%d, error=%d", 4114 drv_name, drv_instance, error); 4115 4116 uacp->usb_ac_plumbed[count].acp_dip = NULL; 4117 4118 /* skip plumbing the hid driver */ 4119 child_dip = ddi_get_next_sibling(child_dip); 4120 continue; 4121 } 4122 } else { 4123 /* should not be here */ 4124 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4125 "usb_ac_mux_walk_siblings:- unknown module %s%d", 4126 drv_name, drv_instance); 4127 count--; 4128 4129 uacp->usb_ac_plumbed[count].acp_dip = NULL; 4130 4131 /* skip plumbing an unknown module */ 4132 child_dip = ddi_get_next_sibling(child_dip); 4133 continue; 4134 } 4135 4136 mutex_exit(&uacp->usb_ac_mutex); 4137 error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]); 4138 mutex_enter(&uacp->usb_ac_mutex); 4139 4140 if (error != USB_SUCCESS) { 4141 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4142 "usb_ac_mux_walk_siblings: usb_ac_plumb " 4143 "failed for %s%d", drv_name, drv_instance); 4144 4145 return (0); 4146 } 4147 4148 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4149 "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x", 4150 drv_instance, drv_minor); 4151 4152 child_dip = ddi_get_next_sibling(child_dip); 4153 count++; 4154 } 4155 4156 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4157 "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux", 4158 count); 4159 4160 return (count); 4161 } 4162 4163 4164 /* 4165 * Register with mixer only after first plumbing. 4166 * Also do not register if earlier reg data 4167 * couldn't be received from at least one 4168 * streaming interface 4169 */ 4170 4171 static int 4172 usb_ac_mixer_registration(usb_ac_state_t *uacp) 4173 { 4174 usb_as_registration_t *asreg; 4175 int n; 4176 4177 if (uacp->usb_ac_registered_with_mixer) { 4178 return (USB_SUCCESS); 4179 } 4180 4181 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 4182 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) { 4183 break; 4184 } 4185 } 4186 4187 /* Haven't found a streaming interface; fail mixer registration */ 4188 if (n > USB_AC_MAX_AS_PLUMBED) { 4189 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4190 "usb_ac_mixer_registration:- no streaming interface found"); 4191 4192 return (USB_FAILURE); 4193 } 4194 4195 /* 4196 * Fill out streaming interface specific stuff 4197 * Note that we handle only one playing and one recording 4198 * streaming interface at the most 4199 */ 4200 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 4201 int ch, chs, id; 4202 4203 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) { 4204 continue; 4205 } 4206 4207 asreg = &(uacp->usb_ac_streams[n].acs_streams_reg); 4208 if (asreg->reg_valid == 0) { 4209 continue; 4210 } 4211 4212 4213 chs = asreg->reg_formats[0].fmt_chns; 4214 4215 /* check if any channel supports vol. control for this fmt */ 4216 for (ch = 0; ch <= chs; ch++) { 4217 if ((id = usb_ac_get_featureID(uacp, 4218 asreg->reg_mode, ch, 4219 USB_AUDIO_VOLUME_CONTROL)) != -1) { 4220 USB_DPRINTF_L3(PRINT_MASK_ALL, 4221 uacp->usb_ac_log_handle, 4222 "usb_ac_mixer_registration:n= [%d]" 4223 "- dir=%d featureID=%d", 4224 n, asreg->reg_mode, id); 4225 4226 break; 4227 } 4228 } 4229 4230 uacp->usb_ac_streams[n].acs_default_gain = 4231 (id == USB_AC_ID_NONE) ? (AF_MAX_GAIN): (AF_MAX_GAIN*3/4); 4232 4233 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4234 "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d" 4235 "default_gain=%d id=%d", 4236 n, asreg->reg_mode, chs, 4237 uacp->usb_ac_streams[n].acs_default_gain, id); 4238 4239 } 4240 4241 /* the rest */ 4242 4243 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4244 "usb_ac_mixer_registration: calling usb_audio_register"); 4245 4246 mutex_exit(&uacp->usb_ac_mutex); 4247 4248 if (usb_audio_register(uacp) != USB_SUCCESS) { 4249 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4250 "usb_ac_mixer_registration: usb_audio_register failed"); 4251 4252 mutex_enter(&uacp->usb_ac_mutex); 4253 4254 return (USB_FAILURE); 4255 } 4256 4257 mutex_enter(&uacp->usb_ac_mutex); 4258 4259 uacp->usb_ac_registered_with_mixer = 1; 4260 4261 return (USB_SUCCESS); 4262 } 4263 4264 4265 /* 4266 * Get registriations data when driver attach 4267 */ 4268 static int 4269 usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index) 4270 { 4271 int n, error, rval; 4272 usb_as_registration_t *streams_reg; 4273 4274 4275 ASSERT(uacp->usb_ac_registered_with_mixer == 0); 4276 4277 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 4278 /* 4279 * We haven't received registration data 4280 * from n-th streaming interface in the array 4281 */ 4282 if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) { 4283 break; 4284 } 4285 } 4286 4287 if (n >= USB_AC_MAX_AS_PLUMBED) { 4288 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4289 "More than 2 streaming interfaces (play " 4290 "and/or record) currently not supported"); 4291 4292 return (USB_FAILURE); 4293 } 4294 4295 /* take the stream reg struct with the same index */ 4296 streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg; 4297 4298 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4299 "usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d", 4300 (void *)streams_reg, n); 4301 4302 mutex_exit(&uacp->usb_ac_mutex); 4303 4304 if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION, 4305 (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) { 4306 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4307 "usb_ac_get_reg_data: ldi_ioctl failed for" 4308 "mixer registration error=%d", error); 4309 4310 mutex_enter(&uacp->usb_ac_mutex); 4311 4312 return (USB_FAILURE); 4313 } else { 4314 mutex_enter(&uacp->usb_ac_mutex); 4315 4316 rval = usb_ac_setup_plumbed(uacp, index, n); 4317 4318 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4319 "usb_ac_get_reg_data:usb_ac_streams[%d]: " 4320 "received_reg_data=%d type=%s", index, 4321 uacp->usb_ac_streams[n].acs_rcvd_reg_data, 4322 ((streams_reg->reg_mode == USB_AUDIO_PLAY) ? 4323 "play" : "record")); 4324 4325 usb_ac_print_reg_data(uacp, streams_reg); 4326 4327 return (rval); 4328 } 4329 } 4330 4331 4332 /* 4333 * setup plumbed and stream info structure 4334 */ 4335 static int 4336 usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx) 4337 { 4338 uacp->usb_ac_plumbed[plb_idx].acp_data = 4339 &uacp->usb_ac_streams[str_idx]; 4340 uacp->usb_ac_streams[str_idx].acs_plumbed = 4341 &uacp->usb_ac_plumbed[plb_idx]; 4342 uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1; 4343 4344 4345 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4346 "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ", 4347 plb_idx, str_idx); 4348 4349 return (USB_SUCCESS); 4350 } 4351 4352 4353 /* 4354 * function to dump registration data 4355 */ 4356 static void 4357 usb_ac_print_reg_data(usb_ac_state_t *uacp, 4358 usb_as_registration_t *reg) 4359 { 4360 int n; 4361 4362 for (n = 0; n < reg->reg_n_formats; n++) { 4363 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4364 "format%d: alt=%d chns=%d prec=%d enc=%d", n, 4365 reg->reg_formats[n].fmt_alt, 4366 reg->reg_formats[n].fmt_chns, 4367 reg->reg_formats[n].fmt_precision, 4368 reg->reg_formats[n].fmt_encoding); 4369 } 4370 4371 for (n = 0; n < USB_AS_N_FORMATS; n++) { 4372 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4373 "reg_formats[%d] ptr=0x%p", n, 4374 (void *)®->reg_formats[n]); 4375 } 4376 4377 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4378 "usb_ac_print_reg_data: End"); 4379 } 4380 4381 4382 static int 4383 usb_ac_online_siblings(usb_ac_state_t *uacp) 4384 { 4385 dev_info_t *pdip, *child_dip; 4386 int rval = USB_SUCCESS; 4387 4388 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 4389 4390 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4391 "usb_ac_online_siblings:start"); 4392 4393 pdip = ddi_get_parent(uacp->usb_ac_dip); 4394 4395 child_dip = ddi_get_child(pdip); 4396 while (child_dip != NULL) { 4397 4398 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4399 "usb_ac_online_siblings: onlining %s%d ref=%d", 4400 ddi_driver_name(child_dip), 4401 ddi_get_instance(child_dip), 4402 DEVI(child_dip)->devi_ref); 4403 4404 /* Online the child_dip of usb_as and hid, if not already */ 4405 if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) || 4406 (strcmp(ddi_driver_name(child_dip), "hid") == 0)) { 4407 4408 mutex_exit(&uacp->usb_ac_mutex); 4409 if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) != 4410 NDI_SUCCESS) { 4411 USB_DPRINTF_L3(PRINT_MASK_ALL, 4412 uacp->usb_ac_log_handle, 4413 "usb_ac_online_siblings:failed to online" 4414 "device %s%d", ddi_driver_name(child_dip), 4415 ddi_get_instance(child_dip)); 4416 4417 /* only onlining usb_as is fatal */ 4418 if (strcmp(ddi_driver_name(child_dip), 4419 "usb_as") == 0) { 4420 mutex_enter(&uacp->usb_ac_mutex); 4421 rval = USB_FAILURE; 4422 break; 4423 } 4424 } 4425 mutex_enter(&uacp->usb_ac_mutex); 4426 } 4427 child_dip = ddi_get_next_sibling(child_dip); 4428 } 4429 4430 return (rval); 4431 } 4432 4433 4434 /* 4435 * hold all audio children before or after plumbing 4436 * online usb_as and hid, if not already 4437 */ 4438 static void 4439 usb_ac_hold_siblings(usb_ac_state_t *uacp) 4440 { 4441 int circ; 4442 dev_info_t *pdip, *child_dip; 4443 4444 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4445 "usb_ac_hold_siblings:start"); 4446 4447 /* hold all siblings and ourselves */ 4448 pdip = ddi_get_parent(uacp->usb_ac_dip); 4449 4450 /* hold the children */ 4451 ndi_devi_enter(pdip, &circ); 4452 child_dip = ddi_get_child(pdip); 4453 while (child_dip != NULL) { 4454 ndi_hold_devi(child_dip); 4455 4456 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4457 "usb_ac_hold_siblings: held %s%d ref=%d", 4458 ddi_driver_name(child_dip), ddi_get_instance(child_dip), 4459 DEVI(child_dip)->devi_ref); 4460 4461 child_dip = ddi_get_next_sibling(child_dip); 4462 } 4463 ndi_devi_exit(pdip, circ); 4464 } 4465 4466 4467 /* 4468 * release all audio children before or after plumbing 4469 */ 4470 static void 4471 usb_ac_rele_siblings(usb_ac_state_t *uacp) 4472 { 4473 int circ; 4474 dev_info_t *pdip, *child_dip; 4475 4476 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4477 "usb_ac_rele_siblings: start"); 4478 4479 /* release all siblings and ourselves */ 4480 pdip = ddi_get_parent(uacp->usb_ac_dip); 4481 ndi_devi_enter(pdip, &circ); 4482 child_dip = ddi_get_child(pdip); 4483 while (child_dip != NULL) { 4484 ndi_rele_devi(child_dip); 4485 4486 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4487 "usb_ac_rele_siblings: released %s%d ref=%d", 4488 ddi_driver_name(child_dip), ddi_get_instance(child_dip), 4489 DEVI(child_dip)->devi_ref); 4490 4491 child_dip = ddi_get_next_sibling(child_dip); 4492 } 4493 ndi_devi_exit(pdip, circ); 4494 } 4495 static void 4496 usb_restore_engine(usb_ac_state_t *statep) 4497 { 4498 usb_audio_eng_t *engp; 4499 int i; 4500 4501 for (i = 0; i < USB_AC_ENG_MAX; i++) { 4502 4503 mutex_enter(&statep->usb_ac_mutex); 4504 engp = &statep->engines[i]; 4505 mutex_exit(&statep->usb_ac_mutex); 4506 4507 if (engp->af_engp == NULL) 4508 continue; 4509 if (usb_ac_set_format(statep, engp) != USB_SUCCESS) { 4510 USB_DPRINTF_L2(PRINT_MASK_ATTA, 4511 statep->usb_ac_log_handle, 4512 "usb_restore_engine:set format fail, i=%d", i); 4513 return; 4514 } 4515 if (engp->started) { 4516 (void) usb_engine_start(engp); 4517 } 4518 4519 } 4520 4521 (void) usb_ac_ctrl_restore(statep); 4522 } 4523 4524 4525 /* 4526 * get the maximum format specification the device supports 4527 */ 4528 static void 4529 usb_ac_max_fmt(usb_as_registration_t *reg_data, 4530 usb_audio_format_t *fmtp) 4531 { 4532 4533 uint_t ch = 0, sr = 0, prec = 0, enc = 0; 4534 int i; 4535 4536 usb_audio_formats_t *reg_formats = reg_data->reg_formats; 4537 4538 /* format priority: channels, sample rate, precision, encoding */ 4539 for (i = 0; i < reg_data->reg_n_formats; i++) { 4540 uint_t val, fmt_sr; 4541 int n, keep; 4542 4543 val = reg_formats[i].fmt_chns; 4544 if (val < ch) 4545 continue; 4546 if (val > ch) 4547 keep = 1; 4548 4549 for (n = 0, fmt_sr = 0; n < reg_formats[i].fmt_n_srs; n++) { 4550 if (fmt_sr < reg_formats[i].fmt_srs[n]) { 4551 fmt_sr = reg_formats[i].fmt_srs[n]; 4552 } 4553 } 4554 if (!keep && fmt_sr < sr) 4555 continue; 4556 if (fmt_sr > sr) 4557 keep = 1; 4558 4559 val = reg_formats[i].fmt_precision; 4560 if (!keep && (val < prec)) 4561 continue; 4562 if (val > prec) 4563 keep = 1; 4564 4565 val = reg_formats[i].fmt_encoding; 4566 if (!keep && (val < enc)) 4567 continue; 4568 4569 ch = reg_formats[i].fmt_chns; 4570 sr = fmt_sr; 4571 prec = reg_formats[i].fmt_precision; 4572 enc = reg_formats[i].fmt_encoding; 4573 } 4574 4575 fmtp->ch = ch; 4576 fmtp->sr = sr; 4577 fmtp->prec = prec; 4578 fmtp->enc = enc; 4579 } 4580 4581 4582 static void 4583 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp) 4584 { 4585 if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL) 4586 return; 4587 4588 audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp); 4589 audio_engine_free(engp->af_engp); 4590 4591 mutex_enter(&engp->lock); 4592 engp->af_engp = NULL; 4593 engp->streams = NULL; 4594 mutex_exit(&engp->lock); 4595 4596 mutex_destroy(&engp->lock); 4597 cv_destroy(&engp->usb_audio_cv); 4598 } 4599 4600 4601 static int 4602 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t *asinfo) 4603 { 4604 audio_dev_t *af_devp = uacp->usb_ac_audio_dev; 4605 usb_audio_eng_t *engp; 4606 audio_engine_t *af_engp; 4607 int rv = USB_FAILURE; 4608 int dir = asinfo->acs_streams_reg.reg_mode; 4609 uint_t defgain; 4610 4611 if (asinfo->acs_rcvd_reg_data == 0) { 4612 4613 return (USB_SUCCESS); 4614 } 4615 if (dir == USB_AUDIO_PLAY) { 4616 engp = &(uacp->engines[0]); 4617 } else { 4618 engp = &(uacp->engines[1]); 4619 } 4620 4621 cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL); 4622 4623 mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL); 4624 4625 mutex_enter(&engp->lock); 4626 4627 engp->af_eflags = 4628 (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP; 4629 engp->statep = uacp; 4630 4631 /* Set the format for the engine */ 4632 usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt); 4633 4634 /* init the default gain */ 4635 defgain = asinfo->acs_default_gain; 4636 if (engp->fmt.ch == 2) { 4637 engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain); 4638 } else { 4639 engp->af_defgain = defgain; 4640 } 4641 engp->streams = asinfo; 4642 4643 mutex_exit(&engp->lock); 4644 4645 af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags); 4646 if (af_engp == NULL) { 4647 4648 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 4649 "audio_engine_alloc failed"); 4650 goto OUT; 4651 } 4652 ASSERT(engp->af_engp == 0); 4653 4654 mutex_enter(&engp->lock); 4655 engp->af_engp = af_engp; 4656 mutex_exit(&engp->lock); 4657 4658 audio_engine_set_private(af_engp, engp); 4659 audio_dev_add_engine(af_devp, af_engp); 4660 4661 /* 4662 * Set the format for this engine 4663 */ 4664 if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) { 4665 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 4666 "set format failed, dir = %d", dir); 4667 goto OUT; 4668 } 4669 rv = USB_SUCCESS; 4670 4671 OUT: 4672 if (rv != USB_SUCCESS) 4673 usb_ac_rem_eng(uacp, engp); 4674 4675 return (rv); 4676 } 4677 4678 4679 static int 4680 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep) 4681 { 4682 usb_audio_ctrl_t *ctrlp; 4683 int rv = USB_SUCCESS; 4684 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 4685 "usb_ac_ctrl_set_defaults:begin"); 4686 4687 for (int i = 0; i < CTL_NUM; i++) { 4688 ctrlp = statep->controls[i]; 4689 if (!ctrlp) { 4690 continue; 4691 } 4692 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) { 4693 USB_DPRINTF_L2(PRINT_MASK_ATTA, 4694 statep->usb_ac_log_handle, 4695 "usb_ac_ctrl_set_defaults:control write failed"); 4696 rv = USB_FAILURE; 4697 } 4698 4699 } 4700 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 4701 "usb_ac_ctrl_set_defaults:end"); 4702 return (rv); 4703 } 4704 4705 4706 static int 4707 usb_ac_ctrl_restore(usb_ac_state_t *statep) 4708 { 4709 usb_audio_ctrl_t *ctrlp; 4710 int rv = USB_SUCCESS; 4711 4712 for (int i = 0; i < CTL_NUM; i++) { 4713 ctrlp = statep->controls[i]; 4714 if (ctrlp) { 4715 USB_DPRINTF_L3(PRINT_MASK_ATTA, 4716 statep->usb_ac_log_handle, 4717 "usb_ac_ctrl_restore:i = %d", i); 4718 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) { 4719 rv = USB_FAILURE; 4720 } 4721 } 4722 } 4723 return (rv); 4724 } 4725 4726 4727 4728 4729 /* 4730 * moves data between driver buffer and framework/shim buffer 4731 */ 4732 static void 4733 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz) 4734 { 4735 size_t cpsz = sz; 4736 caddr_t *src, *dst; 4737 4738 if (engp->af_eflags & ENGINE_OUTPUT_CAP) { 4739 src = &engp->bufpos; 4740 dst = (caddr_t *)&buf; 4741 } else { 4742 src = (caddr_t *)&buf; 4743 dst = &engp->bufpos; 4744 } 4745 4746 /* 4747 * Wrap. If sz is exactly the remainder of the buffer 4748 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so 4749 * the second memcpy() should have no effect, with bufpos updated 4750 * to the head of the buffer. 4751 */ 4752 if (engp->bufpos + sz >= engp->bufendp) { 4753 cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos; 4754 (void) memcpy(*dst, *src, cpsz); 4755 4756 4757 buf = (caddr_t)buf + cpsz; 4758 engp->bufpos = engp->bufp; 4759 cpsz = sz - cpsz; 4760 } 4761 4762 if (cpsz) { 4763 (void) memcpy(*dst, *src, cpsz); 4764 4765 4766 engp->bufpos += cpsz; 4767 } 4768 engp->bufio_count++; 4769 } 4770 4771 4772 /* 4773 * control read callback 4774 */ 4775 static int 4776 usb_audio_ctrl_read(void *arg, uint64_t *cvalp) 4777 { 4778 usb_audio_ctrl_t *ctrlp = arg; 4779 4780 mutex_enter(&ctrlp->ctrl_mutex); 4781 *cvalp = ctrlp->cval; 4782 mutex_exit(&ctrlp->ctrl_mutex); 4783 4784 return (0); 4785 } 4786 4787 4788 /* 4789 * stereo level control callback 4790 */ 4791 static int 4792 usb_audio_write_stero_rec(void *arg, uint64_t cval) 4793 { 4794 usb_audio_ctrl_t *ctrlp = arg; 4795 usb_ac_state_t *statep = ctrlp->statep; 4796 int rv = EIO; 4797 int left, right; 4798 uint_t count = 0; 4799 4800 4801 left = AUDIO_CTRL_STEREO_LEFT(cval); 4802 right = AUDIO_CTRL_STEREO_RIGHT(cval); 4803 4804 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN || 4805 right < AF_MIN_GAIN || right > AF_MAX_GAIN) { 4806 4807 return (EINVAL); 4808 } 4809 4810 mutex_enter(&ctrlp->ctrl_mutex); 4811 ctrlp->cval = cval; 4812 mutex_exit(&ctrlp->ctrl_mutex); 4813 4814 mutex_enter(&statep->usb_ac_mutex); 4815 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD, 4816 USB_AUDIO_FEATURE_UNIT, 1, 4817 USB_AUDIO_VOLUME_CONTROL, 4818 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain); 4819 4820 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD, 4821 USB_AUDIO_FEATURE_UNIT, 2, 4822 USB_AUDIO_VOLUME_CONTROL, 4823 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain); 4824 rv = 0; 4825 4826 done: 4827 mutex_exit(&statep->usb_ac_mutex); 4828 return (rv); 4829 } 4830 4831 static int 4832 usb_audio_write_ster_vol(void *arg, uint64_t cval) 4833 { 4834 usb_audio_ctrl_t *ctrlp = arg; 4835 usb_ac_state_t *statep = ctrlp->statep; 4836 int rv = EIO; 4837 int left, right; 4838 uint_t count = 0; 4839 4840 left = AUDIO_CTRL_STEREO_LEFT(cval); 4841 right = AUDIO_CTRL_STEREO_RIGHT(cval); 4842 4843 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN || 4844 right < AF_MIN_GAIN || right > AF_MAX_GAIN) { 4845 return (EINVAL); 4846 } 4847 4848 mutex_enter(&ctrlp->ctrl_mutex); 4849 ctrlp->cval = cval; 4850 mutex_exit(&ctrlp->ctrl_mutex); 4851 4852 4853 mutex_enter(&statep->usb_ac_mutex); 4854 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 4855 USB_AUDIO_FEATURE_UNIT, 1, 4856 USB_AUDIO_VOLUME_CONTROL, 4857 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain); 4858 4859 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 4860 USB_AUDIO_FEATURE_UNIT, 2, 4861 USB_AUDIO_VOLUME_CONTROL, 4862 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain); 4863 rv = 0; 4864 4865 OUT: 4866 mutex_exit(&statep->usb_ac_mutex); 4867 return (rv); 4868 } 4869 4870 4871 /* 4872 * mono level control callback 4873 */ 4874 static int 4875 usb_audio_write_mono_vol(void *arg, uint64_t cval) 4876 { 4877 usb_audio_ctrl_t *ctrlp = arg; 4878 usb_ac_state_t *statep = ctrlp->statep; 4879 int rv = EIO; 4880 int gain; 4881 4882 uint_t count = 0; 4883 4884 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) { 4885 return (EINVAL); 4886 } 4887 4888 mutex_enter(&ctrlp->ctrl_mutex); 4889 ctrlp->cval = cval; 4890 mutex_exit(&ctrlp->ctrl_mutex); 4891 4892 gain = (int)(cval); 4893 4894 mutex_enter(&statep->usb_ac_mutex); 4895 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 4896 USB_AUDIO_FEATURE_UNIT, 1, 4897 USB_AUDIO_VOLUME_CONTROL, 4898 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain); 4899 4900 rv = 0; 4901 OUT: 4902 mutex_exit(&statep->usb_ac_mutex); 4903 4904 return (rv); 4905 } 4906 4907 4908 /* 4909 * mono level control callback 4910 */ 4911 static int 4912 usb_audio_write_monitor_gain(void *arg, uint64_t cval) 4913 { 4914 usb_audio_ctrl_t *ctrlp = arg; 4915 usb_ac_state_t *statep = ctrlp->statep; 4916 int rv = EIO; 4917 int gain; 4918 uint_t count = 0; 4919 4920 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) { 4921 4922 return (EINVAL); 4923 } 4924 4925 mutex_enter(&ctrlp->ctrl_mutex); 4926 ctrlp->cval = cval; 4927 mutex_exit(&ctrlp->ctrl_mutex); 4928 4929 gain = (int)(cval); 4930 4931 mutex_enter(&statep->usb_ac_mutex); 4932 (void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD, 4933 USB_AUDIO_INPUT_TERMINAL, 1, 4934 USB_AUDIO_VOLUME_CONTROL, 4935 USB_AC_FIND_ALL, &count, gain, 4936 usb_ac_set_monitor_gain); 4937 4938 rv = 0; 4939 OUT: 4940 mutex_exit(&statep->usb_ac_mutex); 4941 return (rv); 4942 } 4943 4944 static int 4945 usb_audio_write_mono_rec(void *arg, uint64_t cval) 4946 { 4947 usb_audio_ctrl_t *ctrlp = arg; 4948 usb_ac_state_t *statep = ctrlp->statep; 4949 int rv = EIO; 4950 int gain; 4951 4952 uint_t count = 0; 4953 4954 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) { 4955 4956 return (EINVAL); 4957 } 4958 4959 mutex_enter(&ctrlp->ctrl_mutex); 4960 ctrlp->cval = cval; 4961 mutex_exit(&ctrlp->ctrl_mutex); 4962 4963 gain = (int)(cval); 4964 4965 mutex_enter(&statep->usb_ac_mutex); 4966 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD, 4967 USB_AUDIO_FEATURE_UNIT, 1, 4968 USB_AUDIO_VOLUME_CONTROL, 4969 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain); 4970 4971 rv = 0; 4972 4973 mutex_exit(&statep->usb_ac_mutex); 4974 return (rv); 4975 } 4976 4977 static int 4978 usb_audio_write_mic_boost(void *arg, uint64_t cval) 4979 { 4980 usb_audio_ctrl_t *ctrlp = arg; 4981 4982 mutex_enter(&ctrlp->ctrl_mutex); 4983 ctrlp->cval = cval; 4984 mutex_exit(&ctrlp->ctrl_mutex); 4985 /* do nothing here */ 4986 return (0); 4987 } 4988 4989 static int 4990 usb_audio_write_rec_src(void *arg, uint64_t cval) 4991 { 4992 usb_audio_ctrl_t *ctrlp = arg; 4993 usb_ac_state_t *statep = ctrlp->statep; 4994 int rv = 0; 4995 4996 if (cval & ~(statep->usb_ac_input_ports)) 4997 return (EINVAL); 4998 4999 mutex_enter(&ctrlp->ctrl_mutex); 5000 ctrlp->cval = cval; 5001 mutex_exit(&ctrlp->ctrl_mutex); 5002 5003 mutex_enter(&statep->usb_ac_mutex); 5004 if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) { 5005 5006 USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle, 5007 "usb_audio_write_rec_src: failed"); 5008 rv = EINVAL; 5009 } 5010 mutex_exit(&statep->usb_ac_mutex); 5011 rv = 0; 5012 5013 OUT: 5014 return (rv); 5015 5016 } 5017 5018 5019 int 5020 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval) 5021 { 5022 short muteval; 5023 int rval; 5024 5025 uint_t count; 5026 muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF; 5027 count = 0; 5028 /* only support AUDIO_PLAY */ 5029 5030 mutex_enter(&statep->usb_ac_mutex); 5031 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY, 5032 USB_AUDIO_FEATURE_UNIT, 0, 5033 USB_AUDIO_MUTE_CONTROL, 5034 USB_AC_FIND_ALL, &count, muteval, 5035 usb_ac_set_mute); 5036 mutex_exit(&statep->usb_ac_mutex); 5037 5038 rval = (count == 0) ? USB_SUCCESS : USB_FAILURE; 5039 5040 return (rval); 5041 } 5042 5043 5044 /* 5045 * port selection control callback 5046 */ 5047 /* 5048 * audio control registration related routines 5049 */ 5050 5051 static usb_audio_ctrl_t * 5052 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val) 5053 { 5054 audio_ctrl_desc_t desc; 5055 audio_ctrl_wr_t fn; 5056 usb_audio_ctrl_t *pc; 5057 5058 pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP); 5059 5060 mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL); 5061 5062 bzero(&desc, sizeof (desc)); 5063 5064 switch (num) { 5065 case CTL_VOLUME_MONO: 5066 desc.acd_name = AUDIO_CTRL_ID_VOLUME; 5067 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 5068 desc.acd_minvalue = 0; 5069 desc.acd_maxvalue = AF_MAX_GAIN; 5070 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW 5071 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL; 5072 fn = usb_audio_write_mono_vol; 5073 break; 5074 5075 case CTL_VOLUME_STERO: 5076 desc.acd_name = AUDIO_CTRL_ID_VOLUME; 5077 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 5078 desc.acd_minvalue = 0; 5079 desc.acd_maxvalue = AF_MAX_GAIN; 5080 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW 5081 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL; 5082 fn = usb_audio_write_ster_vol; 5083 5084 break; 5085 5086 case CTL_REC_MONO: 5087 desc.acd_name = AUDIO_CTRL_ID_RECGAIN; 5088 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 5089 desc.acd_minvalue = 0; 5090 desc.acd_maxvalue = AF_MAX_GAIN; 5091 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC 5092 | AUDIO_CTRL_FLAG_RW; 5093 fn = usb_audio_write_mono_rec; 5094 break; 5095 case CTL_REC_STERO: 5096 5097 desc.acd_name = AUDIO_CTRL_ID_RECGAIN; 5098 desc.acd_type = AUDIO_CTRL_TYPE_STEREO; 5099 desc.acd_minvalue = 0; 5100 desc.acd_maxvalue = AF_MAX_GAIN; 5101 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC 5102 | AUDIO_CTRL_FLAG_RW; 5103 fn = usb_audio_write_stero_rec; 5104 break; 5105 5106 case CTL_MONITOR_GAIN: 5107 5108 desc.acd_name = AUDIO_CTRL_ID_MONGAIN; 5109 desc.acd_type = AUDIO_CTRL_TYPE_MONO; 5110 desc.acd_minvalue = 0; 5111 desc.acd_maxvalue = AF_MAX_GAIN; 5112 desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR 5113 |AUDIO_CTRL_FLAG_RW; 5114 fn = usb_audio_write_monitor_gain; 5115 break; 5116 5117 case CTL_MIC_BOOST: 5118 5119 desc.acd_name = AUDIO_CTRL_ID_MICBOOST; 5120 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN; 5121 desc.acd_minvalue = 0; 5122 desc.acd_maxvalue = 1; 5123 desc.acd_flags = AUDIO_CTRL_FLAG_RW; 5124 fn = usb_audio_write_mic_boost; 5125 break; 5126 case CTL_REC_SRC: 5127 5128 desc.acd_name = AUDIO_CTRL_ID_RECSRC; 5129 desc.acd_type = AUDIO_CTRL_TYPE_ENUM; 5130 desc.acd_minvalue = statep->usb_ac_input_ports; 5131 desc.acd_maxvalue = statep->usb_ac_input_ports; 5132 desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC; 5133 for (int i = 0; usb_audio_dtypes[i]; i++) { 5134 desc.acd_enum[i] = usb_audio_dtypes[i]; 5135 } 5136 5137 fn = usb_audio_write_rec_src; 5138 break; 5139 5140 5141 5142 default: 5143 5144 break; 5145 } 5146 5147 mutex_enter(&pc->ctrl_mutex); 5148 5149 pc->statep = statep; 5150 pc->cval = val; 5151 pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc, 5152 usb_audio_ctrl_read, fn, pc); 5153 5154 mutex_exit(&pc->ctrl_mutex); 5155 5156 mutex_enter(&statep->usb_ac_mutex); 5157 statep->controls[num] = pc; 5158 mutex_exit(&statep->usb_ac_mutex); 5159 5160 5161 return (pc); 5162 } 5163 5164 5165 static void 5166 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp) 5167 { 5168 kmem_free(ctrlp, sizeof (usb_audio_ctrl_t)); 5169 } 5170 5171 static void 5172 usb_ac_rem_controls(usb_ac_state_t *statep) 5173 { 5174 usb_audio_ctrl_t *ctrlp; 5175 5176 for (int i = 0; i < CTL_NUM; i++) { 5177 ctrlp = statep->controls[i]; 5178 if (ctrlp) { 5179 if (ctrlp->af_ctrlp != NULL) 5180 audio_dev_del_control(ctrlp->af_ctrlp); 5181 5182 usb_audio_ctrl_free(ctrlp); 5183 mutex_enter(&statep->usb_ac_mutex); 5184 statep->controls[i] = NULL; 5185 mutex_exit(&statep->usb_ac_mutex); 5186 } 5187 } 5188 5189 } 5190 5191 5192 static int 5193 usb_ac_add_controls(usb_ac_state_t *statep) 5194 { 5195 int rv = USB_FAILURE; 5196 usb_audio_format_t *format; 5197 5198 5199 if (statep->engines[0].af_engp) { 5200 /* Init controls for play format */ 5201 format = &(statep->engines[0].fmt); 5202 if (format->ch == 2) { 5203 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO, 5204 statep->engines[0].af_defgain); 5205 } else { 5206 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO, 5207 statep->engines[0].af_defgain); 5208 } 5209 5210 } 5211 5212 /* Init controls for rec format */ 5213 if (statep->engines[1].af_engp) { 5214 format = &(statep->engines[1].fmt); 5215 if (format->ch == 2) { 5216 (void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO, 5217 statep->engines[1].af_defgain); 5218 } else { 5219 (void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO, 5220 statep->engines[1].af_defgain); 5221 } 5222 5223 /* Add monitor control */ 5224 { 5225 (void) usb_audio_ctrl_alloc(statep, 5226 CTL_MONITOR_GAIN, 0); 5227 } 5228 5229 /* Add ports control */ 5230 { 5231 (void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC, 5232 statep->usb_ac_input_ports); 5233 } 5234 5235 } 5236 5237 5238 rv = USB_SUCCESS; 5239 5240 OUT: 5241 if (rv != USB_SUCCESS) 5242 usb_ac_rem_controls(statep); 5243 return (rv); 5244 } 5245 5246 5247 5248 5249 5250 /*ARGSUSED*/ 5251 static int 5252 usb_audio_unregister(usb_ac_state_t *statep) 5253 { 5254 int i; 5255 5256 if (statep == NULL) 5257 return (USB_SUCCESS); 5258 5259 if (statep->usb_ac_audio_dev == NULL) 5260 return (USB_SUCCESS); 5261 5262 if ((statep->flags & AF_REGISTERED) && 5263 audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) { 5264 return (USB_FAILURE); 5265 } 5266 mutex_enter(&statep->usb_ac_mutex); 5267 statep->flags &= ~AF_REGISTERED; 5268 mutex_exit(&statep->usb_ac_mutex); 5269 5270 for (i = 0; i < USB_AC_ENG_MAX; i++) 5271 usb_ac_rem_eng(statep, &statep->engines[i]); 5272 5273 usb_ac_rem_controls(statep); 5274 5275 audio_dev_free(statep->usb_ac_audio_dev); 5276 5277 mutex_enter(&statep->usb_ac_mutex); 5278 statep->usb_ac_audio_dev = NULL; 5279 mutex_exit(&statep->usb_ac_mutex); 5280 5281 return (USB_SUCCESS); 5282 } 5283 5284 5285 static int 5286 usb_audio_register(usb_ac_state_t *statep) { 5287 audio_dev_t *af_devp; 5288 int rv = USB_FAILURE; 5289 int n; 5290 5291 af_devp = audio_dev_alloc(statep->usb_ac_dip, 0); 5292 audio_dev_set_description(af_devp, "USB Audio"); 5293 audio_dev_set_version(af_devp, "1.0"); 5294 5295 mutex_enter(&statep->usb_ac_mutex); 5296 statep->usb_ac_audio_dev = af_devp; 5297 mutex_exit(&statep->usb_ac_mutex); 5298 5299 5300 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) { 5301 if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n])) 5302 != USB_SUCCESS) { 5303 USB_DPRINTF_L2(PRINT_MASK_ATTA, 5304 statep->usb_ac_log_handle, 5305 "usb_audio_register: add engine n =%d failed", n); 5306 goto OUT; 5307 } 5308 } 5309 5310 5311 if (usb_ac_add_controls(statep) != USB_SUCCESS) { 5312 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5313 "usb_audio_register: add controls failed"); 5314 goto OUT; 5315 } 5316 5317 if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) { 5318 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5319 "usb_audio_register: set defaults failed"); 5320 goto OUT; 5321 } 5322 5323 if (audio_dev_register(af_devp) != DDI_SUCCESS) { 5324 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5325 "audio_dev_register() failed"); 5326 goto OUT; 5327 } 5328 mutex_enter(&statep->usb_ac_mutex); 5329 statep->flags |= AF_REGISTERED; 5330 mutex_exit(&statep->usb_ac_mutex); 5331 5332 rv = USB_SUCCESS; 5333 5334 OUT: 5335 if (rv != USB_SUCCESS) { 5336 (void) usb_audio_unregister(statep); 5337 } 5338 return (rv); 5339 } 5340 5341 5342 int 5343 usb_ac_get_audio(void *handle, void *buf, int samples) 5344 { 5345 usb_ac_state_t *statep = (usb_ac_state_t *)(handle); 5346 usb_audio_eng_t *engp = &(statep->engines[0]); 5347 unsigned reqframes = samples >> engp->frsmshift; 5348 unsigned frames; 5349 unsigned i; 5350 size_t sz; 5351 caddr_t bp = buf; 5352 5353 mutex_enter(&engp->lock); 5354 if (!engp->started) { 5355 mutex_exit(&engp->lock); 5356 5357 return (0); 5358 } 5359 engp->busy = B_TRUE; 5360 mutex_exit(&engp->lock); 5361 5362 /* break requests from the driver into fragment sized chunks */ 5363 for (i = 0; i < reqframes; i += frames) { 5364 5365 mutex_enter(&engp->lock); 5366 frames = reqframes - i; 5367 if (frames > engp->fragfr) 5368 frames = engp->fragfr; 5369 5370 sz = (frames << engp->frsmshift) << engp->smszshift; 5371 5372 /* must move data before updating framework */ 5373 usb_eng_bufio(engp, bp, sz); 5374 engp->frames += frames; 5375 bp += sz; 5376 5377 mutex_exit(&engp->lock); 5378 } 5379 5380 mutex_enter(&engp->lock); 5381 engp->io_count++; 5382 engp->busy = B_FALSE; 5383 cv_signal(&engp->usb_audio_cv); 5384 mutex_exit(&engp->lock); 5385 5386 return (samples); 5387 } 5388 5389 5390 5391 void 5392 usb_ac_send_audio(void *handle, void *buf, int samples) 5393 { 5394 usb_ac_state_t *statep = (usb_ac_state_t *)(handle); 5395 usb_audio_eng_t *engp = &(statep->engines[1]); 5396 unsigned reqframes = samples >> engp->frsmshift; 5397 unsigned frames; 5398 unsigned i; 5399 size_t sz; 5400 caddr_t bp = buf; 5401 5402 mutex_enter(&engp->lock); 5403 5404 if (!engp->started) { 5405 5406 mutex_exit(&engp->lock); 5407 return; 5408 } 5409 engp->busy = B_TRUE; 5410 mutex_exit(&engp->lock); 5411 5412 /* break requests from the driver into fragment sized chunks */ 5413 for (i = 0; i < reqframes; i += frames) { 5414 mutex_enter(&engp->lock); 5415 5416 frames = reqframes - i; 5417 if (frames > engp->fragfr) 5418 frames = engp->fragfr; 5419 5420 sz = (frames << engp->frsmshift) << engp->smszshift; 5421 5422 /* must move data before updating framework */ 5423 usb_eng_bufio(engp, bp, sz); 5424 engp->frames += frames; 5425 bp += sz; 5426 5427 mutex_exit(&engp->lock); 5428 } 5429 5430 mutex_enter(&engp->lock); 5431 engp->io_count++; 5432 engp->busy = B_FALSE; 5433 cv_signal(&engp->usb_audio_cv); 5434 mutex_exit(&engp->lock); 5435 } 5436 5437 5438 /* 5439 * ************************************************************************** 5440 * audio framework engine callbacks 5441 */ 5442 static int 5443 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp) 5444 { 5445 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5446 usb_ac_state_t *statep = engp->statep; 5447 int rv = EIO; 5448 5449 _NOTE(ARGUNUSED(flag)); 5450 5451 if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) { 5452 5453 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5454 "usb_ac_open() failed"); 5455 return (EIO); 5456 } 5457 5458 mutex_enter(&engp->lock); 5459 5460 engp->intrate = 150; 5461 engp->sampsz = engp->fmt.prec / 8; 5462 engp->framesz = engp->sampsz * engp->fmt.ch; 5463 5464 engp->frsmshift = engp->fmt.ch / 2; 5465 engp->smszshift = engp->sampsz / 2; 5466 5467 /* 5468 * In order to match the requested number of samples per interrupt 5469 * from SADA drivers when computing the fragment size, 5470 * we need to first truncate the floating point result from 5471 * sample rate * channels / intr rate 5472 * then adjust up to an even number, before multiplying it 5473 * with the sample size 5474 */ 5475 engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate; 5476 if (engp->fragsz & 1) 5477 engp->fragsz++; 5478 engp->fragsz *= engp->sampsz; 5479 engp->fragfr = engp->fragsz / engp->framesz; 5480 5481 engp->nfrags = 10; 5482 engp->bufsz = engp->fragsz * engp->nfrags; 5483 5484 engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP); 5485 engp->bufpos = engp->bufp; 5486 engp->bufendp = engp->bufp + engp->bufsz; 5487 engp->frames = 0; 5488 engp->io_count = 0; 5489 engp->bufio_count = 0; 5490 engp->started = B_FALSE; 5491 engp->busy = B_FALSE; 5492 5493 *nframesp = engp->nfrags * engp->fragfr; 5494 *bufp = engp->bufp; 5495 5496 mutex_exit(&engp->lock); 5497 5498 if (usb_ac_setup(statep, engp) != USB_SUCCESS) { 5499 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5500 "device setup failed"); 5501 goto OUT; 5502 } 5503 5504 5505 5506 mutex_enter(&statep->usb_ac_mutex); 5507 statep->flags |= AD_SETUP; 5508 mutex_exit(&statep->usb_ac_mutex); 5509 5510 rv = 0; 5511 5512 5513 OUT: 5514 if (rv != 0) 5515 usb_engine_close(arg); 5516 5517 return (rv); 5518 } 5519 5520 5521 static void 5522 usb_engine_close(void *arg) 5523 { 5524 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5525 usb_ac_state_t *statep = engp->statep; 5526 5527 mutex_enter(&engp->lock); 5528 while (engp->busy) { 5529 cv_wait(&engp->usb_audio_cv, &engp->lock); 5530 } 5531 5532 mutex_exit(&engp->lock); 5533 5534 if (statep->flags & AD_SETUP) { 5535 usb_ac_teardown(statep, engp); 5536 mutex_enter(&statep->usb_ac_mutex); 5537 statep->flags &= ~AD_SETUP; 5538 mutex_exit(&statep->usb_ac_mutex); 5539 } 5540 mutex_enter(&engp->lock); 5541 5542 if (engp->bufp != NULL) { 5543 kmem_free(engp->bufp, engp->bufsz); 5544 engp->bufp = NULL; 5545 engp->bufpos = NULL; 5546 engp->bufendp = NULL; 5547 } 5548 5549 mutex_exit(&engp->lock); 5550 5551 usb_ac_close(statep->usb_ac_dip); 5552 } 5553 5554 5555 5556 static int 5557 usb_engine_start(void *arg) 5558 { 5559 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5560 int rv = 0; 5561 int (*start)(usb_ac_state_t *, usb_audio_eng_t *); 5562 5563 mutex_enter(&engp->lock); 5564 engp->started = B_TRUE; 5565 mutex_exit(&engp->lock); 5566 5567 usb_ac_state_t *statep = engp->statep; 5568 5569 start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ? 5570 usb_ac_start_play : usb_ac_start_record; 5571 5572 if ((*start)(statep, engp) != USB_SUCCESS) { 5573 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5574 "failed to start %d engine", engp->af_eflags); 5575 rv = EIO; 5576 } 5577 5578 5579 return (rv); 5580 } 5581 5582 5583 static void 5584 usb_engine_stop(void *arg) 5585 { 5586 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5587 5588 mutex_enter(&engp->lock); 5589 engp->started = B_FALSE; 5590 mutex_exit(&engp->lock); 5591 5592 usb_ac_state_t *statep = engp->statep; 5593 void (*stop)(usb_ac_state_t *, usb_audio_eng_t *); 5594 5595 stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ? 5596 usb_ac_stop_play : usb_ac_stop_record; 5597 5598 (*stop)(statep, engp); 5599 } 5600 5601 5602 static uint64_t 5603 usb_engine_count(void *arg) 5604 { 5605 usb_audio_eng_t *engp = arg; 5606 uint64_t val; 5607 5608 mutex_enter(&engp->lock); 5609 val = engp->frames; 5610 mutex_exit(&engp->lock); 5611 5612 return (val); 5613 } 5614 5615 5616 static int 5617 usb_engine_format(void *arg) 5618 { 5619 usb_audio_eng_t *engp = arg; 5620 5621 switch (engp->fmt.enc) { 5622 case USB_AUDIO_FORMAT_TYPE1_MULAW: 5623 return (AUDIO_FORMAT_ULAW); 5624 case USB_AUDIO_FORMAT_TYPE1_ALAW: 5625 return (AUDIO_FORMAT_ALAW); 5626 case USB_AUDIO_FORMAT_TYPE1_PCM8: 5627 return (AUDIO_FORMAT_U8); 5628 5629 case USB_AUDIO_FORMAT_TYPE1_PCM: 5630 break; 5631 default: 5632 return (AUDIO_FORMAT_NONE); 5633 } 5634 5635 switch (engp->fmt.prec) { 5636 case USB_AUDIO_PRECISION_8: 5637 return (AUDIO_FORMAT_S8); 5638 case USB_AUDIO_PRECISION_16: 5639 return (AUDIO_FORMAT_S16_LE); 5640 case USB_AUDIO_PRECISION_24: 5641 return (AUDIO_FORMAT_S24_LE); 5642 case USB_AUDIO_PRECISION_32: 5643 return (AUDIO_FORMAT_S32_LE); 5644 default: 5645 break; 5646 } 5647 return (AUDIO_FORMAT_NONE); 5648 5649 5650 } 5651 5652 static int 5653 usb_engine_channels(void *arg) 5654 { 5655 usb_audio_eng_t *engp = arg; 5656 5657 return (engp->fmt.ch); 5658 } 5659 5660 5661 static int 5662 usb_engine_rate(void *arg) 5663 { 5664 usb_audio_eng_t *engp = arg; 5665 5666 return (engp->fmt.sr); 5667 } 5668 5669 5670 /*ARGSUSED*/ 5671 static void 5672 usb_engine_sync(void *arg, unsigned nframes) 5673 { 5674 /* Do nothing */ 5675 } 5676 5677 5678 static unsigned 5679 usb_engine_qlen(void *arg) 5680 { 5681 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg; 5682 5683 return (engp->fragfr); 5684 } 5685 5686 /* 5687 * ************************************************************************** 5688 * interfaces used by USB audio 5689 */ 5690 5691 /*ARGSUSED*/ 5692 static int 5693 usb_change_phy_vol(usb_ac_state_t *statep, int value) 5694 { 5695 usb_audio_ctrl_t *ctrlp; 5696 uint64_t cval = 0; 5697 int64_t left, right, delta = 0; 5698 5699 ctrlp = statep->controls[CTL_VOLUME_STERO]; 5700 5701 ASSERT(value != 0); 5702 5703 delta = (value < 0)?-1:1; 5704 5705 left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta; 5706 right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta; 5707 5708 if (left > AF_MAX_GAIN) 5709 left = AF_MAX_GAIN; 5710 if (right > AF_MAX_GAIN) 5711 right = AF_MAX_GAIN; 5712 5713 if (left < AF_MIN_GAIN) 5714 left = AF_MIN_GAIN; 5715 if (right < AF_MIN_GAIN) 5716 right = AF_MIN_GAIN; 5717 5718 cval = AUDIO_CTRL_STEREO_VAL(left, right); 5719 5720 if (audio_control_write(ctrlp->af_ctrlp, cval)) { 5721 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle, 5722 "updateing control to value 0x%llx by driver failed", 5723 (long long unsigned)cval); 5724 return (USB_FAILURE); 5725 } 5726 return (USB_SUCCESS); 5727 } 5728