1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #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", (void *)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", (void *)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 (void *)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", 982 (void *)q, uacp->usb_ac_busy_count); 983 984 mutex_exit(&uacp->usb_ac_mutex); 985 986 return (0); 987 } 988 989 990 /* 991 * usb_ac_close : 992 * Close entry point 993 */ 994 /*ARGSUSED*/ 995 static int 996 usb_ac_close(queue_t *q, int flag, cred_t *credp) 997 { 998 dev_t dev = audio_sup_get_qptr_dev(q); 999 int minor = getminor(dev); 1000 int instance = audio_sup_get_qptr_instance(q); 1001 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance); 1002 int rval; 1003 1004 mutex_enter(&uacp->usb_ac_mutex); 1005 1006 USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1007 "usb_ac_close: Begin q=0x%p, opencount=%d", 1008 (void *)q, uacp->usb_ac_busy_count); 1009 1010 /* closing the mux? */ 1011 if (minor == uacp->usb_ac_mux_minor) { 1012 USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1013 "usb_ac_close: closing mux plumbing stream"); 1014 mutex_exit(&uacp->usb_ac_mutex); 1015 1016 /* Wait till all activity in the default pipe has drained */ 1017 usb_ac_serialize_access(uacp); 1018 usb_ac_release_access(uacp); 1019 1020 audio_sup_free_qptr(q); 1021 qprocsoff(q); 1022 1023 return (0); 1024 } 1025 1026 mutex_exit(&uacp->usb_ac_mutex); 1027 1028 rval = audio_sup_close(q, flag, credp); 1029 1030 if (rval != 0) { 1031 USB_DPRINTF_L2(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1032 "audio_sup_close fails %d", rval); 1033 1034 return (rval); 1035 } 1036 1037 mutex_enter(&uacp->usb_ac_mutex); 1038 1039 /* normal streams closing */ 1040 ASSERT(uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED); 1041 1042 uacp->usb_ac_busy_count --; 1043 1044 USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1045 "usb_ac_close: End rval=%d q=0x%p, opencount=%d", 1046 rval, (void *)q, uacp->usb_ac_busy_count); 1047 1048 mutex_exit(&uacp->usb_ac_mutex); 1049 1050 usb_ac_pm_idle_component(uacp); 1051 1052 return (0); 1053 } 1054 1055 1056 /* 1057 * usb_ac_uwput: 1058 * write put entry point for the upper mux. Only PLUMB/UNPLUMB ioctls 1059 * are processed here. All other ioctls are passed to audio_sup routines 1060 * for further processing. 1061 */ 1062 static int 1063 usb_ac_uwput(queue_t *q, mblk_t *mp) 1064 { 1065 int instance = audio_sup_get_qptr_instance(q); 1066 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance); 1067 int error = DDI_SUCCESS; 1068 1069 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1070 "usb_ac_uwput: q=0x%p, mp=0x%p", (void *)q, (void *)mp); 1071 1072 ASSERT(mp != NULL); 1073 ASSERT(mp->b_datap != NULL); 1074 1075 mutex_enter(&uacp->usb_ac_mutex); 1076 if (uacp->usb_ac_wq == q) { 1077 ASSERT(mp->b_datap->db_type == M_IOCTL); 1078 1079 mutex_exit(&uacp->usb_ac_mutex); 1080 1081 /* ioctl from plumbing thread (namely P_LINK) */ 1082 usb_ac_plumb_ioctl(q, mp); 1083 1084 return (error); 1085 } 1086 mutex_exit(&uacp->usb_ac_mutex); 1087 1088 /* Pass to audio_sup routine */ 1089 (void) audio_sup_wput(q, mp); 1090 1091 return (error); 1092 } 1093 1094 1095 /* 1096 * usb_ac_lrput: 1097 * read put entry point for the lower mux. Get the response from the 1098 * lower module, signal usb_ac_send_as_cmd(), the thread that is waiting 1099 * for a response to a message sent earlier anbd pass the response 1100 * message block. 1101 */ 1102 static int 1103 usb_ac_lrput(queue_t *q, mblk_t *mp) 1104 { 1105 int instance = audio_sup_get_qptr_instance(q); 1106 usb_ac_state_t *uacp; 1107 int error = DDI_SUCCESS; 1108 usb_ac_plumbed_t *plumb_infop; 1109 usb_ac_streams_info_t *streams_infop = NULL; 1110 int val; 1111 char val1; 1112 struct iocblk *iocp; 1113 1114 uacp = ddi_get_soft_state(usb_ac_statep, instance); 1115 1116 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1117 "usb_ac_lrput: q=0x%p, mp=0x%p, instance=%d", 1118 (void *)q, (void *)mp, instance); 1119 ASSERT(mp != NULL); 1120 1121 mutex_enter(&uacp->usb_ac_mutex); 1122 plumb_infop = usb_ac_get_plumb_info_from_lrq(uacp, q); 1123 ASSERT(plumb_infop != NULL); 1124 1125 switch (mp->b_datap->db_type) { 1126 case M_CTL: 1127 case M_ERROR: 1128 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1129 "M_CTL/M_ERROR"); 1130 1131 switch (plumb_infop->acp_driver) { 1132 case USB_AS_PLUMBED: 1133 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1134 "reply from usb_as, lrq=0x%p", (void *)q); 1135 streams_infop = (usb_ac_streams_info_t *) 1136 plumb_infop->acp_data; 1137 ASSERT(streams_infop != NULL); 1138 streams_infop->acs_ac_to_as_req.acr_reply_mp = mp; 1139 streams_infop->acs_ac_to_as_req.acr_wait_flag = 0; 1140 cv_signal(&streams_infop->acs_ac_to_as_req.acr_cv); 1141 1142 break; 1143 case USB_AH_PLUMBED: 1144 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1145 "M_CTL from hid, lrq=0x%p", (void *)q); 1146 1147 iocp = (struct iocblk *)mp->b_rptr; 1148 ASSERT(mp->b_cont != NULL); 1149 1150 if (uacp->usb_ac_registered_with_mixer) { 1151 1152 val1 = *((char *)mp->b_cont->b_rptr); 1153 val = (int)val1; 1154 1155 USB_DPRINTF_L4(PRINT_MASK_ALL, 1156 uacp->usb_ac_log_handle, "val1=0x%x(%d)," 1157 "val=0x%x(%d)", val1, val1, val, val); 1158 1159 switch (iocp->ioc_cmd) { 1160 /* Handle relative volume change */ 1161 case USB_AUDIO_VOL_CHANGE: 1162 /* prevent unplumbing */ 1163 uacp->usb_ac_busy_count++; 1164 if (uacp->usb_ac_plumbing_state == 1165 USB_AC_STATE_PLUMBED) { 1166 mutex_exit(&uacp->usb_ac_mutex); 1167 (void) am_hw_state_change( 1168 uacp->usb_ac_audiohdl, 1169 AM_HWSC_SET_GAIN_DELTA, 1170 AUDIO_PLAY, val, 1171 AUDIO_NO_SLEEP); 1172 mutex_enter(&uacp-> 1173 usb_ac_mutex); 1174 } 1175 uacp->usb_ac_busy_count--; 1176 /* FALLTHRU */ 1177 case USB_AUDIO_MUTE: 1178 default: 1179 freemsg(mp); 1180 break; 1181 } 1182 } else { 1183 freemsg(mp); 1184 } 1185 1186 break; 1187 default: 1188 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1189 "M_CTL from unknown module(%s)", 1190 ddi_driver_name(plumb_infop->acp_dip)); 1191 freemsg(mp); 1192 } 1193 1194 break; 1195 default: 1196 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1197 "Unknown type=%d", mp->b_datap->db_type); 1198 usb_ac_free_mblk(mp); 1199 } 1200 mutex_exit(&uacp->usb_ac_mutex); 1201 1202 /* 1203 * Nobody is waiting; nothing to send up. 1204 */ 1205 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1206 "usb_ac_lrput: done"); 1207 1208 return (error); 1209 } 1210 1211 1212 /* 1213 * Power Management 1214 * usb_ac_power: 1215 * power entry point 1216 */ 1217 static int 1218 usb_ac_power(dev_info_t *dip, int comp, int level) 1219 { 1220 int instance = ddi_get_instance(dip); 1221 usb_ac_state_t *uacp; 1222 usb_ac_power_t *uacpm; 1223 int rval = DDI_FAILURE; 1224 1225 uacp = ddi_get_soft_state(usb_ac_statep, instance); 1226 1227 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1228 "usb_ac_power: comp=%d level=%d", comp, level); 1229 1230 mutex_enter(&uacp->usb_ac_mutex); 1231 uacpm = uacp->usb_ac_pm; 1232 1233 if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) { 1234 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1235 "usb_ac_power: illegal level=%d pwr_states=%d", 1236 level, uacpm->acpm_pwr_states); 1237 1238 goto done; 1239 } 1240 1241 switch (level) { 1242 case USB_DEV_OS_PWR_OFF: 1243 rval = usb_ac_pwrlvl0(uacp); 1244 break; 1245 case USB_DEV_OS_PWR_1: 1246 rval = usb_ac_pwrlvl1(uacp); 1247 break; 1248 case USB_DEV_OS_PWR_2: 1249 rval = usb_ac_pwrlvl2(uacp); 1250 break; 1251 case USB_DEV_OS_FULL_PWR: 1252 rval = usb_ac_pwrlvl3(uacp); 1253 break; 1254 } 1255 1256 done: 1257 mutex_exit(&uacp->usb_ac_mutex); 1258 1259 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 1260 } 1261 1262 1263 /* 1264 * functions to handle power transition for various levels 1265 * These functions act as place holders to issue USB commands 1266 * to the devices to change their power levels 1267 * Level 0 = Device is powered off 1268 * Level 3 = Device if full powered 1269 * Level 1,2 = Intermediate power level of the device as implemented 1270 * by the hardware. 1271 * Note that Level 0 is OS power-off and Level 3 is OS full-power. 1272 */ 1273 static int 1274 usb_ac_pwrlvl0(usb_ac_state_t *uacp) 1275 { 1276 usb_ac_power_t *uacpm; 1277 int rval; 1278 1279 uacpm = uacp->usb_ac_pm; 1280 1281 switch (uacp->usb_ac_dev_state) { 1282 case USB_DEV_ONLINE: 1283 /* Deny the powerdown request if the device is busy */ 1284 if (uacpm->acpm_pm_busy != 0) { 1285 1286 return (USB_FAILURE); 1287 } 1288 1289 /* Issue USB D3 command to the device here */ 1290 rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip); 1291 ASSERT(rval == USB_SUCCESS); 1292 1293 uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN; 1294 uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF; 1295 1296 /* FALLTHRU */ 1297 case USB_DEV_DISCONNECTED: 1298 case USB_DEV_SUSPENDED: 1299 case USB_DEV_PWRED_DOWN: 1300 default: 1301 return (USB_SUCCESS); 1302 } 1303 } 1304 1305 1306 /* ARGSUSED */ 1307 static int 1308 usb_ac_pwrlvl1(usb_ac_state_t *uacp) 1309 { 1310 int rval; 1311 1312 /* Issue USB D2 command to the device here */ 1313 rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip); 1314 ASSERT(rval == USB_SUCCESS); 1315 1316 return (USB_FAILURE); 1317 } 1318 1319 1320 /* ARGSUSED */ 1321 static int 1322 usb_ac_pwrlvl2(usb_ac_state_t *uacp) 1323 { 1324 int rval; 1325 1326 rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip); 1327 ASSERT(rval == USB_SUCCESS); 1328 1329 return (USB_FAILURE); 1330 } 1331 1332 1333 static int 1334 usb_ac_pwrlvl3(usb_ac_state_t *uacp) 1335 { 1336 usb_ac_power_t *uacpm; 1337 int rval; 1338 1339 uacpm = uacp->usb_ac_pm; 1340 1341 switch (uacp->usb_ac_dev_state) { 1342 case USB_DEV_PWRED_DOWN: 1343 /* Issue USB D0 command to the device here */ 1344 rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip); 1345 ASSERT(rval == USB_SUCCESS); 1346 1347 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 1348 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR; 1349 /* FALLTHRU */ 1350 case USB_DEV_ONLINE: 1351 /* we are already in full power */ 1352 1353 /* FALLTHRU */ 1354 case USB_DEV_DISCONNECTED: 1355 case USB_DEV_SUSPENDED: 1356 1357 return (USB_SUCCESS); 1358 default: 1359 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1360 "usb_ac_pwerlvl3: Illegal dev_state"); 1361 1362 return (USB_FAILURE); 1363 } 1364 } 1365 1366 1367 static void 1368 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp) 1369 { 1370 usb_ac_power_t *uacpm; 1371 uint_t pwr_states; 1372 1373 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1374 "usb_ac_create_pm_components: begin"); 1375 1376 /* Allocate the state structure */ 1377 uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP); 1378 uacp->usb_ac_pm = uacpm; 1379 uacpm->acpm_state = uacp; 1380 uacpm->acpm_capabilities = 0; 1381 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR; 1382 1383 if (usb_create_pm_components(dip, &pwr_states) == 1384 USB_SUCCESS) { 1385 if (usb_handle_remote_wakeup(dip, 1386 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) { 1387 uacpm->acpm_wakeup_enabled = 1; 1388 1389 USB_DPRINTF_L4(PRINT_MASK_PM, 1390 uacp->usb_ac_log_handle, 1391 "remote Wakeup enabled"); 1392 } 1393 uacpm->acpm_pwr_states = (uint8_t)pwr_states; 1394 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 1395 } else { 1396 if (uacpm) { 1397 kmem_free(uacpm, sizeof (usb_ac_power_t)); 1398 uacp->usb_ac_pm = NULL; 1399 } 1400 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1401 "pm not enabled"); 1402 } 1403 1404 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1405 "usb_ac_create_pm_components: end"); 1406 } 1407 1408 1409 /* 1410 * usb_ac_plumb_ioctl: 1411 * IOCTL issued from plumbing thread (only P_LINK_LH/P_UNLINK for now 1412 * caused by ldi_ioctl). Maybe we will need to use this function 1413 * to issue other IOCTLS to children in future from plumbing thread 1414 */ 1415 static void 1416 usb_ac_plumb_ioctl(queue_t *q, mblk_t *mp) 1417 { 1418 int instance = audio_sup_get_qptr_instance(q); 1419 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance); 1420 struct iocblk *iocp; 1421 struct linkblk *linkp; 1422 int n; 1423 usb_ac_streams_info_t *streams_infop; 1424 1425 ASSERT(uacp != NULL); 1426 ASSERT(mp != NULL); 1427 ASSERT(mp->b_cont != NULL); 1428 1429 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1430 "usb_ac_plumb_ioctl, q=0x%p mp=0x%p instance=%d", 1431 (void *)q, (void *)mp, instance); 1432 1433 iocp = (struct iocblk *)mp->b_rptr; 1434 mutex_enter(&uacp->usb_ac_mutex); 1435 n = uacp->usb_ac_current_plumbed_index; 1436 1437 switch (iocp->ioc_cmd) { 1438 case I_PLINK: 1439 linkp = (struct linkblk *)mp->b_cont->b_rptr; 1440 1441 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1442 "LINK ioctl, index=%d linkblk ptr=0x%p", n, (void *)linkp); 1443 1444 /* 1445 * We keep track of the module that is being 1446 * currently plumbed through usb_ac_current_plumbed_index 1447 * to the plumb structure array. We set the lwq field 1448 * of the plumb structure here. 1449 */ 1450 ASSERT(uacp->usb_ac_plumbed[n].acp_lwq == NULL); 1451 uacp->usb_ac_plumbed[n].acp_lwq = linkp->l_qbot; 1452 uacp->usb_ac_plumbed[n].acp_lrq = RD(linkp->l_qbot); 1453 1454 audio_sup_set_qptr(uacp->usb_ac_plumbed[n].acp_lrq, 1455 uacp->usb_ac_dev, (void *)uacp); 1456 1457 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1458 "index=%d lwq=0x%p lrq=0x%p", n, (void *)linkp->l_qbot, 1459 (void *)RD(linkp->l_qbot)); 1460 break; 1461 case I_UNLINK: 1462 case I_PUNLINK: 1463 linkp = (struct linkblk *)mp->b_cont->b_rptr; 1464 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1465 "UNLINK ioctl, linkblk ptr=0x%p", (void *)linkp); 1466 1467 audio_sup_free_qptr(RD(linkp->l_qbot)); 1468 uacp->usb_ac_dev = 0; 1469 1470 if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) { 1471 1472 /* 1473 * we bzero the streams info and plumbed structure 1474 * since there is no guarantee that the next plumbing 1475 * will be identical 1476 */ 1477 streams_infop = (usb_ac_streams_info_t *) 1478 uacp->usb_ac_plumbed[n].acp_data; 1479 cv_destroy(&(streams_infop->acs_ac_to_as_req.acr_cv)); 1480 1481 /* bzero the relevant plumbing structure */ 1482 bzero(streams_infop, sizeof (usb_ac_streams_info_t)); 1483 } 1484 bzero(&uacp->usb_ac_plumbed[n], sizeof (usb_ac_plumbed_t)); 1485 1486 iocp->ioc_count = 0; 1487 break; 1488 default: 1489 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1490 "Unknown ioctl, cmd=%d", iocp->ioc_cmd); 1491 iocp->ioc_error = EINVAL; 1492 mutex_exit(&uacp->usb_ac_mutex); 1493 1494 goto iocnak; 1495 } 1496 1497 mutex_exit(&uacp->usb_ac_mutex); 1498 1499 /* 1500 * Common exit path for calls that return a positive 1501 * acknowledgment with a return value of 0. 1502 */ 1503 iocp->ioc_rval = 0; 1504 iocp->ioc_error = 0; 1505 mp->b_datap->db_type = M_IOCACK; 1506 qreply(q, mp); 1507 1508 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1509 "usb_ac_plumb_ioctl: End (ACK)"); 1510 1511 return; 1512 1513 iocnak: 1514 1515 iocp->ioc_rval = 0; 1516 mp->b_datap->db_type = M_IOCNAK; 1517 qreply(q, mp); 1518 1519 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1520 "usb_ac_plumb_ioctl: End: (NAK)"); 1521 } 1522 1523 1524 /* 1525 * usb_ac_get_plumb_info: 1526 * Get plumb_info pointer that matches module "name" 1527 * If name = "usb_as", match the direction also (record or play) 1528 */ 1529 static usb_ac_plumbed_t * 1530 usb_ac_get_plumb_info(usb_ac_state_t *uacp, char *name, uchar_t reg_play_type) 1531 { 1532 int n; 1533 usb_ac_plumbed_t *plumb_infop = NULL; 1534 usb_as_registration_t *asreg; 1535 usb_ac_streams_info_t *asinfo; 1536 1537 for (n = 0; n < USB_AC_MAX_PLUMBED; n++) { 1538 if (uacp->usb_ac_plumbed[n].acp_dip == NULL) { 1539 continue; 1540 } 1541 if (strcmp(ddi_driver_name(uacp-> 1542 usb_ac_plumbed[n].acp_dip), name) != 0) { 1543 continue; 1544 } 1545 if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) { 1546 asinfo = uacp->usb_ac_plumbed[n].acp_data; 1547 asreg = asinfo->acs_streams_reg; 1548 /* Match direction */ 1549 if (asreg->reg_mode & reg_play_type) { 1550 break; 1551 } 1552 } else if (uacp->usb_ac_plumbed[n].acp_driver == 1553 USB_AH_PLUMBED) { 1554 break; 1555 } 1556 } 1557 1558 if (n < USB_AC_MAX_PLUMBED) { 1559 plumb_infop = &uacp->usb_ac_plumbed[n]; 1560 } 1561 1562 return (plumb_infop); 1563 } 1564 1565 1566 /* 1567 * usb_ac_get_pinfo_from_lrq: 1568 * Get plumb_info pointer that matches the lrq passed 1569 */ 1570 static usb_ac_plumbed_t * 1571 usb_ac_get_plumb_info_from_lrq(usb_ac_state_t *uacp, queue_t *lrq) 1572 { 1573 int n; 1574 1575 for (n = 0; n < USB_AC_MAX_PLUMBED; n++) { 1576 if (uacp->usb_ac_plumbed[n].acp_lrq == lrq) { 1577 1578 return (&uacp->usb_ac_plumbed[n]); 1579 } 1580 } 1581 1582 return (NULL); 1583 } 1584 1585 1586 /* 1587 * usb_ac_get_featureID: 1588 * find out if there is at least one feature unit that supports 1589 * the request controls. 1590 * Return featureID or USB_AC_ID_NONE. 1591 */ 1592 static uint_t 1593 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir, 1594 uint_t channel, uint_t control) 1595 { 1596 uint_t count = 0; 1597 1598 return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT, 1599 channel, control, USB_AC_FIND_ONE, &count, 0, 1600 usb_ac_feature_unit_check)); 1601 } 1602 1603 1604 /* 1605 * usb_ac_feature_unit_check: 1606 * check if a feature unit can support the required channel 1607 * and control combination. Return USB_SUCCESS or USB_FAILURE. 1608 * Called for each matching unit from usb_ac_traverse_connections. 1609 */ 1610 /*ARGSUSED*/ 1611 static int 1612 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID, 1613 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 1614 { 1615 usb_audio_feature_unit_descr1_t *feature_descrp; 1616 int n_channel_controls; 1617 1618 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1619 "usb_ac_feature_unit_check: ID=%d ch=%d cntrl=%d", 1620 featureID, channel, control); 1621 1622 ASSERT((featureID >= 0) && (featureID < uacp->usb_ac_max_unit)); 1623 1624 /* 1625 * check if this control is supported on this channel 1626 */ 1627 feature_descrp = (usb_audio_feature_unit_descr1_t *) 1628 uacp->usb_ac_units[featureID].acu_descriptor; 1629 ASSERT(feature_descrp->bUnitID == featureID); 1630 1631 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1632 "bControlSize=%d", feature_descrp->bControlSize); 1633 1634 if (feature_descrp->bControlSize == 0) { 1635 featureID = USB_AC_ID_NONE; 1636 } else { 1637 uint_t index; 1638 1639 n_channel_controls = (feature_descrp->bLength - 1640 offsetof(usb_audio_feature_unit_descr1_t, 1641 bmaControls))/feature_descrp->bControlSize; 1642 1643 USB_DPRINTF_L3(PRINT_MASK_ALL, 1644 uacp->usb_ac_log_handle, 1645 "#controls: %d index=%d", n_channel_controls, 1646 feature_descrp->bControlSize * channel); 1647 1648 if (channel > n_channel_controls) { 1649 featureID = USB_AC_ID_NONE; 1650 } else { 1651 /* 1652 * we only support MUTE and VOLUME 1653 * which are in the first byte 1654 */ 1655 index = feature_descrp->bControlSize * 1656 channel; 1657 1658 USB_DPRINTF_L3(PRINT_MASK_ALL, 1659 uacp->usb_ac_log_handle, 1660 "control: 0x%x", 1661 feature_descrp->bmaControls[index]); 1662 1663 if ((feature_descrp->bmaControls[index] & 1664 control) == 0) { 1665 featureID = USB_AC_ID_NONE; 1666 } 1667 } 1668 } 1669 1670 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1671 "usb_ac_feature_unit_check: dir=%d featureID=0x%x", 1672 dir, featureID); 1673 1674 return ((featureID != USB_AC_ID_NONE) ? 1675 USB_SUCCESS : USB_FAILURE); 1676 } 1677 1678 1679 /* 1680 * Descriptor Management 1681 * 1682 * usb_ac_handle_descriptors: 1683 * extract interesting descriptors from the config cloud 1684 */ 1685 static int 1686 usb_ac_handle_descriptors(usb_ac_state_t *uacp) 1687 { 1688 int rest, len, index; 1689 int rval = USB_FAILURE; 1690 usb_audio_cs_if_descr_t descr; 1691 usb_client_dev_data_t *dev_data = uacp->usb_ac_dev_data; 1692 usb_alt_if_data_t *altif_data; 1693 usb_cvs_data_t *cvs; 1694 1695 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1696 "config=%ld, interface=%d", 1697 (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]), 1698 dev_data->dev_curr_if); 1699 1700 altif_data = &dev_data->dev_curr_cfg-> 1701 cfg_if[dev_data->dev_curr_if].if_alt[0]; 1702 1703 uacp->usb_ac_ifno = dev_data->dev_curr_if; 1704 uacp->usb_ac_if_descr = altif_data->altif_descr; 1705 1706 /* find USB_AUDIO_CS_INTERFACE type descriptor */ 1707 for (index = 0; index < altif_data->altif_n_cvs; index++) { 1708 cvs = &altif_data->altif_cvs[index]; 1709 if (cvs->cvs_buf == NULL) { 1710 continue; 1711 } 1712 if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) { 1713 break; 1714 } 1715 } 1716 1717 if (index == altif_data->altif_n_cvs) { 1718 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1719 "cannot find descriptor type %d", USB_AUDIO_CS_INTERFACE); 1720 1721 return (rval); 1722 } 1723 1724 len = usb_parse_data( 1725 CS_AC_IF_HEADER_FORMAT, 1726 cvs->cvs_buf, cvs->cvs_buf_len, 1727 (void *)&descr, sizeof (usb_audio_cs_if_descr_t)); 1728 1729 /* is this a sane header descriptor */ 1730 if (!((len >= CS_AC_IF_HEADER_SIZE) && 1731 (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) && 1732 (descr.bDescriptorSubType == USB_AUDIO_HEADER))) { 1733 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1734 "invalid header"); 1735 1736 return (rval); 1737 } 1738 1739 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1740 "header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t" 1741 "total=0x%x InCol=0x%x", 1742 descr.bDescriptorType, 1743 descr.bDescriptorSubType, 1744 descr.bcdADC, 1745 descr.wTotalLength, 1746 descr.blnCollection); 1747 1748 /* 1749 * we read descriptors by index and store them in ID array. 1750 * the actual parsing is done in usb_ac_add_unit_descriptor() 1751 */ 1752 rest = descr.wTotalLength - descr.bLength; 1753 for (index++; rest > 0; index++) { 1754 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1755 "index=%d rest=%d", index, rest); 1756 1757 cvs = &altif_data->altif_cvs[index]; 1758 if (cvs->cvs_buf == NULL) { 1759 continue; 1760 } 1761 1762 /* add to ID array */ 1763 usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf, 1764 cvs->cvs_buf_len); 1765 rest -= cvs->cvs_buf[0]; 1766 } 1767 rval = USB_SUCCESS; 1768 1769 usb_ac_setup_connections(uacp); 1770 1771 /* determine port types */ 1772 usb_ac_map_termtype_to_port(uacp, AUDIO_PLAY); 1773 usb_ac_map_termtype_to_port(uacp, AUDIO_RECORD); 1774 1775 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1776 "input port types=0x%x output port types =0x%x", 1777 uacp->usb_ac_input_ports, uacp->usb_ac_output_ports); 1778 1779 1780 return (rval); 1781 } 1782 1783 1784 /* 1785 * usb_ac_setup_connections: 1786 * build a matrix reflecting all connections 1787 */ 1788 static void 1789 usb_ac_setup_connections(usb_ac_state_t *uacp) 1790 { 1791 usb_ac_unit_list_t *units = uacp->usb_ac_units; 1792 uchar_t *a, **p, i, unit; 1793 size_t a_len, p_len; 1794 1795 /* allocate array for unit types for quick reference */ 1796 uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit, 1797 KM_SLEEP); 1798 /* allocate array for traversal path */ 1799 uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit, 1800 KM_SLEEP); 1801 1802 1803 /* allocate the connection matrix and set it up */ 1804 a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit; 1805 p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *); 1806 1807 /* trick to create a 2 dimensional array */ 1808 a = kmem_zalloc(a_len, KM_SLEEP); 1809 p = kmem_zalloc(p_len, KM_SLEEP); 1810 for (i = 0; i < uacp->usb_ac_max_unit; i++) { 1811 p[i] = a + i * uacp->usb_ac_max_unit; 1812 } 1813 uacp->usb_ac_connections = p; 1814 uacp->usb_ac_connections_len = p_len; 1815 uacp->usb_ac_connections_a = a; 1816 uacp->usb_ac_connections_a_len = a_len; 1817 1818 /* traverse all units and set connections */ 1819 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) { 1820 1821 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1822 "traversing unit=0x%x type=0x%x", 1823 unit, units[unit].acu_type); 1824 1825 /* store type in the first unused column */ 1826 uacp->usb_ac_unit_type[unit] = units[unit].acu_type; 1827 1828 /* save the Unit ID in the unit it points to */ 1829 switch (units[unit].acu_type) { 1830 case USB_AUDIO_FEATURE_UNIT: 1831 { 1832 usb_audio_feature_unit_descr1_t *d = 1833 units[unit].acu_descriptor; 1834 1835 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1836 "sourceID=0x%x type=0x%x", d->bSourceID, 1837 units[d->bSourceID].acu_type); 1838 1839 if (d->bSourceID != 0) { 1840 ASSERT(p[unit][d->bSourceID] == B_FALSE); 1841 p[unit][d->bSourceID] = B_TRUE; 1842 } 1843 1844 break; 1845 } 1846 case USB_AUDIO_OUTPUT_TERMINAL: 1847 { 1848 usb_audio_output_term_descr_t *d = 1849 units[unit].acu_descriptor; 1850 1851 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1852 "sourceID=0x%x type=0x%x", d->bSourceID, 1853 units[d->bSourceID].acu_type); 1854 1855 if (d->bSourceID != 0) { 1856 ASSERT(p[unit][d->bSourceID] == B_FALSE); 1857 p[unit][d->bSourceID] = B_TRUE; 1858 } 1859 1860 break; 1861 } 1862 case USB_AUDIO_MIXER_UNIT: 1863 { 1864 usb_audio_mixer_unit_descr1_t *d = 1865 units[unit].acu_descriptor; 1866 int n_sourceID = d->bNrInPins; 1867 int id; 1868 1869 for (id = 0; id < n_sourceID; id++) { 1870 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1871 uacp->usb_ac_log_handle, 1872 "sourceID=0x%x type=0x%x c=%d", 1873 d->baSourceID[id], 1874 units[d->baSourceID[id]].acu_type, 1875 p[unit][d->baSourceID[id]]); 1876 1877 if (d->baSourceID[id] != 0) { 1878 ASSERT(p[unit][d->baSourceID[id]] == 1879 B_FALSE); 1880 p[unit][d->baSourceID[id]] = B_TRUE; 1881 } 1882 } 1883 1884 break; 1885 } 1886 case USB_AUDIO_SELECTOR_UNIT: 1887 { 1888 usb_audio_selector_unit_descr1_t *d = 1889 units[unit].acu_descriptor; 1890 int n_sourceID = d->bNrInPins; 1891 int id; 1892 1893 for (id = 0; id < n_sourceID; id++) { 1894 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1895 uacp->usb_ac_log_handle, 1896 "sourceID=0x%x type=0x%x", 1897 d->baSourceID[id], 1898 units[d->baSourceID[id]].acu_type); 1899 1900 if (d->baSourceID[id] != 0) { 1901 ASSERT(p[unit][d->baSourceID[id]] == 1902 B_FALSE); 1903 p[unit][d->baSourceID[id]] = B_TRUE; 1904 } 1905 } 1906 1907 break; 1908 } 1909 case USB_AUDIO_PROCESSING_UNIT: 1910 { 1911 usb_audio_mixer_unit_descr1_t *d = 1912 units[unit].acu_descriptor; 1913 int n_sourceID = d->bNrInPins; 1914 int id; 1915 1916 for (id = 0; id < n_sourceID; id++) { 1917 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1918 uacp->usb_ac_log_handle, 1919 "sourceID=0x%x type=0x%x", 1920 d->baSourceID[id], 1921 units[d->baSourceID[id]].acu_type); 1922 1923 if (d->baSourceID[id] != 0) { 1924 ASSERT(p[unit][d->baSourceID[id]] == 1925 B_FALSE); 1926 p[unit][d->baSourceID[id]] = B_TRUE; 1927 } 1928 } 1929 1930 break; 1931 } 1932 case USB_AUDIO_EXTENSION_UNIT: 1933 { 1934 usb_audio_extension_unit_descr1_t *d = 1935 units[unit].acu_descriptor; 1936 int n_sourceID = d->bNrInPins; 1937 int id; 1938 1939 for (id = 0; id < n_sourceID; id++) { 1940 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1941 uacp->usb_ac_log_handle, 1942 "sourceID=0x%x type=0x%x", 1943 d->baSourceID[id], 1944 units[d->baSourceID[id]].acu_type); 1945 1946 if (d->baSourceID[id] != 0) { 1947 ASSERT(p[unit][d->baSourceID[id]] == 1948 B_TRUE); 1949 p[unit][d->baSourceID[id]] = B_FALSE; 1950 } 1951 } 1952 1953 break; 1954 } 1955 case USB_AUDIO_INPUT_TERMINAL: 1956 1957 break; 1958 default: 1959 /* 1960 * Ignore the rest because they are not support yet 1961 */ 1962 break; 1963 } 1964 } 1965 1966 #ifdef DEBUG 1967 /* display topology in log buffer */ 1968 { 1969 uint_t i, j, l; 1970 char *buf; 1971 1972 l = uacp->usb_ac_max_unit * 5; 1973 1974 buf = kmem_alloc(l, KM_SLEEP); 1975 1976 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1977 "unit types:"); 1978 1979 /* two strings so they won't be replaced accidentily by tab */ 1980 (void) sprintf(&buf[0], " "" "); 1981 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1982 (void) sprintf(&buf[2 + (i*3)], "%02d ", i); 1983 } 1984 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1985 1986 (void) sprintf(&buf[0], " +-------"); 1987 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1988 (void) sprintf(&buf[5+((i-1)*3)], "---"); 1989 } 1990 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1991 1992 (void) sprintf(&buf[0], " "" "); 1993 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1994 (void) sprintf(&buf[2 + (i*3)], "%02d ", 1995 uacp->usb_ac_unit_type[i]); 1996 } 1997 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1998 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " "); 1999 2000 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2001 "adjacency matrix:"); 2002 (void) sprintf(&buf[0], " "" "); 2003 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 2004 (void) sprintf(&buf[2 + (i*3)], "%02d ", i); 2005 } 2006 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 2007 2008 (void) sprintf(&buf[0], " +-------"); 2009 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 2010 (void) sprintf(&buf[5+((i-1)*3)], "---"); 2011 } 2012 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 2013 2014 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 2015 (void) sprintf(&buf[0], "%02d| "" ", i); 2016 for (j = 1; j < uacp->usb_ac_max_unit; j++) { 2017 (void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]); 2018 } 2019 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 2020 } 2021 kmem_free(buf, l); 2022 } 2023 #endif 2024 } 2025 2026 2027 /* 2028 * usb_ac_add_unit_descriptor: 2029 * take the parsed descriptor in the buffer and store it in the ID unit 2030 * array. we grow the unit array if the ID exceeds the current max 2031 */ 2032 static void 2033 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer, 2034 size_t buflen) 2035 { 2036 void *descr; 2037 int len; 2038 char *format; 2039 size_t size; 2040 2041 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2042 "usb_ac_add_unit_descriptor: 0x%x 0x%x 0x%x", 2043 buffer[0], buffer[1], buffer[2]); 2044 2045 /* doubling the length should allow for padding */ 2046 len = 2 * buffer[0]; 2047 descr = kmem_zalloc(len, KM_SLEEP); 2048 2049 switch (buffer[2]) { 2050 case USB_AUDIO_INPUT_TERMINAL: 2051 format = CS_AC_INPUT_TERM_FORMAT; 2052 size = CS_AC_INPUT_TERM_SIZE; 2053 2054 break; 2055 case USB_AUDIO_OUTPUT_TERMINAL: 2056 format = CS_AC_OUTPUT_TERM_FORMAT; 2057 size = CS_AC_OUTPUT_TERM_SIZE; 2058 2059 break; 2060 case USB_AUDIO_MIXER_UNIT: 2061 format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c"; 2062 size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1; 2063 2064 break; 2065 case USB_AUDIO_SELECTOR_UNIT: 2066 format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c"; 2067 size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1; 2068 2069 break; 2070 case USB_AUDIO_FEATURE_UNIT: 2071 format = CS_AC_FEATURE_UNIT_FORMAT "255c"; 2072 size = CS_AC_FEATURE_UNIT_SIZE; 2073 2074 break; 2075 case USB_AUDIO_PROCESSING_UNIT: 2076 format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c"; 2077 size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1; 2078 2079 break; 2080 case USB_AUDIO_EXTENSION_UNIT: 2081 format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c"; 2082 size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1; 2083 2084 break; 2085 default: 2086 USB_DPRINTF_L2(PRINT_MASK_ATTA, 2087 uacp->usb_ac_log_handle, 2088 "unsupported descriptor %d", buffer[2]); 2089 2090 /* ignore this descriptor */ 2091 kmem_free(descr, len); 2092 2093 return; 2094 } 2095 2096 if (usb_parse_data(format, buffer, buflen, descr, len) < size) { 2097 /* ignore this descriptor */ 2098 kmem_free(descr, len); 2099 2100 return; 2101 } 2102 2103 switch (buffer[2]) { 2104 case USB_AUDIO_INPUT_TERMINAL: 2105 { 2106 usb_audio_input_term_descr_t *d = 2107 (usb_audio_input_term_descr_t *)descr; 2108 2109 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2110 uacp->usb_ac_log_handle, 2111 "input term: type=0x%x sub=0x%x termid=0x%x\n\t" 2112 "termtype=0x%x assoc=0x%x #ch=%d " 2113 "chconf=0x%x ich=0x%x iterm=0x%x", 2114 d->bDescriptorType, d->bDescriptorSubType, 2115 d->bTerminalID, d->wTerminalType, 2116 d->bAssocTerminal, d->bNrChannels, 2117 d->wChannelConfig, d->iChannelNames, 2118 d->iTerminal); 2119 2120 usb_ac_alloc_unit(uacp, d->bTerminalID); 2121 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr; 2122 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2]; 2123 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len; 2124 2125 break; 2126 } 2127 case USB_AUDIO_OUTPUT_TERMINAL: 2128 { 2129 usb_audio_output_term_descr_t *d = 2130 (usb_audio_output_term_descr_t *)descr; 2131 2132 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2133 uacp->usb_ac_log_handle, 2134 "output term: type=0x%x sub=0x%x termid=0x%x\n\t" 2135 "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x", 2136 d->bDescriptorType, d->bDescriptorSubType, 2137 d->bTerminalID, d->wTerminalType, 2138 d->bAssocTerminal, d->bSourceID, 2139 d->iTerminal); 2140 2141 usb_ac_alloc_unit(uacp, d->bTerminalID); 2142 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr; 2143 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2]; 2144 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len; 2145 2146 break; 2147 } 2148 case USB_AUDIO_MIXER_UNIT: 2149 { 2150 usb_audio_mixer_unit_descr1_t *d = 2151 (usb_audio_mixer_unit_descr1_t *)descr; 2152 2153 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2154 uacp->usb_ac_log_handle, 2155 "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2156 "#pins=0x%x sourceid[0]=0x%x", 2157 d->bDescriptorType, d->bDescriptorSubType, 2158 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2159 usb_ac_alloc_unit(uacp, d->bUnitID); 2160 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2161 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2162 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2163 2164 break; 2165 } 2166 case USB_AUDIO_SELECTOR_UNIT: 2167 { 2168 usb_audio_selector_unit_descr1_t *d = 2169 (usb_audio_selector_unit_descr1_t *)descr; 2170 2171 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2172 uacp->usb_ac_log_handle, 2173 "selector unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2174 "#pins=0x%x sourceid[0]=0x%x", 2175 d->bDescriptorType, d->bDescriptorSubType, 2176 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2177 usb_ac_alloc_unit(uacp, d->bUnitID); 2178 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2179 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2180 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2181 2182 break; 2183 } 2184 case USB_AUDIO_FEATURE_UNIT: 2185 { 2186 usb_audio_feature_unit_descr1_t *d = 2187 (usb_audio_feature_unit_descr1_t *)descr; 2188 2189 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2190 uacp->usb_ac_log_handle, 2191 "feature unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2192 "sourceid=0x%x size=0x%x", 2193 d->bDescriptorType, d->bDescriptorSubType, 2194 d->bUnitID, d->bSourceID, d->bControlSize); 2195 2196 usb_ac_alloc_unit(uacp, d->bUnitID); 2197 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2198 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2199 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2200 2201 break; 2202 } 2203 case USB_AUDIO_PROCESSING_UNIT: 2204 { 2205 usb_audio_processing_unit_descr1_t *d = 2206 (usb_audio_processing_unit_descr1_t *)descr; 2207 2208 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2209 uacp->usb_ac_log_handle, 2210 "processing unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2211 "#pins=0x%x sourceid[0]=0x%x", 2212 d->bDescriptorType, d->bDescriptorSubType, 2213 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2214 usb_ac_alloc_unit(uacp, d->bUnitID); 2215 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2216 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2217 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2218 2219 break; 2220 } 2221 case USB_AUDIO_EXTENSION_UNIT: 2222 { 2223 usb_audio_extension_unit_descr1_t *d = 2224 (usb_audio_extension_unit_descr1_t *)descr; 2225 2226 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2227 uacp->usb_ac_log_handle, 2228 "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2229 "#pins=0x%x sourceid[0]=0x%x", 2230 d->bDescriptorType, d->bDescriptorSubType, 2231 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2232 usb_ac_alloc_unit(uacp, d->bUnitID); 2233 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2234 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2235 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2236 2237 break; 2238 } 2239 default: 2240 break; 2241 } 2242 } 2243 2244 2245 /* 2246 * usb_ac_alloc_unit: 2247 * check if the unit ID is less than max_unit in which case no 2248 * extra entries are needed. If more entries are needed, copy over 2249 * the existing array into a new larger array 2250 */ 2251 static void 2252 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit) 2253 { 2254 usb_ac_unit_list_t *old = NULL; 2255 uint_t max_unit; 2256 2257 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2258 "usb_ac_alloc_unit: unit=%d", unit); 2259 2260 if (uacp->usb_ac_units) { 2261 if (unit < uacp->usb_ac_max_unit) { 2262 /* existing array is big enough */ 2263 2264 return; 2265 } 2266 old = uacp->usb_ac_units; 2267 max_unit = uacp->usb_ac_max_unit; 2268 } 2269 2270 /* allocate two extra ones */ 2271 unit += 2; 2272 uacp->usb_ac_max_unit = unit; 2273 uacp->usb_ac_units = kmem_zalloc(unit * 2274 sizeof (usb_ac_unit_list_t), KM_SLEEP); 2275 2276 if (old) { 2277 size_t len = max_unit * sizeof (usb_ac_unit_list_t); 2278 bcopy(old, uacp->usb_ac_units, len); 2279 2280 kmem_free(old, len); 2281 } 2282 } 2283 2284 2285 /* 2286 * usb_ac_free_all_units: 2287 * free the entire unit list 2288 */ 2289 static void 2290 usb_ac_free_all_units(usb_ac_state_t *uacp) 2291 { 2292 uint_t unit; 2293 usb_ac_unit_list_t *unitp; 2294 2295 if (uacp->usb_ac_units == NULL) { 2296 2297 return; 2298 } 2299 2300 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2301 "usb_ac_alloc_unit: max_unit=%d", uacp->usb_ac_max_unit); 2302 2303 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) { 2304 unitp = &uacp->usb_ac_units[unit]; 2305 if (unitp) { 2306 if (unitp->acu_descriptor) { 2307 kmem_free(unitp->acu_descriptor, 2308 unitp->acu_descr_length); 2309 } 2310 } 2311 } 2312 2313 kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit * 2314 sizeof (usb_ac_unit_list_t)); 2315 } 2316 2317 2318 /* 2319 * usb_ac_lookup_port_type: 2320 * map term type to port type 2321 * default just return LINE_IN + LINE_OUT 2322 */ 2323 static int 2324 usb_ac_lookup_port_type(ushort_t termtype) 2325 { 2326 uint_t i; 2327 2328 for (i = 0; ; i++) { 2329 if (usb_ac_term_type_map[i].term_type == 0) { 2330 2331 break; 2332 } 2333 2334 if (usb_ac_term_type_map[i].term_type == termtype) { 2335 2336 return (usb_ac_term_type_map[i].port_type); 2337 } 2338 } 2339 2340 return (AUDIO_LINE_IN|AUDIO_LINE_OUT); 2341 } 2342 2343 2344 /* 2345 * usb_ac_update_port: 2346 * called for each terminal 2347 */ 2348 /*ARGSUSED*/ 2349 static int 2350 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id, 2351 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 2352 { 2353 if (dir & AUDIO_PLAY) { 2354 usb_audio_output_term_descr_t *d = 2355 (usb_audio_output_term_descr_t *) 2356 uacp->usb_ac_units[id].acu_descriptor; 2357 uint_t port_type = 2358 usb_ac_lookup_port_type(d->wTerminalType); 2359 2360 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2361 "usb_ac_update_port: dir=%d type=0x%x port type=%d", 2362 dir, d->wTerminalType, port_type); 2363 2364 uacp->usb_ac_output_ports |= port_type; 2365 uacp->usb_ac_output_ports &= ~AUDIO_LINE_IN; 2366 } else { 2367 usb_audio_output_term_descr_t *d = 2368 (usb_audio_output_term_descr_t *) 2369 uacp->usb_ac_units[id].acu_descriptor; 2370 uint_t port_type = 2371 usb_ac_lookup_port_type(d->wTerminalType); 2372 2373 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2374 "usb_ac_update_port: dir=%d type=0x%x port type=%d", 2375 dir, d->wTerminalType, port_type); 2376 2377 uacp->usb_ac_input_ports |= 2378 usb_ac_lookup_port_type(d->wTerminalType); 2379 uacp->usb_ac_input_ports &= ~AUDIO_LINE_OUT; 2380 } 2381 2382 return (USB_SUCCESS); 2383 } 2384 2385 2386 /* 2387 * usb_ac_map_termtype_to_port: 2388 * starting from a streaming termtype find all 2389 * input or output terminals and OR into uacp->usb_ac_input_ports 2390 * or uacp->usb_ac_output_ports; 2391 */ 2392 static void 2393 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir) 2394 { 2395 uint_t count = 0; 2396 uint_t depth = 0; 2397 uint_t search_type = (dir & AUDIO_PLAY) ? 2398 USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL; 2399 2400 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2401 "usb_ac_map_term_to_port: dir=%d", dir); 2402 2403 (void) usb_ac_traverse_all_units(uacp, dir, search_type, 0, 2404 0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port); 2405 2406 ASSERT(depth == 0); 2407 } 2408 2409 2410 /* 2411 * usb_ac_set_port: 2412 * find a selector port (record side only) and set the 2413 * input to the matching pin 2414 */ 2415 static uint_t 2416 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port) 2417 { 2418 uint_t count = 0; 2419 uint_t id; 2420 uint_t depth = 0; 2421 2422 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2423 "usb_ac_set_port: dir=%d port=%d", dir, port); 2424 2425 /* we only support the selector for the record side */ 2426 if (dir & AUDIO_RECORD) { 2427 id = usb_ac_traverse_all_units(uacp, dir, 2428 USB_AUDIO_SELECTOR_UNIT, 0, 2429 0, USB_AC_FIND_ONE, &count, port, &depth, 2430 usb_ac_set_selector); 2431 2432 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2433 "usb_ac_set_port: id=%d count=%d port=%d", 2434 id, count, port); 2435 2436 ASSERT(depth == 0); 2437 } 2438 2439 return (USB_SUCCESS); 2440 } 2441 2442 2443 /* 2444 * usb_ac_match_port: 2445 * given the requested port type, find a correspondig term type 2446 * Called from usb_ac_traverse_all_units() 2447 */ 2448 /*ARGSUSED*/ 2449 static int 2450 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id, 2451 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 2452 { 2453 uint_t port_type; 2454 2455 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2456 "usb_ac_match_port: id=%d dir=%d port=%d", 2457 id, dir, arg1); 2458 2459 if (dir & AUDIO_PLAY) { 2460 usb_audio_output_term_descr_t *d = 2461 (usb_audio_output_term_descr_t *) 2462 uacp->usb_ac_units[id].acu_descriptor; 2463 port_type = usb_ac_lookup_port_type(d->wTerminalType); 2464 2465 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2466 "usb_ac_match_port: " 2467 "dir=%d type=0x%x port_type=%d port=%d", 2468 dir, d->wTerminalType, port_type, arg1); 2469 } else { 2470 usb_audio_output_term_descr_t *d = 2471 (usb_audio_output_term_descr_t *) 2472 uacp->usb_ac_units[id].acu_descriptor; 2473 port_type = usb_ac_lookup_port_type(d->wTerminalType); 2474 2475 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2476 "usb_ac_match_port: " 2477 "dir=%d type=0x%x port_type=%d port=%d", 2478 dir, d->wTerminalType, port_type, arg1); 2479 } 2480 2481 return ((port_type & arg1) ? USB_SUCCESS : USB_FAILURE); 2482 } 2483 2484 2485 /* 2486 * usb_ac_set_selector: 2487 * Called from usb_ac_traverse_all_units() 2488 * Find the correct pin and set selector to this pin 2489 */ 2490 /*ARGSUSED*/ 2491 static int 2492 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id, 2493 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 2494 { 2495 uint_t count = 0; 2496 uint_t unit = USB_AC_ID_NONE; 2497 uint_t pin; 2498 uint_t search_target = 2499 (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL : 2500 USB_AUDIO_INPUT_TERMINAL; 2501 usb_audio_selector_unit_descr1_t *d = 2502 (usb_audio_selector_unit_descr1_t *) 2503 uacp->usb_ac_units[id].acu_descriptor; 2504 int n_sourceID = d->bNrInPins; 2505 int rval = USB_FAILURE; 2506 2507 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2508 "usb_ac_set_selector: id=%d dir=%d port=%d", 2509 id, dir, arg1); 2510 2511 /* 2512 * for each pin, find a term type that matches the 2513 * requested port type 2514 */ 2515 for (pin = 0; pin < n_sourceID; pin++) { 2516 if (d->baSourceID[pin] == 0) { 2517 2518 break; 2519 } 2520 unit = d->baSourceID[pin]; 2521 2522 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2523 "usb_ac_set_selector: pin=%d unit=%d", pin, unit); 2524 2525 if (uacp->usb_ac_unit_type[unit] == search_target) { 2526 if (usb_ac_match_port(uacp, unit, dir, channel, 2527 control, arg1, depth) == USB_SUCCESS) { 2528 2529 break; 2530 } else { 2531 unit = USB_AC_ID_NONE; 2532 2533 continue; 2534 } 2535 } 2536 2537 /* find units connected to this unit */ 2538 unit = usb_ac_traverse_connections(uacp, unit, 2539 dir, search_target, channel, control, 2540 USB_AC_FIND_ONE, &count, arg1, depth, 2541 usb_ac_match_port); 2542 2543 if (unit != USB_AC_ID_NONE) { 2544 2545 break; 2546 } 2547 } 2548 2549 2550 if (unit != USB_AC_ID_NONE) { 2551 mblk_t *data; 2552 usb_cr_t cr; 2553 usb_cb_flags_t cb_flags; 2554 2555 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2556 "usb_ac_set_selector: found id=%d at pin %d", unit, pin); 2557 2558 mutex_exit(&uacp->usb_ac_mutex); 2559 2560 data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL); 2561 2562 /* pins are 1-based */ 2563 *(data->b_rptr) = (char)++pin; 2564 2565 if (usb_pipe_sync_ctrl_xfer( 2566 uacp->usb_ac_dip, 2567 uacp->usb_ac_default_ph, 2568 USB_DEV_REQ_HOST_TO_DEV | 2569 USB_DEV_REQ_TYPE_CLASS | 2570 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 2571 USB_AUDIO_SET_CUR, /* bRequest */ 2572 0, /* wValue */ 2573 /* feature unit and id */ 2574 (id << 8)| uacp->usb_ac_ifno, /* wIndex */ 2575 1, /* wLength */ 2576 &data, 2577 USB_ATTRS_NONE, 2578 &cr, &cb_flags, 2579 USB_FLAGS_SLEEP) == USB_SUCCESS) { 2580 USB_DPRINTF_L3(PRINT_MASK_ALL, 2581 uacp->usb_ac_log_handle, 2582 "set current selection: %d", *data->b_rptr); 2583 2584 rval = USB_SUCCESS; 2585 } else { 2586 USB_DPRINTF_L2(PRINT_MASK_ALL, 2587 uacp->usb_ac_log_handle, 2588 "set current pin selection failed"); 2589 } 2590 freemsg(data); 2591 2592 mutex_enter(&uacp->usb_ac_mutex); 2593 } else { 2594 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2595 "usb_ac_set_selector: nothing found"); 2596 } 2597 2598 return (rval); 2599 } 2600 2601 2602 /* 2603 * usb_ac_set_control: 2604 * apply func to all units of search_target type for both the 2605 * requested channel and master channel 2606 */ 2607 static uint_t 2608 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target, 2609 uint_t channel, uint_t control, uint_t all_or_one, 2610 uint_t *count, uint_t arg1, 2611 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2612 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2613 { 2614 uint_t id; 2615 uint_t depth = 0; 2616 2617 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2618 "usb_ac_set_control: dir=%d type=%d ch=%d cntl=%d", 2619 dir, search_target, channel, control); 2620 2621 2622 id = usb_ac_traverse_all_units(uacp, dir, search_target, channel, 2623 control, all_or_one, count, arg1, &depth, func); 2624 2625 if ((channel != 0) && 2626 (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) || 2627 (all_or_one == USB_AC_FIND_ALL))) { 2628 /* try master channel */ 2629 channel = 0; 2630 id = usb_ac_traverse_all_units(uacp, dir, search_target, 2631 channel, control, all_or_one, count, arg1, 2632 &depth, func); 2633 } 2634 2635 ASSERT(depth == 0); 2636 2637 return (id); 2638 } 2639 2640 2641 /* 2642 * usb_ac_traverse_all_units: 2643 * traverse all units starting with all IT or OT depending on direction. 2644 * If no unit is found for the particular channel, try master channel 2645 * If a matching unit is found, apply the function passed by 2646 * the caller 2647 */ 2648 static uint_t 2649 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir, 2650 uint_t search_target, uint_t channel, uint_t control, 2651 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth, 2652 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2653 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2654 { 2655 uint_t unit, start_type, id; 2656 2657 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2658 "usb_ac_traverse_all_units: " 2659 "dir=%d type=%d ch=%d cntl=%d all=%d depth=%d", 2660 dir, search_target, channel, control, all_or_one, *depth); 2661 2662 start_type = (dir & AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL : 2663 USB_AUDIO_OUTPUT_TERMINAL; 2664 2665 /* keep track of recursion */ 2666 if ((*depth)++ > USB_AC_MAX_DEPTH) { 2667 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2668 "Unit topology too complex, giving up"); 2669 2670 return (USB_AC_ID_NONE); 2671 } 2672 2673 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2674 /* is this an IT or OT? */ 2675 if (uacp->usb_ac_unit_type[unit] != start_type) { 2676 2677 continue; 2678 } 2679 2680 /* start at streaming term types */ 2681 if (dir & AUDIO_PLAY) { 2682 usb_audio_input_term_descr_t *d = 2683 uacp->usb_ac_units[unit].acu_descriptor; 2684 if (d->wTerminalType != 2685 USB_AUDIO_TERM_TYPE_STREAMING) { 2686 2687 continue; 2688 } 2689 } else { 2690 usb_audio_output_term_descr_t *d = 2691 uacp->usb_ac_units[unit].acu_descriptor; 2692 if (d->wTerminalType != 2693 USB_AUDIO_TERM_TYPE_STREAMING) { 2694 2695 continue; 2696 } 2697 } 2698 2699 /* find units connected to this unit */ 2700 id = usb_ac_traverse_connections(uacp, unit, dir, 2701 search_target, channel, control, all_or_one, count, 2702 arg1, depth, func); 2703 2704 if ((all_or_one == USB_AC_FIND_ONE) && 2705 (id != USB_AC_ID_NONE)) { 2706 unit = id; 2707 2708 break; 2709 } 2710 } 2711 2712 (*depth)--; 2713 2714 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE); 2715 } 2716 2717 2718 /* 2719 * usb_ac_set_monitor_gain_control: 2720 * search for a feature unit between output terminal (OT) and 2721 * input terminal. We are looking for a path between 2722 * for example a microphone and a speaker through a feature unit 2723 * and mixer 2724 */ 2725 static uint_t 2726 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir, 2727 uint_t search_target, uint_t channel, uint_t control, 2728 uint_t all_or_one, uint_t *count, uint_t arg1, 2729 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2730 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2731 { 2732 uint_t unit, id; 2733 uint_t depth = 0; 2734 2735 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2736 "usb_ac_set_monitor_gain_control: dir=%d type=%d ch=%d cntl=%d", 2737 dir, search_target, channel, control); 2738 2739 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2740 usb_audio_output_term_descr_t *d = 2741 uacp->usb_ac_units[unit].acu_descriptor; 2742 2743 /* is this an OT and not stream type? */ 2744 if ((uacp->usb_ac_unit_type[unit] == 2745 USB_AUDIO_OUTPUT_TERMINAL) && 2746 (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) { 2747 2748 /* find units connected to this unit */ 2749 id = usb_ac_traverse_connections(uacp, unit, dir, 2750 search_target, channel, control, all_or_one, count, 2751 arg1, &depth, func); 2752 2753 if ((all_or_one == USB_AC_FIND_ONE) && 2754 (id != USB_AC_ID_NONE)) { 2755 2756 break; 2757 } 2758 } 2759 } 2760 2761 ASSERT(depth == 0); 2762 2763 return (id); 2764 } 2765 2766 2767 /* 2768 * usb_ac_push/pop_unit 2769 * add/remove unit ID to the traverse path 2770 */ 2771 static void 2772 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit) 2773 { 2774 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2775 "usb_ac_push_unit_id: pushing %d at %d", unit, 2776 uacp->usb_ac_traverse_path_index); 2777 2778 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] = unit; 2779 ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit); 2780 } 2781 2782 2783 static void 2784 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit) 2785 { 2786 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2787 "usb_ac_push_unit_id: popping %d at %d", unit, 2788 uacp->usb_ac_traverse_path_index); 2789 2790 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0; 2791 } 2792 2793 2794 /* 2795 * usb_ac_show_traverse_path: 2796 * display entire path, just for debugging 2797 */ 2798 static void 2799 usb_ac_show_traverse_path(usb_ac_state_t *uacp) 2800 { 2801 int i; 2802 2803 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) { 2804 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2805 "traverse path %d: unit=%d type=%d", 2806 i, uacp->usb_ac_traverse_path[i], 2807 uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]); 2808 } 2809 } 2810 2811 2812 /* 2813 * usb_ac_check_path: 2814 * check for a specified type in the traverse path 2815 */ 2816 static int 2817 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type) 2818 { 2819 int i; 2820 2821 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) { 2822 uint_t unit = uacp->usb_ac_traverse_path[i]; 2823 2824 if (uacp->usb_ac_unit_type[unit] == type) { 2825 2826 return (USB_SUCCESS); 2827 } 2828 } 2829 2830 return (USB_FAILURE); 2831 } 2832 2833 2834 /* 2835 * usb_ac_traverse_connections: 2836 * traverse all units and for each unit with the right type, call 2837 * func. If the func returns a success and search == USB_AC_FIND_ONE, 2838 * we are done. If all is set then we continue until we terminate 2839 * and input or output terminal. 2840 * For audio play, we traverse columns starting from an input terminal 2841 * to an output terminal while for record we traverse rows from output 2842 * terminal to input terminal. 2843 */ 2844 static uint_t 2845 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir, 2846 uint_t search_target, uint_t channel, uint_t control, 2847 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth, 2848 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2849 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2850 { 2851 uint_t unit, id; 2852 uint_t done = (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL : 2853 USB_AUDIO_INPUT_TERMINAL; 2854 2855 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2856 "usb_ac_traverse_connections: " 2857 "start=%d dir=%d type=%d ch=%d cntl=%d all=%d depth=%d", 2858 start_unit, dir, search_target, channel, control, 2859 all_or_one, *depth); 2860 2861 /* keep track of recursion depth */ 2862 if ((*depth)++ > USB_AC_MAX_DEPTH) { 2863 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2864 "Unit topology too complex, giving up"); 2865 2866 return (USB_AC_ID_NONE); 2867 } 2868 2869 usb_ac_push_unit_id(uacp, start_unit); 2870 2871 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2872 uint_t entry = (dir & AUDIO_PLAY) ? 2873 uacp->usb_ac_connections[unit][start_unit] : 2874 uacp->usb_ac_connections[start_unit][unit]; 2875 2876 if (entry) { 2877 USB_DPRINTF_L3(PRINT_MASK_ALL, 2878 uacp->usb_ac_log_handle, 2879 "start=%d unit=%d entry=%d type=%d " 2880 "done=%d found=%d", 2881 start_unit, unit, entry, search_target, done, 2882 uacp->usb_ac_unit_type[unit]); 2883 2884 /* did we find a matching type? */ 2885 if (uacp->usb_ac_unit_type[unit] == search_target) { 2886 USB_DPRINTF_L3(PRINT_MASK_ALL, 2887 uacp->usb_ac_log_handle, 2888 "match: dir=%d unit=%d type=%d", 2889 dir, unit, search_target); 2890 2891 /* yes, no apply function to this unit */ 2892 if (func(uacp, unit, dir, channel, 2893 control, arg1, depth) == USB_SUCCESS) { 2894 (*count)++; 2895 2896 USB_DPRINTF_L3(PRINT_MASK_ALL, 2897 uacp->usb_ac_log_handle, 2898 "func returned success, " 2899 "unit=%d all=%d", unit, 2900 all_or_one); 2901 2902 /* are we done? */ 2903 if (all_or_one == USB_AC_FIND_ONE) { 2904 2905 break; 2906 } 2907 } 2908 } 2909 2910 /* did we find the terminating unit */ 2911 if (uacp->usb_ac_unit_type[unit] == done) { 2912 2913 continue; 2914 } 2915 id = usb_ac_traverse_connections(uacp, unit, dir, 2916 search_target, channel, control, 2917 all_or_one, count, arg1, depth, func); 2918 if ((id != USB_AC_ID_NONE) && 2919 (all_or_one == USB_AC_FIND_ONE)) { 2920 unit = id; 2921 2922 break; 2923 } 2924 } 2925 } 2926 2927 (*depth)--; 2928 usb_ac_pop_unit_id(uacp, start_unit); 2929 2930 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE); 2931 } 2932 2933 2934 /* 2935 * Event Management 2936 * 2937 * usb_ac_disconnect_event_cb: 2938 * The device has been disconnected. we either wait for 2939 * detach or a reconnect event. 2940 */ 2941 static int 2942 usb_ac_disconnect_event_cb(dev_info_t *dip) 2943 { 2944 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2945 usb_ac_statep, ddi_get_instance(dip)); 2946 2947 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2948 "usb_ac_disconnect_event_cb: dip=0x%p", (void *)dip); 2949 2950 usb_ac_serialize_access(uacp); 2951 2952 /* setting to disconnect state will prevent replumbing */ 2953 mutex_enter(&uacp->usb_ac_mutex); 2954 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED; 2955 2956 if (uacp->usb_ac_busy_count) { 2957 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2958 "device was disconnected while busy. " 2959 "Data may have been lost"); 2960 } 2961 mutex_exit(&uacp->usb_ac_mutex); 2962 2963 USB_DPRINTF_L3(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2964 "usb_ac_disconnect_event_cb: done"); 2965 2966 usb_ac_release_access(uacp); 2967 2968 return (USB_SUCCESS); 2969 } 2970 2971 2972 /* 2973 * usb_ac_cpr_suspend: 2974 */ 2975 static int 2976 usb_ac_cpr_suspend(dev_info_t *dip) 2977 { 2978 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2979 usb_ac_statep, ddi_get_instance(dip)); 2980 2981 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2982 "usb_ac_cpr_suspend: Begin"); 2983 2984 mutex_enter(&uacp->usb_ac_mutex); 2985 uacp->usb_ac_dev_state = USB_DEV_SUSPENDED; 2986 mutex_exit(&uacp->usb_ac_mutex); 2987 2988 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2989 "usb_ac_cpr_suspend: End"); 2990 2991 return (USB_SUCCESS); 2992 } 2993 2994 2995 2996 /* 2997 * usb_ac_reconnect_event_cb: 2998 * The device was disconnected but this instance not detached, probably 2999 * because the device was busy. 3000 * if the same device, continue with restoring state 3001 * We should either be in the unplumbed state or the plumbed open 3002 * state. 3003 */ 3004 static int 3005 usb_ac_reconnect_event_cb(dev_info_t *dip) 3006 { 3007 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 3008 usb_ac_statep, ddi_get_instance(dip)); 3009 3010 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 3011 "usb_ac_reconnect_event_cb: dip=0x%p", (void *)dip); 3012 3013 mutex_enter(&uacp->usb_ac_mutex); 3014 mutex_exit(&uacp->usb_ac_mutex); 3015 3016 usb_ac_serialize_access(uacp); 3017 3018 /* check the plumbing state */ 3019 mutex_enter(&uacp->usb_ac_mutex); 3020 uacp->usb_ac_busy_count++; 3021 if (uacp->usb_ac_plumbing_state == 3022 USB_AC_STATE_PLUMBED) { 3023 mutex_exit(&uacp->usb_ac_mutex); 3024 usb_ac_restore_device_state(dip, uacp); 3025 mutex_enter(&uacp->usb_ac_mutex); 3026 } 3027 uacp->usb_ac_busy_count--; 3028 3029 if (uacp->usb_ac_busy_count) { 3030 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 3031 "busy device has been reconnected"); 3032 } 3033 mutex_exit(&uacp->usb_ac_mutex); 3034 3035 usb_ac_release_access(uacp); 3036 3037 return (USB_SUCCESS); 3038 } 3039 3040 3041 /* 3042 * usb_ac_cpr_resume: 3043 * Restore device state 3044 */ 3045 static void 3046 usb_ac_cpr_resume(dev_info_t *dip) 3047 { 3048 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 3049 usb_ac_statep, ddi_get_instance(dip)); 3050 3051 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 3052 "usb_ac_cpr_resume"); 3053 3054 usb_ac_serialize_access(uacp); 3055 3056 usb_ac_restore_device_state(dip, uacp); 3057 3058 usb_ac_release_access(uacp); 3059 } 3060 3061 3062 /* 3063 * usb_ac_restore_device_state: 3064 * Set original configuration of the device 3065 * enable wrq - this starts new transactions on the control pipe 3066 */ 3067 static void 3068 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp) 3069 { 3070 usb_ac_power_t *uacpm; 3071 int rval; 3072 3073 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 3074 "usb_ac_restore_device_state:"); 3075 3076 usb_ac_pm_busy_component(uacp); 3077 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 3078 3079 /* Check if we are talking to the same device */ 3080 if (usb_check_same_device(dip, uacp->usb_ac_log_handle, 3081 USB_LOG_L0, PRINT_MASK_ALL, 3082 USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) { 3083 usb_ac_pm_idle_component(uacp); 3084 3085 /* change the device state from suspended to disconnected */ 3086 mutex_enter(&uacp->usb_ac_mutex); 3087 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED; 3088 mutex_exit(&uacp->usb_ac_mutex); 3089 3090 return; 3091 } 3092 3093 mutex_enter(&uacp->usb_ac_mutex); 3094 uacpm = uacp->usb_ac_pm; 3095 if (uacpm) { 3096 if (uacpm->acpm_wakeup_enabled) { 3097 mutex_exit(&uacp->usb_ac_mutex); 3098 3099 if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip, 3100 USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) { 3101 3102 USB_DPRINTF_L4(PRINT_MASK_ATTA, 3103 uacp->usb_ac_log_handle, 3104 "usb_ac_restore_device_state: " 3105 "remote wakeup " 3106 "enable failed, rval=%d", rval); 3107 } 3108 3109 mutex_enter(&uacp->usb_ac_mutex); 3110 } 3111 } 3112 3113 /* prevent unplumbing */ 3114 uacp->usb_ac_busy_count++; 3115 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 3116 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) { 3117 (void) usb_ac_restore_audio_state(uacp, 0); 3118 } 3119 uacp->usb_ac_busy_count--; 3120 mutex_exit(&uacp->usb_ac_mutex); 3121 usb_ac_pm_idle_component(uacp); 3122 } 3123 3124 3125 /* 3126 * usb_ac_am_restore_state 3127 */ 3128 static void 3129 usb_ac_am_restore_state(void *arg) 3130 { 3131 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 3132 3133 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3134 "usb_ac_am_restore_state: Begin"); 3135 3136 usb_ac_serialize_access(uacp); 3137 3138 mutex_enter(&uacp->usb_ac_mutex); 3139 3140 if (uacp->usb_ac_plumbing_state == 3141 USB_AC_STATE_PLUMBED_RESTORING) { 3142 mutex_exit(&uacp->usb_ac_mutex); 3143 3144 /* 3145 * allow hid and usb_as to restore themselves 3146 * (some handshake would have been preferable though) 3147 */ 3148 delay(USB_AC_RESTORE_DELAY); 3149 3150 (void) audio_sup_restore_state(uacp->usb_ac_audiohdl, 3151 AUDIO_ALL_DEVICES, AUDIO_BOTH); 3152 3153 mutex_enter(&uacp->usb_ac_mutex); 3154 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 3155 } 3156 3157 /* allow unplumbing */ 3158 uacp->usb_ac_busy_count--; 3159 mutex_exit(&uacp->usb_ac_mutex); 3160 3161 usb_ac_release_access(uacp); 3162 3163 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3164 "usb_ac_am_restore_state: End"); 3165 } 3166 3167 3168 /* 3169 * usb_ac_restore_audio_state: 3170 */ 3171 static int 3172 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag) 3173 { 3174 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3175 3176 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3177 "usb_ac_restore_audio_state: flag=%d", flag); 3178 3179 switch (uacp->usb_ac_plumbing_state) { 3180 case USB_AC_STATE_PLUMBED: 3181 uacp->usb_ac_plumbing_state = 3182 USB_AC_STATE_PLUMBED_RESTORING; 3183 3184 break; 3185 case USB_AC_STATE_UNPLUMBED: 3186 3187 return (USB_SUCCESS); 3188 case USB_AC_STATE_PLUMBED_RESTORING: 3189 default: 3190 3191 return (USB_FAILURE); 3192 } 3193 3194 /* 3195 * increment busy_count again, it will be decremented 3196 * in usb_ac_am_restore_state 3197 */ 3198 uacp->usb_ac_busy_count++; 3199 3200 if (flag & USB_FLAGS_SLEEP) { 3201 mutex_exit(&uacp->usb_ac_mutex); 3202 usb_ac_am_restore_state((void *)uacp); 3203 mutex_enter(&uacp->usb_ac_mutex); 3204 } else { 3205 mutex_exit(&uacp->usb_ac_mutex); 3206 if (usb_async_req(uacp->usb_ac_dip, 3207 usb_ac_am_restore_state, 3208 (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) { 3209 3210 mutex_enter(&uacp->usb_ac_mutex); 3211 uacp->usb_ac_busy_count--; 3212 3213 return (USB_FAILURE); 3214 } 3215 mutex_enter(&uacp->usb_ac_mutex); 3216 } 3217 3218 return (USB_SUCCESS); 3219 } 3220 3221 3222 /* 3223 * Mixer Callback Management 3224 * NOTE: all mixer callbacks are serialized. we cannot be closed while 3225 * we are in the middle of a callback. There needs to be a 3226 * teardown first. We cannot be unplumbed as long as we are 3227 * still open. 3228 * 3229 * usb_ac_setup: 3230 * Send setup to usb_as if the first setup 3231 * Check power is done in usb_ac_send_as_cmd() 3232 */ 3233 static int 3234 usb_ac_setup(audiohdl_t ahdl, int stream, int flag) 3235 { 3236 int rval = AUDIO_SUCCESS; 3237 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3238 3239 ASSERT(uacp != NULL); 3240 3241 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3242 "usb_ac_setup: Begin ahdl=0x%p, stream=%d, flag=%d", 3243 (void *)ahdl, stream, flag); 3244 3245 mutex_enter(&uacp->usb_ac_mutex); 3246 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3247 mutex_exit(&uacp->usb_ac_mutex); 3248 3249 return (AUDIO_FAILURE); 3250 } 3251 mutex_exit(&uacp->usb_ac_mutex); 3252 3253 usb_ac_serialize_access(uacp); 3254 3255 if (flag & AUDIO_PLAY) { 3256 rval = usb_ac_do_setup(ahdl, stream, AUDIO_PLAY); 3257 } 3258 3259 if ((rval == USB_SUCCESS) && (flag & AUDIO_RECORD)) { 3260 rval = usb_ac_do_setup(ahdl, stream, AUDIO_RECORD); 3261 } 3262 3263 usb_ac_release_access(uacp); 3264 3265 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3266 "usb_ac_setup: rval=%d", rval); 3267 3268 return ((rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE); 3269 } 3270 3271 3272 /* 3273 * usb_ac_do_setup: 3274 * Wrapper function for usb_ac_setup which can be called 3275 * either from audio framework for usb_ac_set_format 3276 */ 3277 static int 3278 usb_ac_do_setup(audiohdl_t ahdl, int stream, int flag) 3279 { 3280 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3281 usb_ac_plumbed_t *plumb_infop = NULL; 3282 usb_ac_streams_info_t *streams_infop = NULL; 3283 int dir; 3284 3285 ASSERT(uacp != NULL); 3286 3287 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3288 "usb_ac_do_setup: Begin ahdl=0x%p, stream=%d, flag=%d", 3289 (void *)ahdl, stream, flag); 3290 3291 mutex_enter(&uacp->usb_ac_mutex); 3292 3293 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3294 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3295 ASSERT(plumb_infop != NULL); 3296 3297 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3298 ASSERT(streams_infop != NULL); 3299 3300 /* 3301 * Handle multiple setup calls. Pass the setup call to usb_as only 3302 * the first time so isoc pipe will be opened only once 3303 */ 3304 if (streams_infop->acs_setup_teardown_count++) { 3305 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3306 "usb_ac_do_setup: more than one setup, cnt=%d", 3307 streams_infop->acs_setup_teardown_count); 3308 3309 mutex_exit(&uacp->usb_ac_mutex); 3310 3311 return (USB_SUCCESS); 3312 } 3313 3314 /* Send setup command to usb_as */ 3315 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SETUP, 0) != 3316 USB_SUCCESS) { 3317 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3318 "usb_ac_do_setup: failure"); 3319 3320 streams_infop->acs_setup_teardown_count--; 3321 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3322 3323 mutex_exit(&uacp->usb_ac_mutex); 3324 3325 return (USB_FAILURE); 3326 } 3327 3328 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3329 3330 mutex_exit(&uacp->usb_ac_mutex); 3331 3332 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3333 "usb_ac_do_setup: End"); 3334 3335 return (USB_SUCCESS); 3336 } 3337 3338 3339 /* 3340 * usb_ac_teardown: 3341 * Send teardown to usb_as if the last teardown 3342 * Check power is done in usb_ac_send_as_cmd() 3343 * NOTE: allow teardown when disconnected 3344 */ 3345 static void 3346 usb_ac_teardown(audiohdl_t ahdl, int stream, int flag) 3347 { 3348 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3349 3350 ASSERT(uacp != NULL); 3351 3352 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3353 "usb_ac_teardown: Begin ahdl=0x%p, stream=%d", 3354 (void *)ahdl, stream); 3355 3356 usb_ac_serialize_access(uacp); 3357 3358 if (flag & AUDIO_PLAY) { 3359 usb_ac_do_teardown(ahdl, stream, AUDIO_PLAY); 3360 } 3361 3362 if (flag & AUDIO_RECORD) { 3363 usb_ac_do_teardown(ahdl, stream, AUDIO_RECORD); 3364 } 3365 3366 usb_ac_release_access(uacp); 3367 3368 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3369 "usb_ac_teardown: End"); 3370 } 3371 3372 3373 /* 3374 * usb_ac_do_teardown() 3375 * Check power is done in usb_ac_send_as_cmd() 3376 */ 3377 static void 3378 usb_ac_do_teardown(audiohdl_t ahdl, int stream, int flag) 3379 { 3380 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3381 usb_ac_plumbed_t *plumb_infop = NULL; 3382 usb_ac_streams_info_t *streams_infop = NULL; 3383 int dir; 3384 3385 ASSERT(uacp != NULL); 3386 3387 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3388 "usb_ac_do_teardown: Begin ahdl=0x%p, stream=%d", 3389 (void *)ahdl, stream); 3390 3391 mutex_enter(&uacp->usb_ac_mutex); 3392 3393 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3394 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3395 ASSERT(plumb_infop != NULL); 3396 3397 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3398 ASSERT(streams_infop != NULL); 3399 3400 /* There should be at least one matching setup call */ 3401 ASSERT(streams_infop->acs_setup_teardown_count); 3402 3403 /* 3404 * Handle multiple setup/teardown calls. Pass the call to usb_as 3405 * only this is the last teardown so that isoc pipe is closed 3406 * only once 3407 */ 3408 if (--(streams_infop->acs_setup_teardown_count)) { 3409 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3410 "usb_ac_do_teardown: more than one setup/teardown, " 3411 "cnt=%d", 3412 streams_infop->acs_setup_teardown_count); 3413 3414 mutex_exit(&uacp->usb_ac_mutex); 3415 3416 return; 3417 } 3418 3419 /* Send teardown command to usb_as */ 3420 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_TEARDOWN, 3421 (void *)NULL) != USB_SUCCESS) { 3422 3423 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3424 "usb_ac_do_teardown: failure"); 3425 3426 streams_infop->acs_setup_teardown_count++; 3427 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3428 3429 mutex_exit(&uacp->usb_ac_mutex); 3430 3431 return; 3432 } 3433 3434 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3435 3436 mutex_exit(&uacp->usb_ac_mutex); 3437 3438 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3439 "usb_ac_do_teardown: End"); 3440 } 3441 3442 3443 /* 3444 * usb_ac_set_config: 3445 * This routine will send control commands to get the max 3446 * and min gain balance, calculate the gain to be set from the 3447 * arguments and send another control command to set it. 3448 * Check power is done here since we will access the default pipe 3449 */ 3450 static int 3451 usb_ac_set_config(audiohdl_t ahdl, int stream, int command, int flag, 3452 int arg1, int arg2) 3453 { 3454 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3455 char *what; 3456 int rval = AUDIO_FAILURE; 3457 uint_t channel; 3458 uchar_t n_channels = 0; 3459 uint_t dir, count; 3460 short muteval; 3461 3462 ASSERT(uacp != NULL); 3463 3464 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3465 "usb_ac_set_config: Begin ahdl=0x%p\n\t" 3466 "stream=%d, cmd=%d, flag=%d, arg1=%d, arg2=%d", 3467 (void *)ahdl, stream, command, flag, arg1, arg2); 3468 3469 mutex_enter(&uacp->usb_ac_mutex); 3470 if (uacp->usb_ac_plumbing_state < USB_AC_STATE_PLUMBED) { 3471 mutex_exit(&uacp->usb_ac_mutex); 3472 3473 return (AUDIO_FAILURE); 3474 } 3475 3476 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3477 mutex_exit(&uacp->usb_ac_mutex); 3478 3479 return (AUDIO_FAILURE); 3480 } 3481 mutex_exit(&uacp->usb_ac_mutex); 3482 usb_ac_serialize_access(uacp); 3483 mutex_enter(&uacp->usb_ac_mutex); 3484 3485 switch (command) { 3486 case AM_SET_GAIN: 3487 /* 3488 * Set the gain for a channel. The audio mixer calculates the 3489 * impact, if any, on the channel's gain. 3490 * 3491 * 0 <= gain <= AUDIO_MAX_GAIN 3492 * 3493 * arg1 --> gain 3494 * arg2 --> channel #, 0 == left, 1 == right 3495 */ 3496 what = "gain"; 3497 channel = ++arg2; 3498 ASSERT(flag != AUDIO_BOTH); 3499 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3500 3501 /* 3502 * We service the set_config command when the device is 3503 * plumbed and opened. 3504 */ 3505 n_channels = usb_ac_get_curr_n_channels(uacp, dir); 3506 3507 if (channel > n_channels) { 3508 USB_DPRINTF_L2(PRINT_MASK_ALL, 3509 uacp->usb_ac_log_handle, 3510 "usb_ac_set_config: channel(%d) passed is " 3511 " > n_channels(%d)", channel, n_channels); 3512 3513 goto done; 3514 } 3515 count = 0; 3516 (void) usb_ac_set_control(uacp, dir, 3517 USB_AUDIO_FEATURE_UNIT, channel, 3518 USB_AUDIO_VOLUME_CONTROL, 3519 USB_AC_FIND_ALL, &count, arg1, usb_ac_set_gain); 3520 3521 /* 3522 * If feature unit id could not be found, it probably means 3523 * volume/gain control is not available for this device. 3524 * and we just return success if we haven't completed 3525 * the registration with the mixer yet 3526 */ 3527 if (count == 0) { 3528 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3529 "mixer=%d, no featureID, arg1=%d", 3530 uacp->usb_ac_registered_with_mixer, arg1); 3531 rval = (uacp->usb_ac_registered_with_mixer == 0) ? 3532 AUDIO_SUCCESS : AUDIO_FAILURE; 3533 } else { 3534 rval = AUDIO_SUCCESS; 3535 } 3536 3537 break; 3538 case AM_SET_PORT: 3539 what = "port"; 3540 ASSERT(flag != AUDIO_BOTH); 3541 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3542 3543 rval = usb_ac_set_port(uacp, dir, arg1); 3544 rval = (rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE; 3545 3546 break; 3547 case AM_SET_MONITOR_GAIN: 3548 what = "monitor gain"; 3549 channel = ++arg2; 3550 dir = AUDIO_RECORD; 3551 3552 /* 3553 * We service the set_config command when the device is 3554 * plumbed and opened. 3555 */ 3556 n_channels = usb_ac_get_curr_n_channels(uacp, dir); 3557 3558 if (channel > n_channels) { 3559 USB_DPRINTF_L2(PRINT_MASK_ALL, 3560 uacp->usb_ac_log_handle, 3561 "usb_ac_set_config: channel(%d) passed is " 3562 " > n_channels(%d)", channel, n_channels); 3563 3564 goto done; 3565 } 3566 count = 0; 3567 (void) usb_ac_set_monitor_gain_control(uacp, dir, 3568 USB_AUDIO_INPUT_TERMINAL, channel, 3569 USB_AUDIO_VOLUME_CONTROL, 3570 USB_AC_FIND_ALL, &count, arg1, 3571 usb_ac_set_monitor_gain); 3572 3573 /* 3574 * always return success since we told the mixer 3575 * we always support this and sdtaudiocontrol displays 3576 * monitor gain regardless. 3577 */ 3578 rval = AUDIO_SUCCESS; 3579 3580 break; 3581 case AM_OUTPUT_MUTE: 3582 what = "mute"; 3583 ASSERT(flag != AUDIO_BOTH); 3584 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3585 3586 /* 3587 * arg1 != 0 --> mute 3588 * arg1 == 0 --> unmute 3589 * arg2 --> not used 3590 */ 3591 muteval = (arg1 == 0) ? USB_AUDIO_MUTE_OFF : 3592 USB_AUDIO_MUTE_ON; 3593 count = 0; 3594 (void) usb_ac_set_control(uacp, dir, 3595 USB_AUDIO_FEATURE_UNIT, 0, 3596 USB_AUDIO_MUTE_CONTROL, 3597 USB_AC_FIND_ALL, &count, muteval, 3598 usb_ac_set_mute); 3599 3600 rval = (count == 0) ? AUDIO_FAILURE : AUDIO_SUCCESS; 3601 3602 break; 3603 case AM_MIC_BOOST: 3604 what = "mic boost"; 3605 rval = AUDIO_SUCCESS; 3606 break; 3607 case AM_SET_GAIN_BAL: 3608 what = "set gain bal"; 3609 rval = AUDIO_FAILURE; 3610 break; 3611 default: 3612 what = "unknown"; 3613 rval = AUDIO_FAILURE; 3614 } 3615 3616 done: 3617 mutex_exit(&uacp->usb_ac_mutex); 3618 3619 /* Now it's safe to release access to other routines */ 3620 usb_ac_release_access(uacp); 3621 3622 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3623 "usb_ac_set_config: %s done, rval=%d", what, rval); 3624 3625 return (rval); 3626 } 3627 3628 3629 /* 3630 * usb_ac_set_monitor_gain: 3631 * called for each output terminal which supports 3632 * from usb_ac_traverse_connections 3633 */ 3634 static int 3635 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit, 3636 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth) 3637 { 3638 usb_audio_output_term_descr_t *d = 3639 uacp->usb_ac_units[unit].acu_descriptor; 3640 3641 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3642 "usb_ac_set_monitor_gain: "); 3643 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3644 "id=%d dir=%d ch=%d cntl=%d gain=%d type=%d term type=0x%x", 3645 unit, dir, channel, control, gain, 3646 uacp->usb_ac_unit_type[unit], d->wTerminalType); 3647 3648 /* log how we got here */ 3649 usb_ac_push_unit_id(uacp, unit); 3650 usb_ac_show_traverse_path(uacp); 3651 usb_ac_pop_unit_id(uacp, unit); 3652 3653 /* we only care about the ITs connected to real hw inputs */ 3654 switch (d->wTerminalType) { 3655 case USB_AUDIO_TERM_TYPE_STREAMING: 3656 3657 return (USB_FAILURE); 3658 3659 case USB_AUDIO_TERM_TYPE_DT_MICROPHONE: 3660 case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE: 3661 case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE: 3662 case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY: 3663 case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY: 3664 default: 3665 3666 break; 3667 } 3668 3669 /* 3670 * we can only do this if the microphone is mixed into the 3671 * audio output so look for a mixer first 3672 */ 3673 if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) == 3674 USB_SUCCESS) { 3675 int i, id; 3676 3677 /* now look for a feature unit */ 3678 for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0; 3679 i--) { 3680 id = uacp->usb_ac_traverse_path[i]; 3681 3682 switch (uacp->usb_ac_unit_type[id]) { 3683 case USB_AUDIO_MIXER_UNIT: 3684 3685 /* the FU should be before the mixer */ 3686 return (USB_FAILURE); 3687 3688 case USB_AUDIO_FEATURE_UNIT: 3689 /* 3690 * now set the volume 3691 */ 3692 if (usb_ac_set_gain(uacp, id, dir, channel, 3693 control, gain, depth) != USB_SUCCESS) { 3694 3695 /* try master channel */ 3696 if (usb_ac_set_gain(uacp, id, dir, 3697 0, control, gain, depth) != 3698 USB_SUCCESS) { 3699 3700 return (USB_FAILURE); 3701 } 3702 } 3703 3704 return (USB_SUCCESS); 3705 3706 default: 3707 continue; 3708 } 3709 } 3710 } 3711 3712 return (USB_FAILURE); 3713 } 3714 3715 3716 /* 3717 * usb_ac_set_gain is called for each feature unit which supports 3718 * the requested controls from usb_ac_traverse_connections 3719 * we still need to check whether this unit supports the requested 3720 * control. 3721 */ 3722 static int 3723 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID, 3724 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth) 3725 { 3726 short max, min, current; 3727 3728 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3729 "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d", 3730 featureID, dir, channel, control, gain); 3731 3732 if (usb_ac_feature_unit_check(uacp, featureID, 3733 dir, channel, control, gain, depth) != USB_SUCCESS) { 3734 3735 return (USB_FAILURE); 3736 } 3737 3738 if ((max = usb_ac_get_maxmin_volume(uacp, channel, 3739 USB_AUDIO_GET_MAX, dir, featureID)) == USB_FAILURE) { 3740 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3741 "usb_ac_set_gain: getting max gain failed"); 3742 3743 return (USB_FAILURE); 3744 } 3745 3746 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3747 "usb_ac_set_gain: channel %d, max=%d", channel, max); 3748 3749 if ((min = usb_ac_get_maxmin_volume(uacp, channel, 3750 USB_AUDIO_GET_MIN, dir, featureID)) == USB_FAILURE) { 3751 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3752 "usb_ac_set_gain: getting min gain failed"); 3753 3754 return (USB_FAILURE); 3755 } 3756 3757 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3758 "usb_ac_set_gain: channel=%d, min=%d", channel, min); 3759 3760 if ((current = usb_ac_get_maxmin_volume(uacp, channel, 3761 USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) { 3762 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3763 "usb_ac_set_gain: getting cur gain failed"); 3764 3765 return (USB_FAILURE); 3766 } 3767 3768 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3769 "usb_ac_set_gain: channel=%d, cur=%d", channel, current); 3770 3771 /* 3772 * Set the gain for a channel. The audio mixer calculates the 3773 * impact, if any, on the channel's gain. 3774 * 3775 * 0 <= gain <= AUDIO_MAX_GAIN 3776 * 3777 * channel #, 0 == left, 1 == right 3778 */ 3779 3780 if (gain == 0) { 3781 gain = USB_AUDIO_VOLUME_SILENCE; 3782 } else { 3783 gain = max - ((max - min) * (0x100 - gain))/0x100; 3784 } 3785 3786 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3787 "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d", 3788 channel, dir, max, min, gain); 3789 3790 if (usb_ac_set_volume(uacp, channel, gain, dir, 3791 featureID) != USB_SUCCESS) { 3792 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3793 "usb_ac_set_gain: setting volume failed"); 3794 3795 return (USB_FAILURE); 3796 } 3797 3798 /* just curious, read it back, device may round up/down */ 3799 if ((current = usb_ac_get_maxmin_volume(uacp, channel, 3800 USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) { 3801 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3802 "usb_ac_set_gain: getting cur gain failed"); 3803 } 3804 3805 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3806 "usb_ac_set_gain done: " 3807 "id=%d channel=%d, cur=%d gain=%d", featureID, channel, 3808 (ushort_t)current, (ushort_t)gain); 3809 3810 return (USB_SUCCESS); 3811 } 3812 3813 3814 /* 3815 * usb_ac_set_format 3816 * This mixer callback initiates a command to be sent to 3817 * usb_as to select an alternate with the passed characteristics 3818 * and also to set the sample frequency. 3819 * Note that this may be called when a playing is going on in 3820 * the streaming interface. To handle that, first stop 3821 * playing/recording, close the pipe by sending a teardown 3822 * command, send the set_format command down and then reopen 3823 * the pipe. Note : (1) audio framework will restart play/record 3824 * after a set_format command. (2) Check power is done in 3825 * usb_ac_send_as_cmd(). 3826 */ 3827 static int 3828 usb_ac_set_format(audiohdl_t ahdl, int stream, int flag, 3829 int sample, int channels, int precision, int encoding) 3830 { 3831 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3832 usb_audio_formats_t *format; 3833 usb_audio_formats_t old_format; 3834 usb_ac_plumbed_t *plumb_infop; 3835 usb_ac_streams_info_t *streams_infop = NULL; 3836 int old_setup_teardown_count; 3837 int dir; 3838 int rval; 3839 3840 ASSERT(uacp != NULL); 3841 3842 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3843 "usb_ac_set_format: Begin ahdl=0x%p, stream=%d, flag=%d, " 3844 "sr=%d, chnls=%d, prec=%d, enc=%d", (void *)ahdl, stream, flag, 3845 sample, channels, precision, encoding); 3846 3847 mutex_enter(&uacp->usb_ac_mutex); 3848 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3849 mutex_exit(&uacp->usb_ac_mutex); 3850 3851 return (AUDIO_FAILURE); 3852 } 3853 mutex_exit(&uacp->usb_ac_mutex); 3854 3855 usb_ac_serialize_access(uacp); 3856 3857 ASSERT(flag != AUDIO_BOTH); 3858 3859 mutex_enter(&uacp->usb_ac_mutex); 3860 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3861 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3862 if (plumb_infop == NULL) { 3863 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3864 "usb_ac_set_format: no plumb info"); 3865 mutex_exit(&uacp->usb_ac_mutex); 3866 3867 usb_ac_release_access(uacp); 3868 3869 return (AUDIO_FAILURE); 3870 } 3871 3872 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3873 ASSERT(streams_infop != NULL); 3874 3875 /* isoc pipe not open and playing is not in progress */ 3876 if (streams_infop->acs_setup_teardown_count == 0) { 3877 3878 mutex_exit(&uacp->usb_ac_mutex); 3879 3880 rval = usb_ac_send_format_cmd(ahdl, stream, dir, sample, 3881 channels, precision, encoding); 3882 3883 usb_ac_release_access(uacp); 3884 3885 return ((rval == USB_SUCCESS) ? 3886 AUDIO_SUCCESS : AUDIO_FAILURE); 3887 } 3888 3889 /* isoc pipe is open and playing might be in progress */ 3890 format = &streams_infop->acs_ac_to_as_req.acr_curr_format; 3891 3892 /* Keep a copy of the old format */ 3893 bcopy((void *)format, (void *)&old_format, 3894 sizeof (usb_audio_formats_t)); 3895 3896 ASSERT(streams_infop->acs_setup_teardown_count != 0); 3897 3898 old_setup_teardown_count = streams_infop->acs_setup_teardown_count; 3899 streams_infop->acs_setup_teardown_count = 1; 3900 3901 mutex_exit(&uacp->usb_ac_mutex); 3902 3903 if (dir == AUDIO_PLAY) { 3904 usb_ac_do_pause_play(ahdl, stream); 3905 } else if (dir == AUDIO_RECORD) { 3906 usb_ac_do_stop_record(ahdl, stream); 3907 } 3908 3909 /* This blocks until the current isoc xfer is over */ 3910 usb_ac_do_teardown(ahdl, stream, dir); 3911 3912 if (usb_ac_send_format_cmd(ahdl, stream, dir, sample, 3913 channels, precision, encoding) != USB_SUCCESS) { 3914 /* 3915 * Setting new alternate has failed, try restoring 3916 * old one. 3917 * If there is a bandwidth failure, hang around 3918 * till bandwidth is available. Also we know that 3919 * there is a matching alternate, so that can't fail. 3920 */ 3921 if (usb_ac_send_format_cmd(ahdl, stream, dir, 3922 old_format.fmt_sr, old_format.fmt_chns, 3923 old_format.fmt_precision, old_format.fmt_encoding) == 3924 USB_FAILURE) { 3925 3926 /* We closed the pipe; reopen it */ 3927 (void) usb_ac_do_setup(ahdl, stream, dir); 3928 3929 mutex_enter(&uacp->usb_ac_mutex); 3930 streams_infop->acs_setup_teardown_count = 3931 old_setup_teardown_count; 3932 mutex_exit(&uacp->usb_ac_mutex); 3933 3934 usb_ac_release_access(uacp); 3935 3936 return (AUDIO_FAILURE); 3937 } 3938 } 3939 3940 /* This should block until successful */ 3941 (void) usb_ac_do_setup(ahdl, stream, dir); 3942 3943 mutex_enter(&uacp->usb_ac_mutex); 3944 streams_infop->acs_setup_teardown_count = old_setup_teardown_count; 3945 mutex_exit(&uacp->usb_ac_mutex); 3946 3947 usb_ac_release_access(uacp); 3948 3949 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3950 "usb_ac_set_format: End"); 3951 3952 return (AUDIO_SUCCESS); 3953 } 3954 3955 3956 /* 3957 * usb_ac_get_curr_n_channels: 3958 * Return no. of channels from the current format table 3959 */ 3960 static int 3961 usb_ac_get_curr_n_channels(usb_ac_state_t *uacp, int dir) 3962 { 3963 usb_audio_formats_t *cur_fmt = usb_ac_get_curr_format(uacp, dir); 3964 3965 return (cur_fmt->fmt_chns); 3966 } 3967 3968 3969 /* 3970 * usb_ac_get_cur_format: 3971 * Get format for the current alternate 3972 */ 3973 static usb_audio_formats_t * 3974 usb_ac_get_curr_format(usb_ac_state_t *uacp, int dir) 3975 { 3976 usb_ac_plumbed_t *plumb_infop; 3977 usb_ac_streams_info_t *streams_infop = NULL; 3978 3979 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3980 3981 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3982 if (plumb_infop == NULL) { 3983 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3984 "usb_ac_get_curr_format: no plumb info"); 3985 3986 return (NULL); 3987 } 3988 3989 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3990 ASSERT(streams_infop != NULL); 3991 3992 return (&streams_infop->acs_cur_fmt); 3993 } 3994 3995 3996 /* 3997 * usb_ac_send_format_cmd 3998 * Sets format and get alternate setting that matches with 3999 * the format from the usb_as playing or recording interface 4000 * Send the set sample freq command down to usb_as. 4001 */ 4002 static int 4003 usb_ac_send_format_cmd(audiohdl_t ahdl, int stream, int dir, 4004 int sample, int channels, int precision, int encoding) 4005 { 4006 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4007 usb_audio_formats_t *format; 4008 usb_ac_plumbed_t *plumb_infop = NULL; 4009 usb_ac_streams_info_t *streams_infop = NULL; 4010 4011 ASSERT(uacp != NULL); 4012 4013 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4014 "usb_ac_send_format_cmd: Begin ahdl=0x%p, stream=%d, dir=%d, " 4015 "sr=%d, chnls=%d, prec=%d, enc=%d", (void *)ahdl, stream, dir, 4016 sample, channels, precision, encoding); 4017 4018 mutex_enter(&uacp->usb_ac_mutex); 4019 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4020 mutex_exit(&uacp->usb_ac_mutex); 4021 4022 return (USB_FAILURE); 4023 } 4024 4025 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 4026 ASSERT(plumb_infop); 4027 4028 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4029 ASSERT(streams_infop != NULL); 4030 4031 ASSERT(dir == AUDIO_PLAY || dir == AUDIO_RECORD); 4032 streams_infop->acs_ac_to_as_req.acr_curr_dir = dir; 4033 4034 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4035 "usb_ac_send_format_cmd: plumb_infop=0x%p, streams_infop=0x%p", 4036 (void *)plumb_infop, (void *)streams_infop); 4037 4038 format = &(streams_infop->acs_ac_to_as_req.acr_curr_format); 4039 bzero(format, sizeof (usb_audio_formats_t)); 4040 4041 /* save format info */ 4042 format->fmt_sr = (uint_t)sample; 4043 format->fmt_chns = (uchar_t)channels; 4044 format->fmt_precision = (uchar_t)precision; 4045 format->fmt_encoding = (uchar_t)encoding; 4046 4047 streams_infop->acs_cur_fmt = *format; 4048 4049 /* 4050 * Set format for the streaming interface with lower write queue 4051 * This boils down to set_alternate interface command in 4052 * usb_as and the reply mp contains the currently active 4053 * alternate number that is stored in the as_req structure 4054 */ 4055 if (usb_ac_send_as_cmd(uacp, plumb_infop, 4056 USB_AUDIO_SET_FORMAT, format) != USB_SUCCESS) { 4057 USB_DPRINTF_L2(PRINT_MASK_ALL, 4058 uacp->usb_ac_log_handle, 4059 "usb_ac_send_format_cmd: failed"); 4060 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4061 mutex_exit(&uacp->usb_ac_mutex); 4062 4063 return (USB_FAILURE); 4064 } else { 4065 /* alternate number stored and reply mp freed */ 4066 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4067 } 4068 4069 /* Set the sample rate */ 4070 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SET_SAMPLE_FREQ, 4071 &sample) != USB_SUCCESS) { 4072 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4073 "usb_ac_send_format_cmd: setting format failed"); 4074 4075 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4076 mutex_exit(&uacp->usb_ac_mutex); 4077 4078 return (USB_FAILURE); 4079 } 4080 4081 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4082 4083 mutex_exit(&uacp->usb_ac_mutex); 4084 4085 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4086 "usb_ac_send_format_cmd: End"); 4087 4088 return (USB_SUCCESS); 4089 } 4090 4091 4092 /* 4093 * usb_ac_start_play 4094 * Send a start_play command down to usb_as 4095 * Check power is done in usb_ac_send_as_cmd() 4096 */ 4097 static int 4098 usb_ac_start_play(audiohdl_t ahdl, int stream) 4099 { 4100 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4101 usb_audio_formats_t *cur_fmt; 4102 usb_ac_plumbed_t *plumb_infop = NULL; 4103 int dir, samples; 4104 usb_audio_play_req_t play_req; 4105 usb_ac_streams_info_t *streams_infop = NULL; 4106 4107 ASSERT(uacp != NULL); 4108 4109 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4110 "usb_ac_start_play: Begin ahdl=0x%p, stream=%d", 4111 (void *)ahdl, stream); 4112 4113 mutex_enter(&uacp->usb_ac_mutex); 4114 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4115 mutex_exit(&uacp->usb_ac_mutex); 4116 4117 return (AUDIO_FAILURE); 4118 } 4119 mutex_exit(&uacp->usb_ac_mutex); 4120 4121 usb_ac_serialize_access(uacp); 4122 4123 mutex_enter(&uacp->usb_ac_mutex); 4124 4125 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY); 4126 ASSERT(plumb_infop); 4127 4128 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4129 ASSERT(streams_infop != NULL); 4130 4131 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4132 "usb_ac_start_play: plumb_infop=0x%p, streams_infop=0x%p", 4133 (void *)plumb_infop, (void *)streams_infop); 4134 4135 dir = streams_infop->acs_ac_to_as_req.acr_curr_dir; 4136 ASSERT(dir == AUDIO_PLAY); 4137 4138 cur_fmt = &streams_infop->acs_ac_to_as_req.acr_curr_format; 4139 4140 /* Check for continuous sample rate done in usb_as */ 4141 samples = cur_fmt->fmt_sr * cur_fmt->fmt_chns / 4142 uacp->usb_ac_am_ad_info.ad_play.ad_int_rate; 4143 if (samples & cur_fmt->fmt_chns) { 4144 samples++; 4145 } 4146 4147 play_req.up_samples = samples; 4148 play_req.up_handle = ahdl; 4149 4150 /* Send setup command to usb_as */ 4151 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_PLAY, 4152 (void *)&play_req) != USB_SUCCESS) { 4153 4154 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4155 "usb_ac_start_play: failure"); 4156 4157 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4158 mutex_exit(&uacp->usb_ac_mutex); 4159 4160 usb_ac_release_access(uacp); 4161 4162 return (AUDIO_FAILURE); 4163 } 4164 4165 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4166 mutex_exit(&uacp->usb_ac_mutex); 4167 4168 usb_ac_release_access(uacp); 4169 4170 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4171 "usb_ac_start_play: End"); 4172 4173 return (AUDIO_SUCCESS); 4174 } 4175 4176 4177 /* 4178 * usb_ac_pause_play: 4179 * Wrapper function for usb_ac_do_pause_play and gets 4180 * called from mixer framework. 4181 */ 4182 static void 4183 usb_ac_pause_play(audiohdl_t ahdl, int stream) 4184 { 4185 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4186 4187 ASSERT(uacp != NULL); 4188 4189 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4190 "usb_ac_pause_play: Begin ahdl=0x%p, stream=%d", 4191 (void *)ahdl, stream); 4192 4193 mutex_enter(&uacp->usb_ac_mutex); 4194 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4195 mutex_exit(&uacp->usb_ac_mutex); 4196 4197 return; 4198 } 4199 mutex_exit(&uacp->usb_ac_mutex); 4200 4201 usb_ac_serialize_access(uacp); 4202 usb_ac_do_pause_play(ahdl, stream); 4203 usb_ac_release_access(uacp); 4204 4205 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4206 "usb_ac_pause_play: End"); 4207 } 4208 4209 /* 4210 * usb_ac_do_pause_play: 4211 * Send a pause_play command to usb_as. 4212 * Check power is done in usb_ac_send_as_cmd() 4213 */ 4214 static void 4215 usb_ac_do_pause_play(audiohdl_t ahdl, int stream) 4216 { 4217 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4218 usb_ac_plumbed_t *plumb_infop = NULL; 4219 usb_ac_streams_info_t *streams_infop = NULL; 4220 4221 ASSERT(uacp != NULL); 4222 4223 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4224 "usb_ac_do_pause_play: Begin ahdl=0x%p, stream=%d", 4225 (void *)ahdl, stream); 4226 4227 mutex_enter(&uacp->usb_ac_mutex); 4228 4229 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY); 4230 ASSERT(plumb_infop); 4231 4232 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4233 ASSERT(streams_infop != NULL); 4234 4235 /* Send setup command to usb_as */ 4236 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_PAUSE_PLAY, 4237 (void *)NULL) != USB_SUCCESS) { 4238 4239 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4240 "usb_ac_do_pause_play: failure"); 4241 4242 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4243 } 4244 4245 mutex_exit(&uacp->usb_ac_mutex); 4246 4247 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4248 "usb_ac_do_pause_play: End"); 4249 } 4250 4251 4252 /* 4253 * usb_ac_stop_play: 4254 * Wrapper function for usb_ac_pause_play and gets 4255 * called from mixer framework. 4256 */ 4257 static void 4258 usb_ac_stop_play(audiohdl_t ahdl, int stream) 4259 { 4260 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4261 4262 ASSERT(uacp != NULL); 4263 4264 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4265 "usb_ac_stop_play: Begin ahdl=0x%p, stream=%d", 4266 (void *)ahdl, stream); 4267 4268 usb_ac_pause_play(ahdl, stream); 4269 4270 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4271 "usb_ac_stop_play: End"); 4272 } 4273 4274 4275 /* 4276 * usb_ac_start_record: 4277 * Sends a start record command down to usb_as. 4278 * Check power is done in usb_ac_send_as_cmd() 4279 */ 4280 static int 4281 usb_ac_start_record(audiohdl_t ahdl, int stream) 4282 { 4283 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4284 usb_ac_plumbed_t *plumb_infop = NULL; 4285 usb_ac_streams_info_t *streams_infop = NULL; 4286 4287 ASSERT(uacp != NULL); 4288 4289 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4290 "usb_ac_start_record: Begin ahdl=0x%p, stream=%d", 4291 (void *)ahdl, stream); 4292 4293 mutex_enter(&uacp->usb_ac_mutex); 4294 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4295 mutex_exit(&uacp->usb_ac_mutex); 4296 4297 return (AUDIO_FAILURE); 4298 } 4299 mutex_exit(&uacp->usb_ac_mutex); 4300 4301 usb_ac_serialize_access(uacp); 4302 4303 mutex_enter(&uacp->usb_ac_mutex); 4304 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD); 4305 ASSERT(plumb_infop); 4306 4307 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4308 ASSERT(streams_infop != NULL); 4309 4310 /* Send setup command to usb_as */ 4311 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_RECORD, 4312 (void *)&ahdl) != USB_SUCCESS) { 4313 4314 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4315 "usb_ac_start_record: failure"); 4316 4317 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4318 mutex_exit(&uacp->usb_ac_mutex); 4319 4320 usb_ac_release_access(uacp); 4321 4322 return (AUDIO_FAILURE); 4323 } 4324 4325 mutex_exit(&uacp->usb_ac_mutex); 4326 4327 usb_ac_release_access(uacp); 4328 4329 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4330 "usb_ac_start_record: End"); 4331 4332 return (AUDIO_SUCCESS); 4333 } 4334 4335 4336 /* 4337 * usb_ac_stop_record: 4338 * Wrapper function for usb_ac_do_stop_record and is 4339 * called form mixer framework. 4340 */ 4341 static void 4342 usb_ac_stop_record(audiohdl_t ahdl, int stream) 4343 { 4344 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4345 4346 ASSERT(uacp != NULL); 4347 4348 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4349 "usb_ac_stop_record: Begin ahdl=0x%p, stream=%d", 4350 (void *)ahdl, stream); 4351 4352 usb_ac_serialize_access(uacp); 4353 usb_ac_do_stop_record(ahdl, stream); 4354 usb_ac_release_access(uacp); 4355 4356 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4357 "usb_ac_stop_record: End"); 4358 } 4359 4360 4361 /* 4362 * usb_ac_do_stop_record: 4363 * Sends a stop_record command down. 4364 * Check power is done in usb_ac_send_as_cmd() 4365 */ 4366 static void 4367 usb_ac_do_stop_record(audiohdl_t ahdl, int stream) 4368 { 4369 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4370 usb_ac_plumbed_t *plumb_infop = NULL; 4371 usb_ac_streams_info_t *streams_infop = NULL; 4372 4373 ASSERT(uacp != NULL); 4374 4375 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4376 "usb_ac_do_stop_record: Begin ahdl=0x%p, stream=%d", 4377 (void *)ahdl, stream); 4378 4379 mutex_enter(&uacp->usb_ac_mutex); 4380 4381 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD); 4382 ASSERT(plumb_infop != NULL); 4383 4384 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4385 ASSERT(streams_infop != NULL); 4386 4387 /* Send setup command to usb_as */ 4388 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_STOP_RECORD, 4389 NULL) != USB_SUCCESS) { 4390 4391 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4392 "usb_ac_do_stop_record: failure"); 4393 4394 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4395 } 4396 4397 mutex_exit(&uacp->usb_ac_mutex); 4398 4399 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4400 "usb_ac_do_stop_record: End"); 4401 } 4402 4403 4404 /* 4405 * Helper Functions for Mixer callbacks 4406 * 4407 * usb_ac_get_maxmin_volume: 4408 * Send USBA command down to get the maximum or minimum gain balance 4409 * Calculate min or max gain balance and return that. Return 4410 * USB_FAILURE for failure cases 4411 */ 4412 static int 4413 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd, 4414 int dir, int feature_unitID) 4415 { 4416 mblk_t *data = NULL; 4417 short max_or_min; 4418 usb_cr_t cr; 4419 usb_cb_flags_t cb_flags; 4420 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4421 "usb_ac_get_maxmin_volume: channel=%d, cmd=%d dir=%d", 4422 channel, cmd, dir); 4423 4424 mutex_exit(&uacp->usb_ac_mutex); 4425 4426 if (usb_pipe_sync_ctrl_xfer( 4427 uacp->usb_ac_dip, 4428 uacp->usb_ac_default_ph, 4429 USB_DEV_REQ_DEV_TO_HOST | 4430 USB_DEV_REQ_TYPE_CLASS | 4431 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 4432 cmd, /* bRequest */ 4433 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 4434 /* feature unit and id */ 4435 (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */ 4436 2, /* wLength */ 4437 &data, 4438 USB_ATTRS_NONE, 4439 &cr, &cb_flags, 4440 USB_FLAGS_SLEEP) != USB_SUCCESS) { 4441 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4442 "usb_ac_get_maxmin_volume: failed, " 4443 "cr=%d, cb=0x%x cmd=%d, data=0x%p", 4444 cr, cb_flags, cmd, (void *)data); 4445 4446 freemsg(data); 4447 mutex_enter(&uacp->usb_ac_mutex); 4448 4449 return (USB_FAILURE); 4450 } 4451 4452 mutex_enter(&uacp->usb_ac_mutex); 4453 ASSERT((data->b_wptr - data->b_rptr) == 2); 4454 4455 max_or_min = (*(data->b_rptr+1) << 8) | *data->b_rptr; 4456 4457 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4458 "usb_ac_get_maxmin_volume: max_or_min=0x%x", max_or_min); 4459 4460 freemsg(data); 4461 4462 return (max_or_min); 4463 } 4464 4465 4466 /* 4467 * usb_ac_set_volume: 4468 * Send USBA command down to set the gain balance 4469 */ 4470 static int 4471 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir, 4472 int feature_unitID) 4473 { 4474 mblk_t *data = NULL; 4475 usb_cr_t cr; 4476 usb_cb_flags_t cb_flags; 4477 int rval = USB_FAILURE; 4478 4479 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4480 "usb_ac_set_volume: channel=%d gain=%d dir=%d FU=%d", 4481 channel, gain, dir, feature_unitID); 4482 4483 mutex_exit(&uacp->usb_ac_mutex); 4484 4485 /* Construct the mblk_t from gain for sending to USBA */ 4486 data = allocb_wait(4, BPRI_HI, STR_NOSIG, NULL); 4487 4488 *(data->b_wptr++) = (char)gain; 4489 *(data->b_wptr++) = (char)(gain >> 8); 4490 4491 if ((rval = usb_pipe_sync_ctrl_xfer( 4492 uacp->usb_ac_dip, 4493 uacp->usb_ac_default_ph, 4494 USB_DEV_REQ_HOST_TO_DEV | 4495 USB_DEV_REQ_TYPE_CLASS | 4496 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 4497 USB_AUDIO_SET_CUR, /* bRequest */ 4498 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 4499 /* feature unit and id */ 4500 (feature_unitID << 8) | uacp->usb_ac_ifno, /* wIndex */ 4501 2, /* wLength */ 4502 &data, 0, 4503 &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 4504 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4505 "usb_ac_set_volume: failed, cr=%d cb=0x%x", 4506 cr, cb_flags); 4507 } 4508 4509 freemsg(data); 4510 mutex_enter(&uacp->usb_ac_mutex); 4511 4512 return (rval); 4513 } 4514 4515 4516 /* 4517 * usb_ac_set_mute is called for each unit that supports the 4518 * requested control from usb_ac_traverse_connections 4519 */ 4520 static int 4521 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir, 4522 uint_t channel, uint_t control, uint_t muteval, uint_t *depth) 4523 { 4524 mblk_t *data; 4525 usb_cr_t cr; 4526 usb_cb_flags_t cb_flags; 4527 int rval = USB_FAILURE; 4528 4529 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4530 "usb_ac_set_mute: muteval=0x%x, dir=%d", muteval, dir); 4531 4532 if (usb_ac_feature_unit_check(uacp, featureID, 4533 dir, channel, control, 0, depth) != USB_SUCCESS) { 4534 4535 return (USB_FAILURE); 4536 } 4537 4538 mutex_exit(&uacp->usb_ac_mutex); 4539 4540 /* Construct the mblk_t for sending to USBA */ 4541 data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL); 4542 *(data->b_wptr++) = (char)muteval; 4543 4544 if ((rval = usb_pipe_sync_ctrl_xfer( 4545 uacp->usb_ac_dip, 4546 uacp->usb_ac_default_ph, 4547 USB_DEV_REQ_HOST_TO_DEV | 4548 USB_DEV_REQ_TYPE_CLASS | 4549 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 4550 USB_AUDIO_SET_CUR, /* bRequest */ 4551 (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */ 4552 /* feature unit and id */ 4553 (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */ 4554 1, /* wLength */ 4555 &data, 4556 0, /* attributes */ 4557 &cr, &cb_flags, 0)) != USB_SUCCESS) { 4558 4559 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4560 "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags); 4561 } 4562 4563 freemsg(data); 4564 mutex_enter(&uacp->usb_ac_mutex); 4565 4566 return (rval); 4567 } 4568 4569 4570 /* 4571 * usb_ac_send_as_cmd: 4572 * Allocate message blk, send a command down to usb_as, 4573 * wait for the reply and free the message 4574 * 4575 * although not really needed to raise power if sending to as 4576 * it seems better to ensure that both interfaces are at full power 4577 */ 4578 static int 4579 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_ac_plumbed_t *plumb_infop, 4580 int cmd, void *arg) 4581 { 4582 mblk_t *mp = NULL; 4583 struct iocblk *iocp; 4584 queue_t *lwq = plumb_infop->acp_lwq; 4585 usb_ac_streams_info_t *streams_infop; 4586 int error = USB_FAILURE; 4587 4588 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 4589 ASSERT(plumb_infop != NULL); 4590 4591 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4592 ASSERT(streams_infop != NULL); 4593 4594 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4595 "usb_ac_send_as_cmd: Begin lwq=0x%p, cmd=0x%x, arg=0x%p", 4596 (void *)lwq, cmd, arg); 4597 4598 if (!canputnext(lwq)) { 4599 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4600 "usb_ac_send_as_cmd: canputnext failed"); 4601 4602 return (error); 4603 } 4604 4605 /* 4606 * Allocate mblk for a particular command 4607 */ 4608 switch (cmd) { 4609 case USB_AUDIO_SET_FORMAT: 4610 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4611 sizeof (usb_audio_formats_t)); 4612 break; 4613 case USB_AUDIO_TEARDOWN: 4614 case USB_AUDIO_STOP_RECORD: 4615 case USB_AUDIO_PAUSE_PLAY: 4616 case USB_AUDIO_SETUP: 4617 mp = usb_ac_allocate_req_mblk(uacp, cmd, NULL, 0); 4618 break; 4619 case USB_AUDIO_START_RECORD: 4620 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4621 sizeof (audiohdl_t *)); 4622 break; 4623 case USB_AUDIO_SET_SAMPLE_FREQ: 4624 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4625 sizeof (int)); 4626 break; 4627 case USB_AUDIO_START_PLAY: 4628 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4629 sizeof (usb_audio_play_req_t)); 4630 break; 4631 default: 4632 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4633 "usb_ac_send_as_cmd: unknown cmd=%d", cmd); 4634 4635 return (error); 4636 } 4637 4638 if (mp == NULL) { 4639 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4640 "usb_ac_send_as_cmd: can't get mblk to send cmd down"); 4641 4642 return (error); 4643 } 4644 4645 /* 4646 * Set wait flag and send message down; we have made sure 4647 * before that canputnext succeeds. Note mp will be freed down 4648 */ 4649 streams_infop->acs_ac_to_as_req.acr_wait_flag = 1; 4650 4651 mutex_exit(&uacp->usb_ac_mutex); 4652 putnext(lwq, mp); 4653 mutex_enter(&uacp->usb_ac_mutex); 4654 4655 /* 4656 * Wait for the response; reply will arrive through rput() 4657 * M_CTL and the cv_wait will be signaled there and wait flag 4658 * will be reset 4659 */ 4660 while (streams_infop->acs_ac_to_as_req.acr_wait_flag) { 4661 #ifndef DEBUG 4662 cv_wait(&streams_infop->acs_ac_to_as_req.acr_cv, 4663 &uacp->usb_ac_mutex); 4664 #else 4665 clock_t tm = ddi_get_lbolt() + 4666 drv_usectohz(usb_ac_wait_timeout); 4667 int rval; 4668 4669 rval = cv_timedwait(&streams_infop->acs_ac_to_as_req.acr_cv, 4670 &uacp->usb_ac_mutex, tm); 4671 4672 if (streams_infop->acs_ac_to_as_req.acr_wait_flag) { 4673 if (rval == -1) { 4674 USB_DPRINTF_L3(PRINT_MASK_ALL, 4675 uacp->usb_ac_log_handle, 4676 "usb_ac_send_as_cmd:" 4677 " timeout happen before cmd complete."); 4678 } else { 4679 USB_DPRINTF_L3(PRINT_MASK_ALL, 4680 uacp->usb_ac_log_handle, 4681 "usb_ac_send_as_cmd:" 4682 " not signaled by USB_AS_PLUMBED."); 4683 } 4684 } 4685 #endif 4686 } 4687 4688 /* Wait is over, get the reply data */ 4689 mp = streams_infop->acs_ac_to_as_req.acr_reply_mp; 4690 ASSERT(mp != NULL); 4691 4692 iocp = (struct iocblk *)mp->b_rptr; 4693 4694 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4695 "usb_ac_send_as_cmd: db_type=0x%x cmd=0x%x", 4696 mp->b_datap->db_type, iocp->ioc_cmd); 4697 4698 switch (mp->b_datap->db_type) { 4699 case M_CTL: 4700 switch (iocp->ioc_cmd) { 4701 case USB_AUDIO_SET_FORMAT: 4702 /* 4703 * This command sets mixer format data 4704 * and returns alternate setting that matches 4705 */ 4706 ASSERT(mp->b_cont != NULL); 4707 ASSERT((mp->b_cont->b_wptr - mp->b_cont->b_rptr) == 4708 sizeof (int)); 4709 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4710 "alternate returned %d", 4711 *((int *)(mp->b_cont->b_rptr))); 4712 4713 streams_infop->acs_ac_to_as_req.acr_curr_format. 4714 fmt_alt = *((int *)(mp->b_cont->b_rptr)); 4715 4716 /*FALLTHROUGH*/ 4717 case USB_AUDIO_SET_SAMPLE_FREQ: 4718 case USB_AUDIO_SETUP: 4719 case USB_AUDIO_START_PLAY: 4720 case USB_AUDIO_PAUSE_PLAY: 4721 case USB_AUDIO_START_RECORD: 4722 case USB_AUDIO_STOP_RECORD: 4723 case USB_AUDIO_TEARDOWN: 4724 error = USB_SUCCESS; 4725 break; 4726 default: 4727 break; 4728 } 4729 break; 4730 case M_ERROR: 4731 default: 4732 error = USB_FAILURE; 4733 } 4734 4735 if (mp) { 4736 usb_ac_free_mblk(mp); 4737 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4738 } 4739 4740 return (error); 4741 } 4742 4743 4744 /* 4745 * usb_ac_allocate_req_mblk: 4746 * Allocate a message block with the specified M_CTL cmd, 4747 * The 2nd mblk contains the data for the command with a length len 4748 */ 4749 static mblk_t * 4750 usb_ac_allocate_req_mblk(usb_ac_state_t *uacp, int cmd, void *buf, uint_t len) 4751 { 4752 mblk_t *mp, *mp2; 4753 struct iocblk *mctlmsg; 4754 4755 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4756 "usb_ac_allocate_req_mblk: cmd=0x%x, buf=0x%p, len=%d", 4757 cmd, buf, len); 4758 4759 mp = allocb_wait(sizeof (struct iocblk), BPRI_HI, STR_NOSIG, NULL); 4760 mp->b_datap->db_type = M_CTL; 4761 mctlmsg = (struct iocblk *)mp->b_datap->db_base; 4762 mctlmsg->ioc_cmd = cmd; 4763 mctlmsg->ioc_count = len; 4764 4765 mp->b_wptr = mp->b_wptr + sizeof (struct iocblk); 4766 4767 if ((len == 0) || (buf == NULL)) { 4768 4769 return (mp); 4770 } 4771 4772 mp2 = allocb_wait(len, BPRI_HI, STR_NOSIG, NULL); 4773 mp->b_cont = mp2; 4774 bcopy(buf, mp->b_cont->b_datap->db_base, len); 4775 mp->b_cont->b_wptr = mp->b_cont->b_wptr + len; 4776 4777 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4778 "usb_ac_allocate_req_mblk: mp=0x%p", (void *)mp); 4779 4780 return (mp); 4781 } 4782 4783 4784 /* 4785 * usb_ac_free_mblk: 4786 * Free the message block 4787 */ 4788 static void 4789 usb_ac_free_mblk(mblk_t *mp) 4790 { 4791 if (mp->b_cont) { 4792 freemsg(mp->b_cont); 4793 mp->b_cont = NULL; 4794 } 4795 freemsg(mp); 4796 } 4797 4798 4799 /* 4800 * usb_ac_serialize/release_access: 4801 */ 4802 static void 4803 usb_ac_serialize_access(usb_ac_state_t *uacp) 4804 { 4805 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0); 4806 } 4807 4808 static void 4809 usb_ac_release_access(usb_ac_state_t *uacp) 4810 { 4811 usb_release_access(uacp->usb_ac_ser_acc); 4812 } 4813 4814 4815 static void 4816 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep) 4817 { 4818 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 4819 4820 if (usb_ac_statep->usb_ac_pm != NULL) { 4821 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4822 usb_ac_statep->usb_ac_pm->acpm_pm_busy++; 4823 4824 USB_DPRINTF_L4(PRINT_MASK_PM, 4825 usb_ac_statep->usb_ac_log_handle, 4826 "usb_ac_pm_busy_component: %d", 4827 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4828 4829 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4830 4831 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) != 4832 DDI_SUCCESS) { 4833 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4834 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 4835 4836 USB_DPRINTF_L2(PRINT_MASK_PM, 4837 usb_ac_statep->usb_ac_log_handle, 4838 "usb_ac_pm_busy_component failed: %d", 4839 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4840 4841 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4842 } 4843 } 4844 } 4845 4846 4847 static void 4848 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep) 4849 { 4850 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 4851 4852 if (usb_ac_statep->usb_ac_pm != NULL) { 4853 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) == 4854 DDI_SUCCESS) { 4855 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4856 ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0); 4857 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 4858 4859 USB_DPRINTF_L4(PRINT_MASK_PM, 4860 usb_ac_statep->usb_ac_log_handle, 4861 "usb_ac_pm_idle_component: %d", 4862 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4863 4864 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4865 } 4866 } 4867 } 4868