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