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