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