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