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 2005 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 3 secs for control 93 * cmd to timeout 94 */ 95 int usb_ac_wait_timeout = 4000000; 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 ASSERT(uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED); 3477 3478 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3479 mutex_exit(&uacp->usb_ac_mutex); 3480 3481 return (AUDIO_FAILURE); 3482 } 3483 mutex_exit(&uacp->usb_ac_mutex); 3484 usb_ac_serialize_access(uacp); 3485 mutex_enter(&uacp->usb_ac_mutex); 3486 3487 switch (command) { 3488 case AM_SET_GAIN: 3489 /* 3490 * Set the gain for a channel. The audio mixer calculates the 3491 * impact, if any, on the channel's gain. 3492 * 3493 * 0 <= gain <= AUDIO_MAX_GAIN 3494 * 3495 * arg1 --> gain 3496 * arg2 --> channel #, 0 == left, 1 == right 3497 */ 3498 what = "gain"; 3499 channel = ++arg2; 3500 ASSERT(flag != AUDIO_BOTH); 3501 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3502 3503 /* 3504 * We service the set_config command when the device is 3505 * plumbed and opened. 3506 */ 3507 n_channels = usb_ac_get_curr_n_channels(uacp, dir); 3508 3509 if (channel > n_channels) { 3510 USB_DPRINTF_L2(PRINT_MASK_ALL, 3511 uacp->usb_ac_log_handle, 3512 "usb_ac_set_config: channel(%d) passed is " 3513 " > n_channels(%d)", channel, n_channels); 3514 3515 goto done; 3516 } 3517 count = 0; 3518 (void) usb_ac_set_control(uacp, dir, 3519 USB_AUDIO_FEATURE_UNIT, channel, 3520 USB_AUDIO_VOLUME_CONTROL, 3521 USB_AC_FIND_ALL, &count, arg1, usb_ac_set_gain); 3522 3523 /* 3524 * If feature unit id could not be found, it probably means 3525 * volume/gain control is not available for this device. 3526 * and we just return success if we haven't completed 3527 * the registration with the mixer yet 3528 */ 3529 if (count == 0) { 3530 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3531 "mixer=%d, no featureID, arg1=%d", 3532 uacp->usb_ac_registered_with_mixer, arg1); 3533 rval = (uacp->usb_ac_registered_with_mixer == 0) ? 3534 AUDIO_SUCCESS : AUDIO_FAILURE; 3535 } else { 3536 rval = AUDIO_SUCCESS; 3537 } 3538 3539 break; 3540 case AM_SET_PORT: 3541 what = "port"; 3542 ASSERT(flag != AUDIO_BOTH); 3543 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3544 3545 rval = usb_ac_set_port(uacp, dir, arg1); 3546 rval = (rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE; 3547 3548 break; 3549 case AM_SET_MONITOR_GAIN: 3550 what = "monitor gain"; 3551 channel = ++arg2; 3552 dir = AUDIO_RECORD; 3553 3554 /* 3555 * We service the set_config command when the device is 3556 * plumbed and opened. 3557 */ 3558 n_channels = usb_ac_get_curr_n_channels(uacp, dir); 3559 3560 if (channel > n_channels) { 3561 USB_DPRINTF_L2(PRINT_MASK_ALL, 3562 uacp->usb_ac_log_handle, 3563 "usb_ac_set_config: channel(%d) passed is " 3564 " > n_channels(%d)", channel, n_channels); 3565 3566 goto done; 3567 } 3568 count = 0; 3569 (void) usb_ac_set_monitor_gain_control(uacp, dir, 3570 USB_AUDIO_INPUT_TERMINAL, channel, 3571 USB_AUDIO_VOLUME_CONTROL, 3572 USB_AC_FIND_ALL, &count, arg1, 3573 usb_ac_set_monitor_gain); 3574 3575 /* 3576 * always return success since we told the mixer 3577 * we always support this and sdtaudiocontrol displays 3578 * monitor gain regardless. 3579 */ 3580 rval = AUDIO_SUCCESS; 3581 3582 break; 3583 case AM_OUTPUT_MUTE: 3584 what = "mute"; 3585 ASSERT(flag != AUDIO_BOTH); 3586 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3587 3588 /* 3589 * arg1 != 0 --> mute 3590 * arg1 == 0 --> unmute 3591 * arg2 --> not used 3592 */ 3593 muteval = (arg1 == 0) ? USB_AUDIO_MUTE_OFF : 3594 USB_AUDIO_MUTE_ON; 3595 count = 0; 3596 (void) usb_ac_set_control(uacp, dir, 3597 USB_AUDIO_FEATURE_UNIT, 0, 3598 USB_AUDIO_MUTE_CONTROL, 3599 USB_AC_FIND_ALL, &count, muteval, 3600 usb_ac_set_mute); 3601 3602 rval = (count == 0) ? AUDIO_FAILURE : AUDIO_SUCCESS; 3603 3604 break; 3605 case AM_MIC_BOOST: 3606 what = "mic boost"; 3607 rval = AUDIO_SUCCESS; 3608 break; 3609 case AM_SET_GAIN_BAL: 3610 what = "set gain bal"; 3611 rval = AUDIO_FAILURE; 3612 break; 3613 default: 3614 what = "unknown"; 3615 rval = AUDIO_FAILURE; 3616 } 3617 3618 done: 3619 mutex_exit(&uacp->usb_ac_mutex); 3620 3621 /* Now it's safe to release access to other routines */ 3622 usb_ac_release_access(uacp); 3623 3624 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3625 "usb_ac_set_config: %s done, rval=%d", what, rval); 3626 3627 return (rval); 3628 } 3629 3630 3631 /* 3632 * usb_ac_set_monitor_gain: 3633 * called for each output terminal which supports 3634 * from usb_ac_traverse_connections 3635 */ 3636 static int 3637 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit, 3638 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth) 3639 { 3640 usb_audio_output_term_descr_t *d = 3641 uacp->usb_ac_units[unit].acu_descriptor; 3642 3643 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3644 "usb_ac_set_monitor_gain: "); 3645 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3646 "id=%d dir=%d ch=%d cntl=%d gain=%d type=%d term type=0x%x", 3647 unit, dir, channel, control, gain, 3648 uacp->usb_ac_unit_type[unit], d->wTerminalType); 3649 3650 /* log how we got here */ 3651 usb_ac_push_unit_id(uacp, unit); 3652 usb_ac_show_traverse_path(uacp); 3653 usb_ac_pop_unit_id(uacp, unit); 3654 3655 /* we only care about the ITs connected to real hw inputs */ 3656 switch (d->wTerminalType) { 3657 case USB_AUDIO_TERM_TYPE_STREAMING: 3658 3659 return (USB_FAILURE); 3660 3661 case USB_AUDIO_TERM_TYPE_DT_MICROPHONE: 3662 case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE: 3663 case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE: 3664 case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY: 3665 case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY: 3666 default: 3667 3668 break; 3669 } 3670 3671 /* 3672 * we can only do this if the microphone is mixed into the 3673 * audio output so look for a mixer first 3674 */ 3675 if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) == 3676 USB_SUCCESS) { 3677 int i, id; 3678 3679 /* now look for a feature unit */ 3680 for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0; 3681 i--) { 3682 id = uacp->usb_ac_traverse_path[i]; 3683 3684 switch (uacp->usb_ac_unit_type[id]) { 3685 case USB_AUDIO_MIXER_UNIT: 3686 3687 /* the FU should be before the mixer */ 3688 return (USB_FAILURE); 3689 3690 case USB_AUDIO_FEATURE_UNIT: 3691 /* 3692 * now set the volume 3693 */ 3694 if (usb_ac_set_gain(uacp, id, dir, channel, 3695 control, gain, depth) != USB_SUCCESS) { 3696 3697 /* try master channel */ 3698 if (usb_ac_set_gain(uacp, id, dir, 3699 0, control, gain, depth) != 3700 USB_SUCCESS) { 3701 3702 return (USB_FAILURE); 3703 } 3704 } 3705 3706 return (USB_SUCCESS); 3707 3708 default: 3709 continue; 3710 } 3711 } 3712 } 3713 3714 return (USB_FAILURE); 3715 } 3716 3717 3718 /* 3719 * usb_ac_set_gain is called for each feature unit which supports 3720 * the requested controls from usb_ac_traverse_connections 3721 * we still need to check whether this unit supports the requested 3722 * control. 3723 */ 3724 static int 3725 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID, 3726 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth) 3727 { 3728 short max, min, current; 3729 3730 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3731 "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d", 3732 featureID, dir, channel, control, gain); 3733 3734 if (usb_ac_feature_unit_check(uacp, featureID, 3735 dir, channel, control, gain, depth) != USB_SUCCESS) { 3736 3737 return (USB_FAILURE); 3738 } 3739 3740 if ((max = usb_ac_get_maxmin_volume(uacp, channel, 3741 USB_AUDIO_GET_MAX, dir, featureID)) == USB_FAILURE) { 3742 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3743 "usb_ac_set_gain: getting max gain failed"); 3744 3745 return (USB_FAILURE); 3746 } 3747 3748 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3749 "usb_ac_set_gain: channel %d, max=%d", channel, max); 3750 3751 if ((min = usb_ac_get_maxmin_volume(uacp, channel, 3752 USB_AUDIO_GET_MIN, dir, featureID)) == USB_FAILURE) { 3753 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3754 "usb_ac_set_gain: getting min gain failed"); 3755 3756 return (USB_FAILURE); 3757 } 3758 3759 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3760 "usb_ac_set_gain: channel=%d, min=%d", channel, min); 3761 3762 if ((current = usb_ac_get_maxmin_volume(uacp, channel, 3763 USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) { 3764 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3765 "usb_ac_set_gain: getting cur gain failed"); 3766 3767 return (USB_FAILURE); 3768 } 3769 3770 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3771 "usb_ac_set_gain: channel=%d, cur=%d", channel, current); 3772 3773 /* 3774 * Set the gain for a channel. The audio mixer calculates the 3775 * impact, if any, on the channel's gain. 3776 * 3777 * 0 <= gain <= AUDIO_MAX_GAIN 3778 * 3779 * channel #, 0 == left, 1 == right 3780 */ 3781 3782 if (gain == 0) { 3783 gain = USB_AUDIO_VOLUME_SILENCE; 3784 } else { 3785 gain = max - ((max - min) * (0x100 - gain))/0x100; 3786 } 3787 3788 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3789 "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d", 3790 channel, dir, max, min, gain); 3791 3792 if (usb_ac_set_volume(uacp, channel, gain, dir, 3793 featureID) != USB_SUCCESS) { 3794 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3795 "usb_ac_set_gain: setting volume failed"); 3796 3797 return (USB_FAILURE); 3798 } 3799 3800 /* just curious, read it back, device may round up/down */ 3801 if ((current = usb_ac_get_maxmin_volume(uacp, channel, 3802 USB_AUDIO_GET_CUR, dir, featureID)) == USB_FAILURE) { 3803 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3804 "usb_ac_set_gain: getting cur gain failed"); 3805 } 3806 3807 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3808 "usb_ac_set_gain done: " 3809 "id=%d channel=%d, cur=%d gain=%d", featureID, channel, 3810 (ushort_t)current, (ushort_t)gain); 3811 3812 return (USB_SUCCESS); 3813 } 3814 3815 3816 /* 3817 * usb_ac_set_format 3818 * This mixer callback initiates a command to be sent to 3819 * usb_as to select an alternate with the passed characteristics 3820 * and also to set the sample frequency. 3821 * Note that this may be called when a playing is going on in 3822 * the streaming interface. To handle that, first stop 3823 * playing/recording, close the pipe by sending a teardown 3824 * command, send the set_format command down and then reopen 3825 * the pipe. Note : (1) audio framework will restart play/record 3826 * after a set_format command. (2) Check power is done in 3827 * usb_ac_send_as_cmd(). 3828 */ 3829 static int 3830 usb_ac_set_format(audiohdl_t ahdl, int stream, int flag, 3831 int sample, int channels, int precision, int encoding) 3832 { 3833 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3834 usb_audio_formats_t *format; 3835 usb_audio_formats_t old_format; 3836 usb_ac_plumbed_t *plumb_infop; 3837 usb_ac_streams_info_t *streams_infop = NULL; 3838 int old_setup_teardown_count; 3839 int dir; 3840 int rval; 3841 3842 ASSERT(uacp != NULL); 3843 3844 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3845 "usb_ac_set_format: Begin ahdl=0x%p, stream=%d, flag=%d, " 3846 "sr=%d, chnls=%d, prec=%d, enc=%d", ahdl, stream, flag, 3847 sample, channels, precision, encoding); 3848 3849 mutex_enter(&uacp->usb_ac_mutex); 3850 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3851 mutex_exit(&uacp->usb_ac_mutex); 3852 3853 return (AUDIO_FAILURE); 3854 } 3855 mutex_exit(&uacp->usb_ac_mutex); 3856 3857 usb_ac_serialize_access(uacp); 3858 3859 ASSERT(flag != AUDIO_BOTH); 3860 3861 mutex_enter(&uacp->usb_ac_mutex); 3862 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3863 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3864 if (plumb_infop == NULL) { 3865 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3866 "usb_ac_set_format: no plumb info"); 3867 mutex_exit(&uacp->usb_ac_mutex); 3868 3869 usb_ac_release_access(uacp); 3870 3871 return (AUDIO_FAILURE); 3872 } 3873 3874 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3875 ASSERT(streams_infop != NULL); 3876 3877 /* isoc pipe not open and playing is not in progress */ 3878 if (streams_infop->acs_setup_teardown_count == 0) { 3879 3880 mutex_exit(&uacp->usb_ac_mutex); 3881 3882 rval = usb_ac_send_format_cmd(ahdl, stream, dir, sample, 3883 channels, precision, encoding); 3884 3885 usb_ac_release_access(uacp); 3886 3887 return ((rval == USB_SUCCESS) ? 3888 AUDIO_SUCCESS : AUDIO_FAILURE); 3889 } 3890 3891 /* isoc pipe is open and playing might be in progress */ 3892 format = &streams_infop->acs_ac_to_as_req.acr_curr_format; 3893 3894 /* Keep a copy of the old format */ 3895 bcopy((void *)format, (void *)&old_format, 3896 sizeof (usb_audio_formats_t)); 3897 3898 ASSERT(streams_infop->acs_setup_teardown_count != 0); 3899 3900 old_setup_teardown_count = streams_infop->acs_setup_teardown_count; 3901 streams_infop->acs_setup_teardown_count = 1; 3902 3903 mutex_exit(&uacp->usb_ac_mutex); 3904 3905 if (dir == AUDIO_PLAY) { 3906 usb_ac_do_pause_play(ahdl, stream); 3907 } else if (dir == AUDIO_RECORD) { 3908 usb_ac_do_stop_record(ahdl, stream); 3909 } 3910 3911 /* This blocks until the current isoc xfer is over */ 3912 usb_ac_do_teardown(ahdl, stream, dir); 3913 3914 if (usb_ac_send_format_cmd(ahdl, stream, dir, sample, 3915 channels, precision, encoding) != USB_SUCCESS) { 3916 /* 3917 * Setting new alternate has failed, try restoring 3918 * old one. 3919 * If there is a bandwidth failure, hang around 3920 * till bandwidth is available. Also we know that 3921 * there is a matching alternate, so that can't fail. 3922 */ 3923 if (usb_ac_send_format_cmd(ahdl, stream, dir, 3924 old_format.fmt_sr, old_format.fmt_chns, 3925 old_format.fmt_precision, old_format.fmt_encoding) == 3926 USB_FAILURE) { 3927 3928 /* We closed the pipe; reopen it */ 3929 (void) usb_ac_do_setup(ahdl, stream, dir); 3930 3931 mutex_enter(&uacp->usb_ac_mutex); 3932 streams_infop->acs_setup_teardown_count = 3933 old_setup_teardown_count; 3934 mutex_exit(&uacp->usb_ac_mutex); 3935 3936 usb_ac_release_access(uacp); 3937 3938 return (AUDIO_FAILURE); 3939 } 3940 } 3941 3942 /* This should block until successful */ 3943 (void) usb_ac_do_setup(ahdl, stream, dir); 3944 3945 mutex_enter(&uacp->usb_ac_mutex); 3946 streams_infop->acs_setup_teardown_count = old_setup_teardown_count; 3947 mutex_exit(&uacp->usb_ac_mutex); 3948 3949 usb_ac_release_access(uacp); 3950 3951 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3952 "usb_ac_set_format: End"); 3953 3954 return (AUDIO_SUCCESS); 3955 } 3956 3957 3958 /* 3959 * usb_ac_get_curr_n_channels: 3960 * Return no. of channels from the current format table 3961 */ 3962 static int 3963 usb_ac_get_curr_n_channels(usb_ac_state_t *uacp, int dir) 3964 { 3965 usb_audio_formats_t *cur_fmt = usb_ac_get_curr_format(uacp, dir); 3966 3967 return (cur_fmt->fmt_chns); 3968 } 3969 3970 3971 /* 3972 * usb_ac_get_cur_format: 3973 * Get format for the current alternate 3974 */ 3975 static usb_audio_formats_t * 3976 usb_ac_get_curr_format(usb_ac_state_t *uacp, int dir) 3977 { 3978 usb_ac_plumbed_t *plumb_infop; 3979 usb_ac_streams_info_t *streams_infop = NULL; 3980 3981 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3982 3983 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3984 if (plumb_infop == NULL) { 3985 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3986 "usb_ac_get_curr_format: no plumb info"); 3987 3988 return (NULL); 3989 } 3990 3991 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3992 ASSERT(streams_infop != NULL); 3993 3994 return (&streams_infop->acs_cur_fmt); 3995 } 3996 3997 3998 /* 3999 * usb_ac_send_format_cmd 4000 * Sets format and get alternate setting that matches with 4001 * the format from the usb_as playing or recording interface 4002 * Send the set sample freq command down to usb_as. 4003 */ 4004 static int 4005 usb_ac_send_format_cmd(audiohdl_t ahdl, int stream, int dir, 4006 int sample, int channels, int precision, int encoding) 4007 { 4008 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4009 usb_audio_formats_t *format; 4010 usb_ac_plumbed_t *plumb_infop = NULL; 4011 usb_ac_streams_info_t *streams_infop = NULL; 4012 4013 ASSERT(uacp != NULL); 4014 4015 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4016 "usb_ac_send_format_cmd: Begin ahdl=0x%p, stream=%d, dir=%d, " 4017 "sr=%d, chnls=%d, prec=%d, enc=%d", ahdl, stream, dir, 4018 sample, channels, precision, encoding); 4019 4020 mutex_enter(&uacp->usb_ac_mutex); 4021 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4022 mutex_exit(&uacp->usb_ac_mutex); 4023 4024 return (USB_FAILURE); 4025 } 4026 4027 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 4028 ASSERT(plumb_infop); 4029 4030 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4031 ASSERT(streams_infop != NULL); 4032 4033 ASSERT(dir == AUDIO_PLAY || dir == AUDIO_RECORD); 4034 streams_infop->acs_ac_to_as_req.acr_curr_dir = dir; 4035 4036 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4037 "usb_ac_send_format_cmd: plumb_infop=0x%p, streams_infop=0x%p", 4038 plumb_infop, streams_infop); 4039 4040 format = &(streams_infop->acs_ac_to_as_req.acr_curr_format); 4041 bzero(format, sizeof (usb_audio_formats_t)); 4042 4043 /* save format info */ 4044 format->fmt_sr = (uint_t)sample; 4045 format->fmt_chns = (uchar_t)channels; 4046 format->fmt_precision = (uchar_t)precision; 4047 format->fmt_encoding = (uchar_t)encoding; 4048 4049 streams_infop->acs_cur_fmt = *format; 4050 4051 /* 4052 * Set format for the streaming interface with lower write queue 4053 * This boils down to set_alternate interface command in 4054 * usb_as and the reply mp contains the currently active 4055 * alternate number that is stored in the as_req structure 4056 */ 4057 if (usb_ac_send_as_cmd(uacp, plumb_infop, 4058 USB_AUDIO_SET_FORMAT, format) != USB_SUCCESS) { 4059 USB_DPRINTF_L2(PRINT_MASK_ALL, 4060 uacp->usb_ac_log_handle, 4061 "usb_ac_send_format_cmd: failed"); 4062 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4063 mutex_exit(&uacp->usb_ac_mutex); 4064 4065 return (USB_FAILURE); 4066 } else { 4067 /* alternate number stored and reply mp freed */ 4068 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4069 } 4070 4071 /* Set the sample rate */ 4072 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SET_SAMPLE_FREQ, 4073 &sample) != USB_SUCCESS) { 4074 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4075 "usb_ac_send_format_cmd: setting format failed"); 4076 4077 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4078 mutex_exit(&uacp->usb_ac_mutex); 4079 4080 return (USB_FAILURE); 4081 } 4082 4083 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4084 4085 mutex_exit(&uacp->usb_ac_mutex); 4086 4087 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4088 "usb_ac_send_format_cmd: End"); 4089 4090 return (USB_SUCCESS); 4091 } 4092 4093 4094 /* 4095 * usb_ac_start_play 4096 * Send a start_play command down to usb_as 4097 * Check power is done in usb_ac_send_as_cmd() 4098 */ 4099 static int 4100 usb_ac_start_play(audiohdl_t ahdl, int stream) 4101 { 4102 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4103 usb_audio_formats_t *cur_fmt; 4104 usb_ac_plumbed_t *plumb_infop = NULL; 4105 int dir, samples; 4106 usb_audio_play_req_t play_req; 4107 usb_ac_streams_info_t *streams_infop = NULL; 4108 4109 ASSERT(uacp != NULL); 4110 4111 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4112 "usb_ac_start_play: Begin ahdl=0x%p, stream=%d", 4113 ahdl, stream); 4114 4115 mutex_enter(&uacp->usb_ac_mutex); 4116 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4117 mutex_exit(&uacp->usb_ac_mutex); 4118 4119 return (AUDIO_FAILURE); 4120 } 4121 mutex_exit(&uacp->usb_ac_mutex); 4122 4123 usb_ac_serialize_access(uacp); 4124 4125 mutex_enter(&uacp->usb_ac_mutex); 4126 4127 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY); 4128 ASSERT(plumb_infop); 4129 4130 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4131 ASSERT(streams_infop != NULL); 4132 4133 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4134 "usb_ac_start_play: plumb_infop=0x%p, streams_infop=0x%p", 4135 plumb_infop, streams_infop); 4136 4137 dir = streams_infop->acs_ac_to_as_req.acr_curr_dir; 4138 ASSERT(dir == AUDIO_PLAY); 4139 4140 cur_fmt = &streams_infop->acs_ac_to_as_req.acr_curr_format; 4141 4142 /* Check for continuous sample rate done in usb_as */ 4143 samples = cur_fmt->fmt_sr * cur_fmt->fmt_chns / 4144 uacp->usb_ac_am_ad_info.ad_play.ad_int_rate; 4145 if (samples & cur_fmt->fmt_chns) { 4146 samples++; 4147 } 4148 4149 play_req.up_samples = samples; 4150 play_req.up_handle = ahdl; 4151 4152 /* Send setup command to usb_as */ 4153 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_PLAY, 4154 (void *)&play_req) != USB_SUCCESS) { 4155 4156 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4157 "usb_ac_start_play: failure"); 4158 4159 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4160 mutex_exit(&uacp->usb_ac_mutex); 4161 4162 usb_ac_release_access(uacp); 4163 4164 return (AUDIO_FAILURE); 4165 } 4166 4167 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4168 mutex_exit(&uacp->usb_ac_mutex); 4169 4170 usb_ac_release_access(uacp); 4171 4172 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4173 "usb_ac_start_play: End"); 4174 4175 return (AUDIO_SUCCESS); 4176 } 4177 4178 4179 /* 4180 * usb_ac_pause_play: 4181 * Wrapper function for usb_ac_do_pause_play and gets 4182 * called from mixer framework. 4183 */ 4184 static void 4185 usb_ac_pause_play(audiohdl_t ahdl, int stream) 4186 { 4187 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4188 4189 ASSERT(uacp != NULL); 4190 4191 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4192 "usb_ac_pause_play: Begin ahdl=0x%p, stream=%d", 4193 ahdl, stream); 4194 4195 mutex_enter(&uacp->usb_ac_mutex); 4196 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4197 mutex_exit(&uacp->usb_ac_mutex); 4198 4199 return; 4200 } 4201 mutex_exit(&uacp->usb_ac_mutex); 4202 4203 usb_ac_serialize_access(uacp); 4204 usb_ac_do_pause_play(ahdl, stream); 4205 usb_ac_release_access(uacp); 4206 4207 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4208 "usb_ac_pause_play: End"); 4209 } 4210 4211 /* 4212 * usb_ac_do_pause_play: 4213 * Send a pause_play command to usb_as. 4214 * Check power is done in usb_ac_send_as_cmd() 4215 */ 4216 static void 4217 usb_ac_do_pause_play(audiohdl_t ahdl, int stream) 4218 { 4219 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4220 usb_ac_plumbed_t *plumb_infop = NULL; 4221 usb_ac_streams_info_t *streams_infop = NULL; 4222 4223 ASSERT(uacp != NULL); 4224 4225 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4226 "usb_ac_do_pause_play: Begin ahdl=0x%p, stream=%d", 4227 ahdl, stream); 4228 4229 mutex_enter(&uacp->usb_ac_mutex); 4230 4231 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_PLAY); 4232 ASSERT(plumb_infop); 4233 4234 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4235 ASSERT(streams_infop != NULL); 4236 4237 /* Send setup command to usb_as */ 4238 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_PAUSE_PLAY, 4239 (void *)NULL) != USB_SUCCESS) { 4240 4241 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4242 "usb_ac_do_pause_play: failure"); 4243 4244 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4245 } 4246 4247 mutex_exit(&uacp->usb_ac_mutex); 4248 4249 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4250 "usb_ac_do_pause_play: End"); 4251 } 4252 4253 4254 /* 4255 * usb_ac_stop_play: 4256 * Wrapper function for usb_ac_pause_play and gets 4257 * called from mixer framework. 4258 */ 4259 static void 4260 usb_ac_stop_play(audiohdl_t ahdl, int stream) 4261 { 4262 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4263 4264 ASSERT(uacp != NULL); 4265 4266 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4267 "usb_ac_stop_play: Begin ahdl=0x%p, stream=%d", 4268 ahdl, stream); 4269 4270 usb_ac_pause_play(ahdl, stream); 4271 4272 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4273 "usb_ac_stop_play: End"); 4274 } 4275 4276 4277 /* 4278 * usb_ac_start_record: 4279 * Sends a start record command down to usb_as. 4280 * Check power is done in usb_ac_send_as_cmd() 4281 */ 4282 static int 4283 usb_ac_start_record(audiohdl_t ahdl, int stream) 4284 { 4285 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4286 usb_ac_plumbed_t *plumb_infop = NULL; 4287 usb_ac_streams_info_t *streams_infop = NULL; 4288 4289 ASSERT(uacp != NULL); 4290 4291 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4292 "usb_ac_start_record: Begin ahdl=0x%p, stream=%d", 4293 ahdl, stream); 4294 4295 mutex_enter(&uacp->usb_ac_mutex); 4296 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 4297 mutex_exit(&uacp->usb_ac_mutex); 4298 4299 return (AUDIO_FAILURE); 4300 } 4301 mutex_exit(&uacp->usb_ac_mutex); 4302 4303 usb_ac_serialize_access(uacp); 4304 4305 mutex_enter(&uacp->usb_ac_mutex); 4306 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD); 4307 ASSERT(plumb_infop); 4308 4309 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4310 ASSERT(streams_infop != NULL); 4311 4312 /* Send setup command to usb_as */ 4313 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_START_RECORD, 4314 (void *)&ahdl) != USB_SUCCESS) { 4315 4316 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4317 "usb_ac_start_record: failure"); 4318 4319 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4320 mutex_exit(&uacp->usb_ac_mutex); 4321 4322 usb_ac_release_access(uacp); 4323 4324 return (AUDIO_FAILURE); 4325 } 4326 4327 mutex_exit(&uacp->usb_ac_mutex); 4328 4329 usb_ac_release_access(uacp); 4330 4331 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4332 "usb_ac_start_record: End"); 4333 4334 return (AUDIO_SUCCESS); 4335 } 4336 4337 4338 /* 4339 * usb_ac_stop_record: 4340 * Wrapper function for usb_ac_do_stop_record and is 4341 * called form mixer framework. 4342 */ 4343 static void 4344 usb_ac_stop_record(audiohdl_t ahdl, int stream) 4345 { 4346 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4347 4348 ASSERT(uacp != NULL); 4349 4350 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4351 "usb_ac_stop_record: Begin ahdl=0x%p, stream=%d", 4352 ahdl, stream); 4353 4354 usb_ac_serialize_access(uacp); 4355 usb_ac_do_stop_record(ahdl, stream); 4356 usb_ac_release_access(uacp); 4357 4358 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4359 "usb_ac_stop_record: End"); 4360 } 4361 4362 4363 /* 4364 * usb_ac_do_stop_record: 4365 * Sends a stop_record command down. 4366 * Check power is done in usb_ac_send_as_cmd() 4367 */ 4368 static void 4369 usb_ac_do_stop_record(audiohdl_t ahdl, int stream) 4370 { 4371 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 4372 usb_ac_plumbed_t *plumb_infop = NULL; 4373 usb_ac_streams_info_t *streams_infop = NULL; 4374 4375 ASSERT(uacp != NULL); 4376 4377 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4378 "usb_ac_do_stop_record: Begin ahdl=0x%p, stream=%d", 4379 ahdl, stream); 4380 4381 mutex_enter(&uacp->usb_ac_mutex); 4382 4383 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", AUDIO_RECORD); 4384 ASSERT(plumb_infop != NULL); 4385 4386 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4387 ASSERT(streams_infop != NULL); 4388 4389 /* Send setup command to usb_as */ 4390 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_STOP_RECORD, 4391 NULL) != USB_SUCCESS) { 4392 4393 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4394 "usb_ac_do_stop_record: failure"); 4395 4396 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4397 } 4398 4399 mutex_exit(&uacp->usb_ac_mutex); 4400 4401 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4402 "usb_ac_do_stop_record: End"); 4403 } 4404 4405 4406 /* 4407 * Helper Functions for Mixer callbacks 4408 * 4409 * usb_ac_get_maxmin_volume: 4410 * Send USBA command down to get the maximum or minimum gain balance 4411 * Calculate min or max gain balance and return that. Return 4412 * USB_FAILURE for failure cases 4413 */ 4414 static int 4415 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd, 4416 int dir, int feature_unitID) 4417 { 4418 mblk_t *data = NULL; 4419 short max_or_min; 4420 usb_cr_t cr; 4421 usb_cb_flags_t cb_flags; 4422 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4423 "usb_ac_get_maxmin_volume: channel=%d, cmd=%d dir=%d", 4424 channel, cmd, dir); 4425 4426 mutex_exit(&uacp->usb_ac_mutex); 4427 4428 if (usb_pipe_sync_ctrl_xfer( 4429 uacp->usb_ac_dip, 4430 uacp->usb_ac_default_ph, 4431 USB_DEV_REQ_DEV_TO_HOST | 4432 USB_DEV_REQ_TYPE_CLASS | 4433 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 4434 cmd, /* bRequest */ 4435 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 4436 /* feature unit and id */ 4437 (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */ 4438 2, /* wLength */ 4439 &data, 4440 USB_ATTRS_NONE, 4441 &cr, &cb_flags, 4442 USB_FLAGS_SLEEP) != USB_SUCCESS) { 4443 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4444 "usb_ac_get_maxmin_volume: failed, " 4445 "cr=%d, cb=0x%x cmd=%d, data=0x%p", 4446 cr, cb_flags, cmd, data); 4447 4448 freemsg(data); 4449 mutex_enter(&uacp->usb_ac_mutex); 4450 4451 return (USB_FAILURE); 4452 } 4453 4454 mutex_enter(&uacp->usb_ac_mutex); 4455 ASSERT((data->b_wptr - data->b_rptr) == 2); 4456 4457 max_or_min = (*(data->b_rptr+1) << 8) | *data->b_rptr; 4458 4459 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4460 "usb_ac_get_maxmin_volume: max_or_min=0x%x", max_or_min); 4461 4462 freemsg(data); 4463 4464 return (max_or_min); 4465 } 4466 4467 4468 /* 4469 * usb_ac_set_volume: 4470 * Send USBA command down to set the gain balance 4471 */ 4472 static int 4473 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir, 4474 int feature_unitID) 4475 { 4476 mblk_t *data = NULL; 4477 usb_cr_t cr; 4478 usb_cb_flags_t cb_flags; 4479 int rval = USB_FAILURE; 4480 4481 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4482 "usb_ac_set_volume: channel=%d gain=%d dir=%d FU=%d", 4483 channel, gain, dir, feature_unitID); 4484 4485 mutex_exit(&uacp->usb_ac_mutex); 4486 4487 /* Construct the mblk_t from gain for sending to USBA */ 4488 data = allocb_wait(4, BPRI_HI, STR_NOSIG, NULL); 4489 4490 *(data->b_wptr++) = (char)gain; 4491 *(data->b_wptr++) = (char)(gain >> 8); 4492 4493 if ((rval = usb_pipe_sync_ctrl_xfer( 4494 uacp->usb_ac_dip, 4495 uacp->usb_ac_default_ph, 4496 USB_DEV_REQ_HOST_TO_DEV | 4497 USB_DEV_REQ_TYPE_CLASS | 4498 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 4499 USB_AUDIO_SET_CUR, /* bRequest */ 4500 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */ 4501 /* feature unit and id */ 4502 (feature_unitID << 8) | uacp->usb_ac_ifno, /* wIndex */ 4503 2, /* wLength */ 4504 &data, 0, 4505 &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 4506 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4507 "usb_ac_set_volume: failed, cr=%d cb=0x%x", 4508 cr, cb_flags); 4509 } 4510 4511 freemsg(data); 4512 mutex_enter(&uacp->usb_ac_mutex); 4513 4514 return (rval); 4515 } 4516 4517 4518 /* 4519 * usb_ac_set_mute is called for each unit that supports the 4520 * requested control from usb_ac_traverse_connections 4521 */ 4522 static int 4523 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir, 4524 uint_t channel, uint_t control, uint_t muteval, uint_t *depth) 4525 { 4526 mblk_t *data; 4527 usb_cr_t cr; 4528 usb_cb_flags_t cb_flags; 4529 int rval = USB_FAILURE; 4530 4531 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4532 "usb_ac_set_mute: muteval=0x%x, dir=%d", muteval, dir); 4533 4534 if (usb_ac_feature_unit_check(uacp, featureID, 4535 dir, channel, control, 0, depth) != USB_SUCCESS) { 4536 4537 return (USB_FAILURE); 4538 } 4539 4540 mutex_exit(&uacp->usb_ac_mutex); 4541 4542 /* Construct the mblk_t for sending to USBA */ 4543 data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL); 4544 *(data->b_wptr++) = (char)muteval; 4545 4546 if ((rval = usb_pipe_sync_ctrl_xfer( 4547 uacp->usb_ac_dip, 4548 uacp->usb_ac_default_ph, 4549 USB_DEV_REQ_HOST_TO_DEV | 4550 USB_DEV_REQ_TYPE_CLASS | 4551 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 4552 USB_AUDIO_SET_CUR, /* bRequest */ 4553 (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */ 4554 /* feature unit and id */ 4555 (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */ 4556 1, /* wLength */ 4557 &data, 4558 0, /* attributes */ 4559 &cr, &cb_flags, 0)) != USB_SUCCESS) { 4560 4561 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4562 "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags); 4563 } 4564 4565 freemsg(data); 4566 mutex_enter(&uacp->usb_ac_mutex); 4567 4568 return (rval); 4569 } 4570 4571 4572 /* 4573 * usb_ac_send_as_cmd: 4574 * Allocate message blk, send a command down to usb_as, 4575 * wait for the reply and free the message 4576 * 4577 * although not really needed to raise power if sending to as 4578 * it seems better to ensure that both interfaces are at full power 4579 */ 4580 static int 4581 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_ac_plumbed_t *plumb_infop, 4582 int cmd, void *arg) 4583 { 4584 mblk_t *mp = NULL; 4585 struct iocblk *iocp; 4586 queue_t *lwq = plumb_infop->acp_lwq; 4587 usb_ac_streams_info_t *streams_infop; 4588 int error = USB_FAILURE; 4589 4590 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 4591 ASSERT(plumb_infop != NULL); 4592 4593 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 4594 ASSERT(streams_infop != NULL); 4595 4596 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4597 "usb_ac_send_as_cmd: Begin lwq=0x%p, cmd=0x%x, arg=0x%p", 4598 lwq, cmd, arg); 4599 4600 if (!canputnext(lwq)) { 4601 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4602 "usb_ac_send_as_cmd: canputnext failed"); 4603 4604 return (error); 4605 } 4606 4607 /* 4608 * Allocate mblk for a particular command 4609 */ 4610 switch (cmd) { 4611 case USB_AUDIO_SET_FORMAT: 4612 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4613 sizeof (usb_audio_formats_t)); 4614 break; 4615 case USB_AUDIO_TEARDOWN: 4616 case USB_AUDIO_STOP_RECORD: 4617 case USB_AUDIO_PAUSE_PLAY: 4618 case USB_AUDIO_SETUP: 4619 mp = usb_ac_allocate_req_mblk(uacp, cmd, NULL, 0); 4620 break; 4621 case USB_AUDIO_START_RECORD: 4622 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4623 sizeof (audiohdl_t *)); 4624 break; 4625 case USB_AUDIO_SET_SAMPLE_FREQ: 4626 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4627 sizeof (int)); 4628 break; 4629 case USB_AUDIO_START_PLAY: 4630 mp = usb_ac_allocate_req_mblk(uacp, cmd, (void *)arg, 4631 sizeof (usb_audio_play_req_t)); 4632 break; 4633 default: 4634 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4635 "usb_ac_send_as_cmd: unknown cmd=%d", cmd); 4636 4637 return (error); 4638 } 4639 4640 if (mp == NULL) { 4641 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4642 "usb_ac_send_as_cmd: can't get mblk to send cmd down"); 4643 4644 return (error); 4645 } 4646 4647 /* 4648 * Set wait flag and send message down; we have made sure 4649 * before that canputnext succeeds. Note mp will be freed down 4650 */ 4651 streams_infop->acs_ac_to_as_req.acr_wait_flag = 1; 4652 4653 mutex_exit(&uacp->usb_ac_mutex); 4654 putnext(lwq, mp); 4655 mutex_enter(&uacp->usb_ac_mutex); 4656 4657 /* 4658 * Wait for the response; reply will arrive through rput() 4659 * M_CTL and the cv_wait will be signaled there and wait flag 4660 * will be reset 4661 */ 4662 while (streams_infop->acs_ac_to_as_req.acr_wait_flag) { 4663 #ifndef DEBUG 4664 cv_wait(&streams_infop->acs_ac_to_as_req.acr_cv, 4665 &uacp->usb_ac_mutex); 4666 #else 4667 clock_t tm = ddi_get_lbolt() + 4668 drv_usectohz(usb_ac_wait_timeout); 4669 int rval; 4670 4671 rval = cv_timedwait(&streams_infop->acs_ac_to_as_req.acr_cv, 4672 &uacp->usb_ac_mutex, tm); 4673 4674 if (streams_infop->acs_ac_to_as_req.acr_wait_flag) { 4675 ASSERT(rval != -1); 4676 } 4677 #endif 4678 } 4679 4680 /* Wait is over, get the reply data */ 4681 mp = streams_infop->acs_ac_to_as_req.acr_reply_mp; 4682 ASSERT(mp != NULL); 4683 4684 iocp = (struct iocblk *)mp->b_rptr; 4685 4686 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4687 "usb_ac_send_as_cmd: db_type=0x%x cmd=0x%x", 4688 mp->b_datap->db_type, iocp->ioc_cmd); 4689 4690 switch (mp->b_datap->db_type) { 4691 case M_CTL: 4692 switch (iocp->ioc_cmd) { 4693 case USB_AUDIO_SET_FORMAT: 4694 /* 4695 * This command sets mixer format data 4696 * and returns alternate setting that matches 4697 */ 4698 ASSERT(mp->b_cont != NULL); 4699 ASSERT((mp->b_cont->b_wptr - mp->b_cont->b_rptr) == 4700 sizeof (int)); 4701 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4702 "alternate returned %d", 4703 *((int *)(mp->b_cont->b_rptr))); 4704 4705 streams_infop->acs_ac_to_as_req.acr_curr_format. 4706 fmt_alt = *((int *)(mp->b_cont->b_rptr)); 4707 4708 /*FALLTHROUGH*/ 4709 case USB_AUDIO_SET_SAMPLE_FREQ: 4710 case USB_AUDIO_SETUP: 4711 case USB_AUDIO_START_PLAY: 4712 case USB_AUDIO_PAUSE_PLAY: 4713 case USB_AUDIO_START_RECORD: 4714 case USB_AUDIO_STOP_RECORD: 4715 case USB_AUDIO_TEARDOWN: 4716 error = USB_SUCCESS; 4717 break; 4718 default: 4719 break; 4720 } 4721 break; 4722 case M_ERROR: 4723 default: 4724 error = USB_FAILURE; 4725 } 4726 4727 if (mp) { 4728 usb_ac_free_mblk(mp); 4729 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4730 } 4731 4732 return (error); 4733 } 4734 4735 4736 /* 4737 * usb_ac_allocate_req_mblk: 4738 * Allocate a message block with the specified M_CTL cmd, 4739 * The 2nd mblk contains the data for the command with a length len 4740 */ 4741 static mblk_t * 4742 usb_ac_allocate_req_mblk(usb_ac_state_t *uacp, int cmd, void *buf, uint_t len) 4743 { 4744 mblk_t *mp, *mp2; 4745 struct iocblk *mctlmsg; 4746 4747 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4748 "usb_ac_allocate_req_mblk: cmd=0x%x, buf=0x%p, len=%d", 4749 cmd, buf, len); 4750 4751 mp = allocb_wait(sizeof (struct iocblk), BPRI_HI, STR_NOSIG, NULL); 4752 mp->b_datap->db_type = M_CTL; 4753 mctlmsg = (struct iocblk *)mp->b_datap->db_base; 4754 mctlmsg->ioc_cmd = cmd; 4755 mctlmsg->ioc_count = len; 4756 4757 mp->b_wptr = mp->b_wptr + sizeof (struct iocblk); 4758 4759 if ((len == 0) || (buf == NULL)) { 4760 4761 return (mp); 4762 } 4763 4764 mp2 = allocb_wait(len, BPRI_HI, STR_NOSIG, NULL); 4765 mp->b_cont = mp2; 4766 bcopy(buf, mp->b_cont->b_datap->db_base, len); 4767 mp->b_cont->b_wptr = mp->b_cont->b_wptr + len; 4768 4769 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4770 "usb_ac_allocate_req_mblk: mp=0x%p", mp); 4771 4772 return (mp); 4773 } 4774 4775 4776 /* 4777 * usb_ac_free_mblk: 4778 * Free the message block 4779 */ 4780 static void 4781 usb_ac_free_mblk(mblk_t *mp) 4782 { 4783 if (mp->b_cont) { 4784 freemsg(mp->b_cont); 4785 mp->b_cont = NULL; 4786 } 4787 freemsg(mp); 4788 } 4789 4790 4791 /* 4792 * usb_ac_serialize/release_access: 4793 */ 4794 static void 4795 usb_ac_serialize_access(usb_ac_state_t *uacp) 4796 { 4797 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0); 4798 } 4799 4800 static void 4801 usb_ac_release_access(usb_ac_state_t *uacp) 4802 { 4803 usb_release_access(uacp->usb_ac_ser_acc); 4804 } 4805 4806 4807 static void 4808 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep) 4809 { 4810 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 4811 4812 if (usb_ac_statep->usb_ac_pm != NULL) { 4813 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4814 usb_ac_statep->usb_ac_pm->acpm_pm_busy++; 4815 4816 USB_DPRINTF_L4(PRINT_MASK_PM, 4817 usb_ac_statep->usb_ac_log_handle, 4818 "usb_ac_pm_busy_component: %d", 4819 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4820 4821 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4822 4823 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) != 4824 DDI_SUCCESS) { 4825 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4826 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 4827 4828 USB_DPRINTF_L2(PRINT_MASK_PM, 4829 usb_ac_statep->usb_ac_log_handle, 4830 "usb_ac_pm_busy_component failed: %d", 4831 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4832 4833 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4834 } 4835 } 4836 } 4837 4838 4839 static void 4840 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep) 4841 { 4842 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 4843 4844 if (usb_ac_statep->usb_ac_pm != NULL) { 4845 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) == 4846 DDI_SUCCESS) { 4847 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4848 ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0); 4849 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 4850 4851 USB_DPRINTF_L4(PRINT_MASK_PM, 4852 usb_ac_statep->usb_ac_log_handle, 4853 "usb_ac_pm_idle_component: %d", 4854 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4855 4856 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4857 } 4858 } 4859 } 4860