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