usb_ac.c revision 7656:2621e50fdf4a
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27/* 28 * AUDIO CONTROL Driver: usb_ac is a streams multiplexor that sits 29 * on top of usb_as and hid and is responsible for 30 * (1) providing the entry points to audio mixer framework, (2) passing 31 * streams messages to and from usb_as and hid and (3) processing 32 * control messages that it can handle. 33 * 34 * 1. Mixer entry points are: usb_ac_setup(), usb_ac_teardown(), 35 * usb_ac_set_config(), usb_ac_set_format(), usb_ac_start_play(), 36 * usb_ac_pause_play(), usb_ac_stop_play, usb_ac_start_record(), 37 * usb_ac_stop_record(). 38 * 2. usb_ac is a streams driver that passes streams messages down to 39 * usb_as that selects the correct alternate with passed format 40 * parameters, sets sample frequency, starts play/record, stops 41 * play/record, pause play/record, open/close isoc pipe. 42 * 3. usb_ac handles the set_config command through the default pipe 43 * of sound control interface of the audio device in a synchronous 44 * manner. 45 * 46 * Serialization: usb_ac being a streams driver and having the requirement 47 * of making non-blockings calls (USBA or streams or mixer) needs to drop 48 * mutexes over such calls. But at the same time, a competing thread 49 * can't be allowed to interfere with (1) pipe, (2) streams state. 50 * So we need some kind of serialization among the asynchronous 51 * threads that can run in the driver. The serialization is mostly 52 * needed to avoid races among open/close/events/power entry points 53 * etc. Once a routine takes control, it checks if the resource (pipe or 54 * stream or dev state) is still accessible. If so, it proceeds with 55 * its job and until it completes, no other thread requiring the same 56 * resource can run. 57 * 58 * PM model in usb_ac: Raise power during attach. If a device is not at full 59 * power, raise power in the entry points. After the command is over, 60 * pm_idle_component() is called. The power is lowered in detach(). 61 * 62 * locking: Warlock is not aware of the automatic locking mechanisms for 63 * streams drivers. 64 */ 65#include <sys/usb/usba/usbai_version.h> 66#include <sys/usb/usba.h> 67#include <sys/stropts.h> 68#include <sys/sunndi.h> 69#include <sys/ndi_impldefs.h> 70#include <sys/strsubr.h> 71#include <sys/strsun.h> 72 73#include <sys/audio.h> 74#include <sys/audiovar.h> 75#include <sys/audio/audio_support.h> 76#include <sys/audio/audio_src.h> 77#include <sys/mixer.h> 78#include <sys/audio/audio_mixer.h> 79 80#include <sys/usb/clients/audio/usb_audio.h> 81#include <sys/usb/clients/audio/usb_mixer.h> 82#include <sys/usb/clients/audio/usb_ac/usb_ac.h> 83 84/* debug support */ 85uint_t usb_ac_errlevel = USB_LOG_L4; 86uint_t usb_ac_errmask = (uint_t)-1; 87uint_t usb_ac_instance_debug = (uint_t)-1; 88 89#ifdef DEBUG 90/* 91 * tunable timeout for usb_as response, allow at least 10 secs for control 92 * cmd to timeout 93 */ 94int usb_ac_wait_timeout = 10000000; 95#endif 96 97/* 98 * table for converting term types of input and output terminals 99 * to SADA port types (pretty rough mapping) 100 */ 101static struct { 102 ushort_t term_type; 103 ushort_t port_type; 104} usb_ac_term_type_map[] = { 105{ USB_AUDIO_TERM_TYPE_STREAMING, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 106{ USB_AUDIO_TERM_TYPE_MICROPHONE, AUDIO_MICROPHONE }, 107{ USB_AUDIO_TERM_TYPE_DT_MICROPHONE, AUDIO_MICROPHONE }, 108{ USB_AUDIO_TERM_TYPE_PERS_MICROPHONE, AUDIO_MICROPHONE }, 109{ USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE, AUDIO_MICROPHONE }, 110{ USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY, AUDIO_MICROPHONE }, 111{ USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY, AUDIO_MICROPHONE }, 112{ USB_AUDIO_TERM_TYPE_SPEAKER, AUDIO_SPEAKER }, 113{ USB_AUDIO_TERM_TYPE_HEADPHONES, AUDIO_HEADPHONE }, 114{ USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO, AUDIO_LINE_OUT }, 115{ USB_AUDIO_TERM_TYPE_DT_SPEAKER, AUDIO_SPEAKER }, 116{ USB_AUDIO_TERM_TYPE_ROOM_SPEAKER, AUDIO_SPEAKER }, 117{ USB_AUDIO_TERM_TYPE_COMM_SPEAKER, AUDIO_SPEAKER }, 118{ USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER, AUDIO_SPEAKER }, 119{ USB_AUDIO_TERM_TYPE_HANDSET, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 120{ USB_AUDIO_TERM_TYPE_HEADSET, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 121{ USB_AUDIO_TERM_TYPE_SPEAKERPHONE, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 122{ USB_AUDIO_TERM_TYPE_ECHO_SUPP_SPEAKERPHONE, 123 AUDIO_LINE_IN|AUDIO_LINE_OUT }, 124{ USB_AUDIO_TERM_TYPE_ECHO_CANCEL_SPEAKERPHONE, 125 AUDIO_LINE_IN|AUDIO_LINE_OUT }, 126{ USB_AUDIO_TERM_TYPE_PHONE_LINE, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 127{ USB_AUDIO_TERM_TYPE_TELEPHONE, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 128{ USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 129{ USB_AUDIO_TERM_TYPE_ANALOG_CONNECTOR, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 130{ USB_AUDIO_TERM_TYPE_DIGITAL_AUDIO_IF, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 131{ USB_AUDIO_TERM_TYPE_LINE_CONNECTOR, AUDIO_LINE_IN|AUDIO_LINE_OUT }, 132{ USB_AUDIO_TERM_TYPE_LEGACY_AUDIO_CONNECTOR, 133 AUDIO_LINE_IN|AUDIO_LINE_OUT }, 134{ USB_AUDIO_TERM_TYPE_SPDIF_IF, AUDIO_SPDIF_IN }, 135{ USB_AUDIO_TERM_TYPE_1394_DA_STREAM, 136 AUDIO_LINE_IN|AUDIO_LINE_OUT }, 137{ USB_AUDIO_TERM_TYPE_1394_DV_STREAM_SNDTRCK, 138 AUDIO_LINE_IN|AUDIO_LINE_OUT }, 139{ 0, 0 } 140}; 141 142 143/* 144 * Module linkage routines for the kernel 145 */ 146static int usb_ac_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 147static int usb_ac_attach(dev_info_t *, ddi_attach_cmd_t); 148static int usb_ac_detach(dev_info_t *, ddi_detach_cmd_t); 149static int usb_ac_power(dev_info_t *, int, int); 150 151/* 152 * STREAMS module entry points 153 */ 154static int usb_ac_open(queue_t *, dev_t *, int, int, cred_t *); 155static int usb_ac_close(queue_t *, int, cred_t *); 156static int usb_ac_uwput(queue_t *, mblk_t *); 157static int usb_ac_lrput(queue_t *, mblk_t *); 158 159/* plumbing */ 160static usb_ac_plumbed_t *usb_ac_get_plumb_info(usb_ac_state_t *, char *, 161 uchar_t); 162static usb_ac_plumbed_t *usb_ac_get_plumb_info_from_lrq(usb_ac_state_t *, 163 queue_t *); 164static uint_t usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t, 165 uint_t); 166static void usb_ac_plumb_ioctl(queue_t *, mblk_t *); 167 168 169/* registration */ 170static int usb_ac_get_curr_n_channels(usb_ac_state_t *, int); 171static usb_audio_formats_t *usb_ac_get_curr_format(usb_ac_state_t *, int); 172 173/* descriptor handling */ 174static int usb_ac_handle_descriptors(usb_ac_state_t *); 175static void usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t); 176static void usb_ac_alloc_unit(usb_ac_state_t *, uint_t); 177static void usb_ac_free_all_units(usb_ac_state_t *); 178static void usb_ac_setup_connections(usb_ac_state_t *); 179static void usb_ac_map_termtype_to_port(usb_ac_state_t *, uint_t); 180 181/* power management */ 182static int usb_ac_pwrlvl0(usb_ac_state_t *); 183static int usb_ac_pwrlvl1(usb_ac_state_t *); 184static int usb_ac_pwrlvl2(usb_ac_state_t *); 185static int usb_ac_pwrlvl3(usb_ac_state_t *); 186static void usb_ac_create_pm_components(dev_info_t *, usb_ac_state_t *); 187static void usb_ac_pm_busy_component(usb_ac_state_t *); 188static void usb_ac_pm_idle_component(usb_ac_state_t *); 189 190/* event handling */ 191static int usb_ac_disconnect_event_cb(dev_info_t *); 192static int usb_ac_reconnect_event_cb(dev_info_t *); 193static int usb_ac_cpr_suspend(dev_info_t *); 194static void usb_ac_cpr_resume(dev_info_t *); 195 196static usb_event_t usb_ac_events = { 197 usb_ac_disconnect_event_cb, 198 usb_ac_reconnect_event_cb, 199 NULL, NULL 200}; 201 202/* misc. support */ 203static void usb_ac_restore_device_state(dev_info_t *, usb_ac_state_t *); 204static int usb_ac_cleanup(dev_info_t *, usb_ac_state_t *); 205static void usb_ac_serialize_access(usb_ac_state_t *); 206static void usb_ac_release_access(usb_ac_state_t *); 207 208static void usb_ac_push_unit_id(usb_ac_state_t *, uint_t); 209static void usb_ac_pop_unit_id(usb_ac_state_t *, uint_t); 210static void usb_ac_show_traverse_path(usb_ac_state_t *); 211static int usb_ac_check_path(usb_ac_state_t *, uint_t); 212 213static uint_t usb_ac_traverse_connections(usb_ac_state_t *, uint_t, uint_t, 214 uint_t, uint_t, uint_t, uint_t, 215 uint_t *, uint_t, uint_t *, 216 int (*func)(usb_ac_state_t *, uint_t, uint_t, 217 uint_t, uint_t, uint_t, uint_t *)); 218static uint_t usb_ac_set_port(usb_ac_state_t *, uint_t, uint_t); 219static uint_t usb_ac_set_control(usb_ac_state_t *, uint_t, uint_t, 220 uint_t, uint_t, uint_t, 221 uint_t *, uint_t, 222 int (*func)(usb_ac_state_t *, uint_t, uint_t, 223 uint_t, uint_t, uint_t, uint_t *)); 224static uint_t usb_ac_set_monitor_gain_control(usb_ac_state_t *, uint_t, 225 uint_t, uint_t, uint_t, uint_t, 226 uint_t *, uint_t, 227 int (*func)(usb_ac_state_t *, uint_t, uint_t, 228 uint_t, uint_t, uint_t, uint_t *)); 229static uint_t usb_ac_traverse_all_units(usb_ac_state_t *, uint_t, uint_t, 230 uint_t, uint_t, uint_t, uint_t *, 231 uint_t, uint_t *, 232 int (*func)(usb_ac_state_t *, uint_t, uint_t, 233 uint_t, uint_t, uint_t, uint_t *)); 234static int usb_ac_update_port(usb_ac_state_t *, uint_t, 235 uint_t, uint_t, uint_t, uint_t, uint_t *); 236static int usb_ac_set_selector(usb_ac_state_t *, uint_t, 237 uint_t, uint_t, uint_t, uint_t, uint_t *); 238static int usb_ac_feature_unit_check(usb_ac_state_t *, uint_t, 239 uint_t, uint_t, uint_t, uint_t, uint_t *); 240static int usb_ac_set_gain(usb_ac_state_t *, uint_t, 241 uint_t, uint_t, uint_t, uint_t, uint_t *); 242static int usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t, 243 uint_t, uint_t, uint_t, uint_t, uint_t *); 244static int usb_ac_set_mute(usb_ac_state_t *, uint_t, uint_t, 245 uint_t, uint_t, uint_t, uint_t *); 246static int usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir, 247 int); 248static int usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int, 249 int); 250static void usb_ac_free_mblk(mblk_t *); 251static mblk_t *usb_ac_allocate_req_mblk(usb_ac_state_t *, int, 252 void *, uint_t); 253static int usb_ac_send_as_cmd(usb_ac_state_t *, usb_ac_plumbed_t *, 254 int, void *); 255static int usb_ac_send_format_cmd(audiohdl_t, int, int, int, 256 int, int, int); 257static int usb_ac_do_setup(audiohdl_t, int, int); 258static void usb_ac_do_teardown(audiohdl_t, int, int); 259static void usb_ac_do_pause_play(audiohdl_t, int); 260static void usb_ac_do_stop_record(audiohdl_t, int); 261 262/* Mixer entry points */ 263static int usb_ac_setup(audiohdl_t, int, int); 264static void usb_ac_teardown(audiohdl_t, int, int); 265static int usb_ac_set_config(audiohdl_t, int, int, int, int, int); 266static int usb_ac_set_format(audiohdl_t, int, int, int, int, int, int); 267static int usb_ac_start_play(audiohdl_t, int); 268static void usb_ac_pause_play(audiohdl_t, int); 269static void usb_ac_stop_play(audiohdl_t, int); 270static int usb_ac_start_record(audiohdl_t, int); 271static void usb_ac_stop_record(audiohdl_t, int); 272static int usb_ac_restore_audio_state(usb_ac_state_t *, int); 273 274/* 275 * External functions 276 */ 277extern int space_store(char *key, uintptr_t ptr); 278extern void space_free(char *); 279 280 281/* 282 * mixer registration data 283 */ 284static am_ad_entry_t usb_ac_entry = { 285 usb_ac_setup, /* ad_setup() */ 286 usb_ac_teardown, /* ad_teardown() */ 287 usb_ac_set_config, /* ad_set_config() */ 288 usb_ac_set_format, /* ad_set_format() */ 289 usb_ac_start_play, /* ad_start_play() */ 290 usb_ac_pause_play, /* ad_pause_play() */ 291 usb_ac_stop_play, /* ad_stop_play() */ 292 usb_ac_start_record, /* ad_start_record() */ 293 usb_ac_stop_record, /* ad_stop_record() */ 294 NULL, /* ad_ioctl() */ 295 NULL /* ad_iocdata() */ 296}; 297 298/* anchor for soft state structures */ 299static void *usb_ac_statep; 300 301/* for passing soft state etc. to usb_ac_dacf module */ 302static usb_ac_state_space_t ssp; 303 304/* STREAMS driver id and limit value structure */ 305static struct module_info usb_ac_modinfo = { 306 0xffff, /* module ID number */ 307 "usb_ac", /* module name */ 308 USB_AUDIO_MIN_PKTSZ, /* minimum packet size */ 309 USB_AUDIO_MAX_PKTSZ, /* maximum packet size */ 310 USB_AC_HIWATER, /* high water mark */ 311 USB_AC_LOWATER /* low water mark */ 312}; 313 314/* STREAMS queue processing procedures structures */ 315/* upper read queue */ 316static struct qinit usb_ac_urqueue = { 317 NULL, /* put procedure */ 318 NULL, /* service procedure */ 319 usb_ac_open, /* open procedure */ 320 usb_ac_close, /* close procedure */ 321 NULL, /* unused */ 322 &usb_ac_modinfo, /* module parameters */ 323 NULL /* module statistics */ 324}; 325 326/* upper write queue */ 327static struct qinit usb_ac_uwqueue = { 328 usb_ac_uwput, /* put procedure */ 329 audio_sup_wsvc, /* service procedure */ 330 NULL, /* open procedure */ 331 NULL, /* close procedure */ 332 NULL, /* unused */ 333 &usb_ac_modinfo, /* module parameters */ 334 NULL /* module statistics */ 335}; 336 337/* lower read queue */ 338static struct qinit usb_ac_lrqueue = { 339 usb_ac_lrput, 340 NULL, 341 NULL, 342 NULL, 343 NULL, 344 &usb_ac_modinfo, /* module parameters */ 345 NULL 346}; 347 348/* lower write queue */ 349static struct qinit usb_ac_lwqueue = { 350 NULL, 351 NULL, 352 NULL, 353 NULL, 354 NULL, 355 &usb_ac_modinfo, /* module parameters */ 356 NULL 357}; 358 359/* STREAMS entity declaration structure */ 360static struct streamtab usb_ac_str_info = { 361 &usb_ac_urqueue, /* upper read queue */ 362 &usb_ac_uwqueue, /* upper write queue */ 363 &usb_ac_lrqueue, /* lower read queue */ 364 &usb_ac_lwqueue, /* lower write queue */ 365}; 366 367/* 368 * DDI Structures 369 * 370 * Entry points structure 371 */ 372static struct cb_ops usb_ac_cb_ops = { 373 nulldev, /* cb_open */ 374 nulldev, /* cb_close */ 375 nodev, /* cb_strategy */ 376 nodev, /* cb_print */ 377 nodev, /* cb_dump */ 378 nodev, /* cb_read */ 379 nodev, /* cb_write */ 380 nodev, /* cb_ioctl */ 381 nodev, /* cb_devmap */ 382 nodev, /* cb_mmap */ 383 nodev, /* cb_segmap */ 384 nochpoll, /* cb_chpoll */ 385 ddi_prop_op, /* cb_prop_op */ 386 &usb_ac_str_info, /* cb_str */ 387 D_MP | D_MTPERQ, /* cb_flag */ 388 CB_REV, /* cb_rev */ 389 nodev, /* cb_aread */ 390 nodev, /* cb_arwite */ 391}; 392 393/* Device operations structure */ 394static struct dev_ops usb_ac_dev_ops = { 395 DEVO_REV, /* devo_rev */ 396 0, /* devo_refcnt */ 397 usb_ac_getinfo, /* devo_getinfo */ 398 nulldev, /* devo_identify - obsolete */ 399 nulldev, /* devo_probe - not needed */ 400 usb_ac_attach, /* devo_attach */ 401 usb_ac_detach, /* devo_detach */ 402 nodev, /* devo_reset */ 403 &usb_ac_cb_ops, /* devi_cb_ops */ 404 NULL, /* devo_busb_ac_ops */ 405 usb_ac_power, /* devo_power */ 406 ddi_quiesce_not_supported, /* devo_quiesce */ 407}; 408 409/* Linkage structure for loadable drivers */ 410static struct modldrv usb_ac_modldrv = { 411 &mod_driverops, /* drv_modops */ 412 "USB Audio Control Driver", /* drv_linkinfo */ 413 &usb_ac_dev_ops /* drv_dev_ops */ 414}; 415 416/* Module linkage structure */ 417static 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 */ 431int 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 461int 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 476int 477_info(struct modinfo *modinfop) 478{ 479 return (mod_info(&usb_ac_modlinkage, modinfop)); 480} 481 482/*ARGSUSED*/ 483static int 484usb_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 516extern uint_t nproc; 517#define INIT_PROCESS_CNT 3 518 519static int 520usb_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); 725fail: 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 736static int 737usb_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 */ 768static int 769usb_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", (void *)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*/ 887static int 888usb_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", (void *)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 (void *)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", 983 (void *)q, uacp->usb_ac_busy_count); 984 985 mutex_exit(&uacp->usb_ac_mutex); 986 987 return (0); 988} 989 990 991/* 992 * usb_ac_close : 993 * Close entry point 994 */ 995/*ARGSUSED*/ 996static int 997usb_ac_close(queue_t *q, int flag, cred_t *credp) 998{ 999 dev_t dev = audio_sup_get_qptr_dev(q); 1000 int minor = getminor(dev); 1001 int instance = audio_sup_get_qptr_instance(q); 1002 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance); 1003 int rval; 1004 1005 mutex_enter(&uacp->usb_ac_mutex); 1006 1007 USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1008 "usb_ac_close: Begin q=0x%p, opencount=%d", 1009 (void *)q, uacp->usb_ac_busy_count); 1010 1011 /* closing the mux? */ 1012 if (minor == uacp->usb_ac_mux_minor) { 1013 USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1014 "usb_ac_close: closing mux plumbing stream"); 1015 mutex_exit(&uacp->usb_ac_mutex); 1016 1017 /* Wait till all activity in the default pipe has drained */ 1018 usb_ac_serialize_access(uacp); 1019 usb_ac_release_access(uacp); 1020 1021 audio_sup_free_qptr(q); 1022 qprocsoff(q); 1023 1024 return (0); 1025 } 1026 1027 mutex_exit(&uacp->usb_ac_mutex); 1028 1029 rval = audio_sup_close(q, flag, credp); 1030 1031 if (rval != 0) { 1032 USB_DPRINTF_L2(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1033 "audio_sup_close fails %d", rval); 1034 1035 return (rval); 1036 } 1037 1038 mutex_enter(&uacp->usb_ac_mutex); 1039 1040 /* normal streams closing */ 1041 ASSERT(uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED); 1042 1043 uacp->usb_ac_busy_count --; 1044 1045 USB_DPRINTF_L4(PRINT_MASK_CLOSE, uacp->usb_ac_log_handle, 1046 "usb_ac_close: End rval=%d q=0x%p, opencount=%d", 1047 rval, (void *)q, uacp->usb_ac_busy_count); 1048 1049 mutex_exit(&uacp->usb_ac_mutex); 1050 1051 usb_ac_pm_idle_component(uacp); 1052 1053 return (0); 1054} 1055 1056 1057/* 1058 * usb_ac_uwput: 1059 * write put entry point for the upper mux. Only PLUMB/UNPLUMB ioctls 1060 * are processed here. All other ioctls are passed to audio_sup routines 1061 * for further processing. 1062 */ 1063static int 1064usb_ac_uwput(queue_t *q, mblk_t *mp) 1065{ 1066 int instance = audio_sup_get_qptr_instance(q); 1067 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance); 1068 int error = DDI_SUCCESS; 1069 1070 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1071 "usb_ac_uwput: q=0x%p, mp=0x%p", (void *)q, (void *)mp); 1072 1073 ASSERT(mp != NULL); 1074 ASSERT(mp->b_datap != NULL); 1075 1076 mutex_enter(&uacp->usb_ac_mutex); 1077 if (uacp->usb_ac_wq == q) { 1078 ASSERT(mp->b_datap->db_type == M_IOCTL); 1079 1080 mutex_exit(&uacp->usb_ac_mutex); 1081 1082 /* ioctl from plumbing thread (namely P_LINK) */ 1083 usb_ac_plumb_ioctl(q, mp); 1084 1085 return (error); 1086 } 1087 mutex_exit(&uacp->usb_ac_mutex); 1088 1089 /* Pass to audio_sup routine */ 1090 (void) audio_sup_wput(q, mp); 1091 1092 return (error); 1093} 1094 1095 1096/* 1097 * usb_ac_lrput: 1098 * read put entry point for the lower mux. Get the response from the 1099 * lower module, signal usb_ac_send_as_cmd(), the thread that is waiting 1100 * for a response to a message sent earlier anbd pass the response 1101 * message block. 1102 */ 1103static int 1104usb_ac_lrput(queue_t *q, mblk_t *mp) 1105{ 1106 int instance = audio_sup_get_qptr_instance(q); 1107 usb_ac_state_t *uacp; 1108 int error = DDI_SUCCESS; 1109 usb_ac_plumbed_t *plumb_infop; 1110 usb_ac_streams_info_t *streams_infop = NULL; 1111 int val; 1112 char val1; 1113 struct iocblk *iocp; 1114 1115 uacp = ddi_get_soft_state(usb_ac_statep, instance); 1116 1117 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1118 "usb_ac_lrput: q=0x%p, mp=0x%p, instance=%d", 1119 (void *)q, (void *)mp, instance); 1120 ASSERT(mp != NULL); 1121 1122 mutex_enter(&uacp->usb_ac_mutex); 1123 plumb_infop = usb_ac_get_plumb_info_from_lrq(uacp, q); 1124 ASSERT(plumb_infop != NULL); 1125 1126 switch (mp->b_datap->db_type) { 1127 case M_CTL: 1128 case M_ERROR: 1129 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1130 "M_CTL/M_ERROR"); 1131 1132 switch (plumb_infop->acp_driver) { 1133 case USB_AS_PLUMBED: 1134 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1135 "reply from usb_as, lrq=0x%p", (void *)q); 1136 streams_infop = (usb_ac_streams_info_t *) 1137 plumb_infop->acp_data; 1138 ASSERT(streams_infop != NULL); 1139 streams_infop->acs_ac_to_as_req.acr_reply_mp = mp; 1140 streams_infop->acs_ac_to_as_req.acr_wait_flag = 0; 1141 cv_signal(&streams_infop->acs_ac_to_as_req.acr_cv); 1142 1143 break; 1144 case USB_AH_PLUMBED: 1145 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1146 "M_CTL from hid, lrq=0x%p", (void *)q); 1147 1148 iocp = (struct iocblk *)mp->b_rptr; 1149 ASSERT(mp->b_cont != NULL); 1150 1151 if (uacp->usb_ac_registered_with_mixer) { 1152 1153 val1 = *((char *)mp->b_cont->b_rptr); 1154 val = (int)val1; 1155 1156 USB_DPRINTF_L4(PRINT_MASK_ALL, 1157 uacp->usb_ac_log_handle, "val1=0x%x(%d)," 1158 "val=0x%x(%d)", val1, val1, val, val); 1159 1160 switch (iocp->ioc_cmd) { 1161 /* Handle relative volume change */ 1162 case USB_AUDIO_VOL_CHANGE: 1163 /* prevent unplumbing */ 1164 uacp->usb_ac_busy_count++; 1165 if (uacp->usb_ac_plumbing_state == 1166 USB_AC_STATE_PLUMBED) { 1167 mutex_exit(&uacp->usb_ac_mutex); 1168 (void) am_hw_state_change( 1169 uacp->usb_ac_audiohdl, 1170 AM_HWSC_SET_GAIN_DELTA, 1171 AUDIO_PLAY, val, 1172 AUDIO_NO_SLEEP); 1173 mutex_enter(&uacp-> 1174 usb_ac_mutex); 1175 } 1176 uacp->usb_ac_busy_count--; 1177 /* FALLTHRU */ 1178 case USB_AUDIO_MUTE: 1179 default: 1180 freemsg(mp); 1181 break; 1182 } 1183 } else { 1184 freemsg(mp); 1185 } 1186 1187 break; 1188 default: 1189 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1190 "M_CTL from unknown module(%s)", 1191 ddi_driver_name(plumb_infop->acp_dip)); 1192 freemsg(mp); 1193 } 1194 1195 break; 1196 default: 1197 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1198 "Unknown type=%d", mp->b_datap->db_type); 1199 usb_ac_free_mblk(mp); 1200 } 1201 mutex_exit(&uacp->usb_ac_mutex); 1202 1203 /* 1204 * Nobody is waiting; nothing to send up. 1205 */ 1206 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1207 "usb_ac_lrput: done"); 1208 1209 return (error); 1210} 1211 1212 1213/* 1214 * Power Management 1215 * usb_ac_power: 1216 * power entry point 1217 */ 1218static int 1219usb_ac_power(dev_info_t *dip, int comp, int level) 1220{ 1221 int instance = ddi_get_instance(dip); 1222 usb_ac_state_t *uacp; 1223 usb_ac_power_t *uacpm; 1224 int rval = DDI_FAILURE; 1225 1226 uacp = ddi_get_soft_state(usb_ac_statep, instance); 1227 1228 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1229 "usb_ac_power: comp=%d level=%d", comp, level); 1230 1231 mutex_enter(&uacp->usb_ac_mutex); 1232 uacpm = uacp->usb_ac_pm; 1233 1234 if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) { 1235 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1236 "usb_ac_power: illegal level=%d pwr_states=%d", 1237 level, uacpm->acpm_pwr_states); 1238 1239 goto done; 1240 } 1241 1242 switch (level) { 1243 case USB_DEV_OS_PWR_OFF: 1244 rval = usb_ac_pwrlvl0(uacp); 1245 break; 1246 case USB_DEV_OS_PWR_1: 1247 rval = usb_ac_pwrlvl1(uacp); 1248 break; 1249 case USB_DEV_OS_PWR_2: 1250 rval = usb_ac_pwrlvl2(uacp); 1251 break; 1252 case USB_DEV_OS_FULL_PWR: 1253 rval = usb_ac_pwrlvl3(uacp); 1254 break; 1255 } 1256 1257done: 1258 mutex_exit(&uacp->usb_ac_mutex); 1259 1260 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 1261} 1262 1263 1264/* 1265 * functions to handle power transition for various levels 1266 * These functions act as place holders to issue USB commands 1267 * to the devices to change their power levels 1268 * Level 0 = Device is powered off 1269 * Level 3 = Device if full powered 1270 * Level 1,2 = Intermediate power level of the device as implemented 1271 * by the hardware. 1272 * Note that Level 0 is OS power-off and Level 3 is OS full-power. 1273 */ 1274static int 1275usb_ac_pwrlvl0(usb_ac_state_t *uacp) 1276{ 1277 usb_ac_power_t *uacpm; 1278 int rval; 1279 1280 uacpm = uacp->usb_ac_pm; 1281 1282 switch (uacp->usb_ac_dev_state) { 1283 case USB_DEV_ONLINE: 1284 /* Deny the powerdown request if the device is busy */ 1285 if (uacpm->acpm_pm_busy != 0) { 1286 1287 return (USB_FAILURE); 1288 } 1289 1290 /* Issue USB D3 command to the device here */ 1291 rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip); 1292 ASSERT(rval == USB_SUCCESS); 1293 1294 uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN; 1295 uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF; 1296 1297 /* FALLTHRU */ 1298 case USB_DEV_DISCONNECTED: 1299 case USB_DEV_SUSPENDED: 1300 case USB_DEV_PWRED_DOWN: 1301 default: 1302 return (USB_SUCCESS); 1303 } 1304} 1305 1306 1307/* ARGSUSED */ 1308static int 1309usb_ac_pwrlvl1(usb_ac_state_t *uacp) 1310{ 1311 int rval; 1312 1313 /* Issue USB D2 command to the device here */ 1314 rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip); 1315 ASSERT(rval == USB_SUCCESS); 1316 1317 return (USB_FAILURE); 1318} 1319 1320 1321/* ARGSUSED */ 1322static int 1323usb_ac_pwrlvl2(usb_ac_state_t *uacp) 1324{ 1325 int rval; 1326 1327 rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip); 1328 ASSERT(rval == USB_SUCCESS); 1329 1330 return (USB_FAILURE); 1331} 1332 1333 1334static int 1335usb_ac_pwrlvl3(usb_ac_state_t *uacp) 1336{ 1337 usb_ac_power_t *uacpm; 1338 int rval; 1339 1340 uacpm = uacp->usb_ac_pm; 1341 1342 switch (uacp->usb_ac_dev_state) { 1343 case USB_DEV_PWRED_DOWN: 1344 /* Issue USB D0 command to the device here */ 1345 rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip); 1346 ASSERT(rval == USB_SUCCESS); 1347 1348 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 1349 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR; 1350 /* FALLTHRU */ 1351 case USB_DEV_ONLINE: 1352 /* we are already in full power */ 1353 1354 /* FALLTHRU */ 1355 case USB_DEV_DISCONNECTED: 1356 case USB_DEV_SUSPENDED: 1357 1358 return (USB_SUCCESS); 1359 default: 1360 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1361 "usb_ac_pwerlvl3: Illegal dev_state"); 1362 1363 return (USB_FAILURE); 1364 } 1365} 1366 1367 1368static void 1369usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp) 1370{ 1371 usb_ac_power_t *uacpm; 1372 uint_t pwr_states; 1373 1374 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1375 "usb_ac_create_pm_components: begin"); 1376 1377 /* Allocate the state structure */ 1378 uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP); 1379 uacp->usb_ac_pm = uacpm; 1380 uacpm->acpm_state = uacp; 1381 uacpm->acpm_capabilities = 0; 1382 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR; 1383 1384 if (usb_create_pm_components(dip, &pwr_states) == 1385 USB_SUCCESS) { 1386 if (usb_handle_remote_wakeup(dip, 1387 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) { 1388 uacpm->acpm_wakeup_enabled = 1; 1389 1390 USB_DPRINTF_L4(PRINT_MASK_PM, 1391 uacp->usb_ac_log_handle, 1392 "remote Wakeup enabled"); 1393 } 1394 uacpm->acpm_pwr_states = (uint8_t)pwr_states; 1395 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 1396 } else { 1397 if (uacpm) { 1398 kmem_free(uacpm, sizeof (usb_ac_power_t)); 1399 uacp->usb_ac_pm = NULL; 1400 } 1401 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1402 "pm not enabled"); 1403 } 1404 1405 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle, 1406 "usb_ac_create_pm_components: end"); 1407} 1408 1409 1410/* 1411 * usb_ac_plumb_ioctl: 1412 * IOCTL issued from plumbing thread (only P_LINK_LH/P_UNLINK for now 1413 * caused by ldi_ioctl). Maybe we will need to use this function 1414 * to issue other IOCTLS to children in future from plumbing thread 1415 */ 1416static void 1417usb_ac_plumb_ioctl(queue_t *q, mblk_t *mp) 1418{ 1419 int instance = audio_sup_get_qptr_instance(q); 1420 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, instance); 1421 struct iocblk *iocp; 1422 struct linkblk *linkp; 1423 int n; 1424 usb_ac_streams_info_t *streams_infop; 1425 1426 ASSERT(uacp != NULL); 1427 ASSERT(mp != NULL); 1428 ASSERT(mp->b_cont != NULL); 1429 1430 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1431 "usb_ac_plumb_ioctl, q=0x%p mp=0x%p instance=%d", 1432 (void *)q, (void *)mp, instance); 1433 1434 iocp = (struct iocblk *)mp->b_rptr; 1435 mutex_enter(&uacp->usb_ac_mutex); 1436 n = uacp->usb_ac_current_plumbed_index; 1437 1438 switch (iocp->ioc_cmd) { 1439 case I_PLINK: 1440 linkp = (struct linkblk *)mp->b_cont->b_rptr; 1441 1442 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1443 "LINK ioctl, index=%d linkblk ptr=0x%p", n, (void *)linkp); 1444 1445 /* 1446 * We keep track of the module that is being 1447 * currently plumbed through usb_ac_current_plumbed_index 1448 * to the plumb structure array. We set the lwq field 1449 * of the plumb structure here. 1450 */ 1451 ASSERT(uacp->usb_ac_plumbed[n].acp_lwq == NULL); 1452 uacp->usb_ac_plumbed[n].acp_lwq = linkp->l_qbot; 1453 uacp->usb_ac_plumbed[n].acp_lrq = RD(linkp->l_qbot); 1454 1455 audio_sup_set_qptr(uacp->usb_ac_plumbed[n].acp_lrq, 1456 uacp->usb_ac_dev, (void *)uacp); 1457 1458 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1459 "index=%d lwq=0x%p lrq=0x%p", n, (void *)linkp->l_qbot, 1460 (void *)RD(linkp->l_qbot)); 1461 break; 1462 case I_UNLINK: 1463 case I_PUNLINK: 1464 linkp = (struct linkblk *)mp->b_cont->b_rptr; 1465 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1466 "UNLINK ioctl, linkblk ptr=0x%p", (void *)linkp); 1467 1468 audio_sup_free_qptr(RD(linkp->l_qbot)); 1469 uacp->usb_ac_dev = 0; 1470 1471 if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) { 1472 1473 /* 1474 * we bzero the streams info and plumbed structure 1475 * since there is no guarantee that the next plumbing 1476 * will be identical 1477 */ 1478 streams_infop = (usb_ac_streams_info_t *) 1479 uacp->usb_ac_plumbed[n].acp_data; 1480 cv_destroy(&(streams_infop->acs_ac_to_as_req.acr_cv)); 1481 1482 /* bzero the relevant plumbing structure */ 1483 bzero(streams_infop, sizeof (usb_ac_streams_info_t)); 1484 } 1485 bzero(&uacp->usb_ac_plumbed[n], sizeof (usb_ac_plumbed_t)); 1486 1487 iocp->ioc_count = 0; 1488 break; 1489 default: 1490 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1491 "Unknown ioctl, cmd=%d", iocp->ioc_cmd); 1492 iocp->ioc_error = EINVAL; 1493 mutex_exit(&uacp->usb_ac_mutex); 1494 1495 goto iocnak; 1496 } 1497 1498 mutex_exit(&uacp->usb_ac_mutex); 1499 1500 /* 1501 * Common exit path for calls that return a positive 1502 * acknowledgment with a return value of 0. 1503 */ 1504 iocp->ioc_rval = 0; 1505 iocp->ioc_error = 0; 1506 mp->b_datap->db_type = M_IOCACK; 1507 qreply(q, mp); 1508 1509 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1510 "usb_ac_plumb_ioctl: End (ACK)"); 1511 1512 return; 1513 1514iocnak: 1515 1516 iocp->ioc_rval = 0; 1517 mp->b_datap->db_type = M_IOCNAK; 1518 qreply(q, mp); 1519 1520 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1521 "usb_ac_plumb_ioctl: End: (NAK)"); 1522} 1523 1524 1525/* 1526 * usb_ac_get_plumb_info: 1527 * Get plumb_info pointer that matches module "name" 1528 * If name = "usb_as", match the direction also (record or play) 1529 */ 1530static usb_ac_plumbed_t * 1531usb_ac_get_plumb_info(usb_ac_state_t *uacp, char *name, uchar_t reg_play_type) 1532{ 1533 int n; 1534 usb_ac_plumbed_t *plumb_infop = NULL; 1535 usb_as_registration_t *asreg; 1536 usb_ac_streams_info_t *asinfo; 1537 1538 for (n = 0; n < USB_AC_MAX_PLUMBED; n++) { 1539 if (uacp->usb_ac_plumbed[n].acp_dip == NULL) { 1540 continue; 1541 } 1542 if (strcmp(ddi_driver_name(uacp-> 1543 usb_ac_plumbed[n].acp_dip), name) != 0) { 1544 continue; 1545 } 1546 if (uacp->usb_ac_plumbed[n].acp_driver == USB_AS_PLUMBED) { 1547 asinfo = uacp->usb_ac_plumbed[n].acp_data; 1548 asreg = asinfo->acs_streams_reg; 1549 /* Match direction */ 1550 if (asreg->reg_mode & reg_play_type) { 1551 break; 1552 } 1553 } else if (uacp->usb_ac_plumbed[n].acp_driver == 1554 USB_AH_PLUMBED) { 1555 break; 1556 } 1557 } 1558 1559 if (n < USB_AC_MAX_PLUMBED) { 1560 plumb_infop = &uacp->usb_ac_plumbed[n]; 1561 } 1562 1563 return (plumb_infop); 1564} 1565 1566 1567/* 1568 * usb_ac_get_pinfo_from_lrq: 1569 * Get plumb_info pointer that matches the lrq passed 1570 */ 1571static usb_ac_plumbed_t * 1572usb_ac_get_plumb_info_from_lrq(usb_ac_state_t *uacp, queue_t *lrq) 1573{ 1574 int n; 1575 1576 for (n = 0; n < USB_AC_MAX_PLUMBED; n++) { 1577 if (uacp->usb_ac_plumbed[n].acp_lrq == lrq) { 1578 1579 return (&uacp->usb_ac_plumbed[n]); 1580 } 1581 } 1582 1583 return (NULL); 1584} 1585 1586 1587/* 1588 * usb_ac_get_featureID: 1589 * find out if there is at least one feature unit that supports 1590 * the request controls. 1591 * Return featureID or USB_AC_ID_NONE. 1592 */ 1593static uint_t 1594usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir, 1595 uint_t channel, uint_t control) 1596{ 1597 uint_t count = 0; 1598 1599 return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT, 1600 channel, control, USB_AC_FIND_ONE, &count, 0, 1601 usb_ac_feature_unit_check)); 1602} 1603 1604 1605/* 1606 * usb_ac_feature_unit_check: 1607 * check if a feature unit can support the required channel 1608 * and control combination. Return USB_SUCCESS or USB_FAILURE. 1609 * Called for each matching unit from usb_ac_traverse_connections. 1610 */ 1611/*ARGSUSED*/ 1612static int 1613usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID, 1614 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 1615{ 1616 usb_audio_feature_unit_descr1_t *feature_descrp; 1617 int n_channel_controls; 1618 1619 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1620 "usb_ac_feature_unit_check: ID=%d ch=%d cntrl=%d", 1621 featureID, channel, control); 1622 1623 ASSERT(featureID < uacp->usb_ac_max_unit); 1624 1625 /* 1626 * check if this control is supported on this channel 1627 */ 1628 feature_descrp = (usb_audio_feature_unit_descr1_t *) 1629 uacp->usb_ac_units[featureID].acu_descriptor; 1630 ASSERT(feature_descrp->bUnitID == featureID); 1631 1632 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1633 "bControlSize=%d", feature_descrp->bControlSize); 1634 1635 if (feature_descrp->bControlSize == 0) { 1636 featureID = USB_AC_ID_NONE; 1637 } else { 1638 uint_t index; 1639 1640 n_channel_controls = (feature_descrp->bLength - 1641 offsetof(usb_audio_feature_unit_descr1_t, 1642 bmaControls))/feature_descrp->bControlSize; 1643 1644 USB_DPRINTF_L3(PRINT_MASK_ALL, 1645 uacp->usb_ac_log_handle, 1646 "#controls: %d index=%d", n_channel_controls, 1647 feature_descrp->bControlSize * channel); 1648 1649 if (channel > n_channel_controls) { 1650 featureID = USB_AC_ID_NONE; 1651 } else { 1652 /* 1653 * we only support MUTE and VOLUME 1654 * which are in the first byte 1655 */ 1656 index = feature_descrp->bControlSize * 1657 channel; 1658 1659 USB_DPRINTF_L3(PRINT_MASK_ALL, 1660 uacp->usb_ac_log_handle, 1661 "control: 0x%x", 1662 feature_descrp->bmaControls[index]); 1663 1664 if ((feature_descrp->bmaControls[index] & 1665 control) == 0) { 1666 featureID = USB_AC_ID_NONE; 1667 } 1668 } 1669 } 1670 1671 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 1672 "usb_ac_feature_unit_check: dir=%d featureID=0x%x", 1673 dir, featureID); 1674 1675 return ((featureID != USB_AC_ID_NONE) ? 1676 USB_SUCCESS : USB_FAILURE); 1677} 1678 1679 1680/* 1681 * Descriptor Management 1682 * 1683 * usb_ac_handle_descriptors: 1684 * extract interesting descriptors from the config cloud 1685 */ 1686static int 1687usb_ac_handle_descriptors(usb_ac_state_t *uacp) 1688{ 1689 int rest, len, index; 1690 int rval = USB_FAILURE; 1691 usb_audio_cs_if_descr_t descr; 1692 usb_client_dev_data_t *dev_data = uacp->usb_ac_dev_data; 1693 usb_alt_if_data_t *altif_data; 1694 usb_cvs_data_t *cvs; 1695 1696 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1697 "config=%ld, interface=%d", 1698 (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]), 1699 dev_data->dev_curr_if); 1700 1701 altif_data = &dev_data->dev_curr_cfg-> 1702 cfg_if[dev_data->dev_curr_if].if_alt[0]; 1703 1704 uacp->usb_ac_ifno = dev_data->dev_curr_if; 1705 uacp->usb_ac_if_descr = altif_data->altif_descr; 1706 1707 /* find USB_AUDIO_CS_INTERFACE type descriptor */ 1708 for (index = 0; index < altif_data->altif_n_cvs; index++) { 1709 cvs = &altif_data->altif_cvs[index]; 1710 if (cvs->cvs_buf == NULL) { 1711 continue; 1712 } 1713 if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) { 1714 break; 1715 } 1716 } 1717 1718 if (index == altif_data->altif_n_cvs) { 1719 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1720 "cannot find descriptor type %d", USB_AUDIO_CS_INTERFACE); 1721 1722 return (rval); 1723 } 1724 1725 len = usb_parse_data( 1726 CS_AC_IF_HEADER_FORMAT, 1727 cvs->cvs_buf, cvs->cvs_buf_len, 1728 (void *)&descr, sizeof (usb_audio_cs_if_descr_t)); 1729 1730 /* is this a sane header descriptor */ 1731 if (!((len >= CS_AC_IF_HEADER_SIZE) && 1732 (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) && 1733 (descr.bDescriptorSubType == USB_AUDIO_HEADER))) { 1734 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1735 "invalid header"); 1736 1737 return (rval); 1738 } 1739 1740 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1741 "header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t" 1742 "total=0x%x InCol=0x%x", 1743 descr.bDescriptorType, 1744 descr.bDescriptorSubType, 1745 descr.bcdADC, 1746 descr.wTotalLength, 1747 descr.blnCollection); 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 usb_ac_setup_connections(uacp); 1771 1772 /* determine port types */ 1773 usb_ac_map_termtype_to_port(uacp, AUDIO_PLAY); 1774 usb_ac_map_termtype_to_port(uacp, AUDIO_RECORD); 1775 1776 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1777 "input port types=0x%x output port types =0x%x", 1778 uacp->usb_ac_input_ports, uacp->usb_ac_output_ports); 1779 1780 1781 return (rval); 1782} 1783 1784 1785/* 1786 * usb_ac_setup_connections: 1787 * build a matrix reflecting all connections 1788 */ 1789static void 1790usb_ac_setup_connections(usb_ac_state_t *uacp) 1791{ 1792 usb_ac_unit_list_t *units = uacp->usb_ac_units; 1793 uchar_t *a, **p, i, unit; 1794 size_t a_len, p_len; 1795 1796 /* allocate array for unit types for quick reference */ 1797 uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit, 1798 KM_SLEEP); 1799 /* allocate array for traversal path */ 1800 uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit, 1801 KM_SLEEP); 1802 1803 1804 /* allocate the connection matrix and set it up */ 1805 a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit; 1806 p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *); 1807 1808 /* trick to create a 2 dimensional array */ 1809 a = kmem_zalloc(a_len, KM_SLEEP); 1810 p = kmem_zalloc(p_len, KM_SLEEP); 1811 for (i = 0; i < uacp->usb_ac_max_unit; i++) { 1812 p[i] = a + i * uacp->usb_ac_max_unit; 1813 } 1814 uacp->usb_ac_connections = p; 1815 uacp->usb_ac_connections_len = p_len; 1816 uacp->usb_ac_connections_a = a; 1817 uacp->usb_ac_connections_a_len = a_len; 1818 1819 /* traverse all units and set connections */ 1820 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) { 1821 1822 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1823 "traversing unit=0x%x type=0x%x", 1824 unit, units[unit].acu_type); 1825 1826 /* store type in the first unused column */ 1827 uacp->usb_ac_unit_type[unit] = units[unit].acu_type; 1828 1829 /* save the Unit ID in the unit it points to */ 1830 switch (units[unit].acu_type) { 1831 case USB_AUDIO_FEATURE_UNIT: 1832 { 1833 usb_audio_feature_unit_descr1_t *d = 1834 units[unit].acu_descriptor; 1835 1836 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1837 "sourceID=0x%x type=0x%x", d->bSourceID, 1838 units[d->bSourceID].acu_type); 1839 1840 if (d->bSourceID != 0) { 1841 ASSERT(p[unit][d->bSourceID] == B_FALSE); 1842 p[unit][d->bSourceID] = B_TRUE; 1843 } 1844 1845 break; 1846 } 1847 case USB_AUDIO_OUTPUT_TERMINAL: 1848 { 1849 usb_audio_output_term_descr_t *d = 1850 units[unit].acu_descriptor; 1851 1852 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1853 "sourceID=0x%x type=0x%x", d->bSourceID, 1854 units[d->bSourceID].acu_type); 1855 1856 if (d->bSourceID != 0) { 1857 ASSERT(p[unit][d->bSourceID] == B_FALSE); 1858 p[unit][d->bSourceID] = B_TRUE; 1859 } 1860 1861 break; 1862 } 1863 case USB_AUDIO_MIXER_UNIT: 1864 { 1865 usb_audio_mixer_unit_descr1_t *d = 1866 units[unit].acu_descriptor; 1867 int n_sourceID = d->bNrInPins; 1868 int id; 1869 1870 for (id = 0; id < n_sourceID; id++) { 1871 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1872 uacp->usb_ac_log_handle, 1873 "sourceID=0x%x type=0x%x c=%d", 1874 d->baSourceID[id], 1875 units[d->baSourceID[id]].acu_type, 1876 p[unit][d->baSourceID[id]]); 1877 1878 if (d->baSourceID[id] != 0) { 1879 ASSERT(p[unit][d->baSourceID[id]] == 1880 B_FALSE); 1881 p[unit][d->baSourceID[id]] = B_TRUE; 1882 } 1883 } 1884 1885 break; 1886 } 1887 case USB_AUDIO_SELECTOR_UNIT: 1888 { 1889 usb_audio_selector_unit_descr1_t *d = 1890 units[unit].acu_descriptor; 1891 int n_sourceID = d->bNrInPins; 1892 int id; 1893 1894 for (id = 0; id < n_sourceID; id++) { 1895 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1896 uacp->usb_ac_log_handle, 1897 "sourceID=0x%x type=0x%x", 1898 d->baSourceID[id], 1899 units[d->baSourceID[id]].acu_type); 1900 1901 if (d->baSourceID[id] != 0) { 1902 ASSERT(p[unit][d->baSourceID[id]] == 1903 B_FALSE); 1904 p[unit][d->baSourceID[id]] = B_TRUE; 1905 } 1906 } 1907 1908 break; 1909 } 1910 case USB_AUDIO_PROCESSING_UNIT: 1911 { 1912 usb_audio_mixer_unit_descr1_t *d = 1913 units[unit].acu_descriptor; 1914 int n_sourceID = d->bNrInPins; 1915 int id; 1916 1917 for (id = 0; id < n_sourceID; id++) { 1918 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1919 uacp->usb_ac_log_handle, 1920 "sourceID=0x%x type=0x%x", 1921 d->baSourceID[id], 1922 units[d->baSourceID[id]].acu_type); 1923 1924 if (d->baSourceID[id] != 0) { 1925 ASSERT(p[unit][d->baSourceID[id]] == 1926 B_FALSE); 1927 p[unit][d->baSourceID[id]] = B_TRUE; 1928 } 1929 } 1930 1931 break; 1932 } 1933 case USB_AUDIO_EXTENSION_UNIT: 1934 { 1935 usb_audio_extension_unit_descr1_t *d = 1936 units[unit].acu_descriptor; 1937 int n_sourceID = d->bNrInPins; 1938 int id; 1939 1940 for (id = 0; id < n_sourceID; id++) { 1941 USB_DPRINTF_L3(PRINT_MASK_ATTA, 1942 uacp->usb_ac_log_handle, 1943 "sourceID=0x%x type=0x%x", 1944 d->baSourceID[id], 1945 units[d->baSourceID[id]].acu_type); 1946 1947 if (d->baSourceID[id] != 0) { 1948 ASSERT(p[unit][d->baSourceID[id]] == 1949 B_TRUE); 1950 p[unit][d->baSourceID[id]] = B_FALSE; 1951 } 1952 } 1953 1954 break; 1955 } 1956 case USB_AUDIO_INPUT_TERMINAL: 1957 1958 break; 1959 default: 1960 /* 1961 * Ignore the rest because they are not support yet 1962 */ 1963 break; 1964 } 1965 } 1966 1967#ifdef DEBUG 1968 /* display topology in log buffer */ 1969{ 1970 uint_t i, j, l; 1971 char *buf; 1972 1973 l = uacp->usb_ac_max_unit * 5; 1974 1975 buf = kmem_alloc(l, KM_SLEEP); 1976 1977 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 1978 "unit types:"); 1979 1980 /* two strings so they won't be replaced accidentily by tab */ 1981 (void) sprintf(&buf[0], " "" "); 1982 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1983 (void) sprintf(&buf[2 + (i*3)], "%02d ", i); 1984 } 1985 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1986 1987 (void) sprintf(&buf[0], " +-------"); 1988 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1989 (void) sprintf(&buf[5+((i-1)*3)], "---"); 1990 } 1991 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1992 1993 (void) sprintf(&buf[0], " "" "); 1994 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 1995 (void) sprintf(&buf[2 + (i*3)], "%02d ", 1996 uacp->usb_ac_unit_type[i]); 1997 } 1998 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 1999 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " "); 2000 2001 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2002 "adjacency matrix:"); 2003 (void) sprintf(&buf[0], " "" "); 2004 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 2005 (void) sprintf(&buf[2 + (i*3)], "%02d ", i); 2006 } 2007 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 2008 2009 (void) sprintf(&buf[0], " +-------"); 2010 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 2011 (void) sprintf(&buf[5+((i-1)*3)], "---"); 2012 } 2013 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 2014 2015 for (i = 1; i < uacp->usb_ac_max_unit; i++) { 2016 (void) sprintf(&buf[0], "%02d| "" ", i); 2017 for (j = 1; j < uacp->usb_ac_max_unit; j++) { 2018 (void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]); 2019 } 2020 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf); 2021 } 2022 kmem_free(buf, l); 2023} 2024#endif 2025} 2026 2027 2028/* 2029 * usb_ac_add_unit_descriptor: 2030 * take the parsed descriptor in the buffer and store it in the ID unit 2031 * array. we grow the unit array if the ID exceeds the current max 2032 */ 2033static void 2034usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer, 2035 size_t buflen) 2036{ 2037 void *descr; 2038 int len; 2039 char *format; 2040 size_t size; 2041 2042 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2043 "usb_ac_add_unit_descriptor: 0x%x 0x%x 0x%x", 2044 buffer[0], buffer[1], buffer[2]); 2045 2046 /* doubling the length should allow for padding */ 2047 len = 2 * buffer[0]; 2048 descr = kmem_zalloc(len, KM_SLEEP); 2049 2050 switch (buffer[2]) { 2051 case USB_AUDIO_INPUT_TERMINAL: 2052 format = CS_AC_INPUT_TERM_FORMAT; 2053 size = CS_AC_INPUT_TERM_SIZE; 2054 2055 break; 2056 case USB_AUDIO_OUTPUT_TERMINAL: 2057 format = CS_AC_OUTPUT_TERM_FORMAT; 2058 size = CS_AC_OUTPUT_TERM_SIZE; 2059 2060 break; 2061 case USB_AUDIO_MIXER_UNIT: 2062 format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c"; 2063 size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1; 2064 2065 break; 2066 case USB_AUDIO_SELECTOR_UNIT: 2067 format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c"; 2068 size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1; 2069 2070 break; 2071 case USB_AUDIO_FEATURE_UNIT: 2072 format = CS_AC_FEATURE_UNIT_FORMAT "255c"; 2073 size = CS_AC_FEATURE_UNIT_SIZE; 2074 2075 break; 2076 case USB_AUDIO_PROCESSING_UNIT: 2077 format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c"; 2078 size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1; 2079 2080 break; 2081 case USB_AUDIO_EXTENSION_UNIT: 2082 format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c"; 2083 size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1; 2084 2085 break; 2086 default: 2087 USB_DPRINTF_L2(PRINT_MASK_ATTA, 2088 uacp->usb_ac_log_handle, 2089 "unsupported descriptor %d", buffer[2]); 2090 2091 /* ignore this descriptor */ 2092 kmem_free(descr, len); 2093 2094 return; 2095 } 2096 2097 if (usb_parse_data(format, buffer, buflen, descr, len) < size) { 2098 /* ignore this descriptor */ 2099 kmem_free(descr, len); 2100 2101 return; 2102 } 2103 2104 switch (buffer[2]) { 2105 case USB_AUDIO_INPUT_TERMINAL: 2106 { 2107 usb_audio_input_term_descr_t *d = 2108 (usb_audio_input_term_descr_t *)descr; 2109 2110 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2111 uacp->usb_ac_log_handle, 2112 "input term: type=0x%x sub=0x%x termid=0x%x\n\t" 2113 "termtype=0x%x assoc=0x%x #ch=%d " 2114 "chconf=0x%x ich=0x%x iterm=0x%x", 2115 d->bDescriptorType, d->bDescriptorSubType, 2116 d->bTerminalID, d->wTerminalType, 2117 d->bAssocTerminal, d->bNrChannels, 2118 d->wChannelConfig, d->iChannelNames, 2119 d->iTerminal); 2120 2121 usb_ac_alloc_unit(uacp, d->bTerminalID); 2122 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr; 2123 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2]; 2124 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len; 2125 2126 break; 2127 } 2128 case USB_AUDIO_OUTPUT_TERMINAL: 2129 { 2130 usb_audio_output_term_descr_t *d = 2131 (usb_audio_output_term_descr_t *)descr; 2132 2133 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2134 uacp->usb_ac_log_handle, 2135 "output term: type=0x%x sub=0x%x termid=0x%x\n\t" 2136 "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x", 2137 d->bDescriptorType, d->bDescriptorSubType, 2138 d->bTerminalID, d->wTerminalType, 2139 d->bAssocTerminal, d->bSourceID, 2140 d->iTerminal); 2141 2142 usb_ac_alloc_unit(uacp, d->bTerminalID); 2143 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr; 2144 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2]; 2145 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len; 2146 2147 break; 2148 } 2149 case USB_AUDIO_MIXER_UNIT: 2150 { 2151 usb_audio_mixer_unit_descr1_t *d = 2152 (usb_audio_mixer_unit_descr1_t *)descr; 2153 2154 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2155 uacp->usb_ac_log_handle, 2156 "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2157 "#pins=0x%x sourceid[0]=0x%x", 2158 d->bDescriptorType, d->bDescriptorSubType, 2159 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2160 usb_ac_alloc_unit(uacp, d->bUnitID); 2161 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2162 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2163 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2164 2165 break; 2166 } 2167 case USB_AUDIO_SELECTOR_UNIT: 2168 { 2169 usb_audio_selector_unit_descr1_t *d = 2170 (usb_audio_selector_unit_descr1_t *)descr; 2171 2172 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2173 uacp->usb_ac_log_handle, 2174 "selector unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2175 "#pins=0x%x sourceid[0]=0x%x", 2176 d->bDescriptorType, d->bDescriptorSubType, 2177 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2178 usb_ac_alloc_unit(uacp, d->bUnitID); 2179 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2180 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2181 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2182 2183 break; 2184 } 2185 case USB_AUDIO_FEATURE_UNIT: 2186 { 2187 usb_audio_feature_unit_descr1_t *d = 2188 (usb_audio_feature_unit_descr1_t *)descr; 2189 2190 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2191 uacp->usb_ac_log_handle, 2192 "feature unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2193 "sourceid=0x%x size=0x%x", 2194 d->bDescriptorType, d->bDescriptorSubType, 2195 d->bUnitID, d->bSourceID, d->bControlSize); 2196 2197 usb_ac_alloc_unit(uacp, d->bUnitID); 2198 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2199 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2200 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2201 2202 break; 2203 } 2204 case USB_AUDIO_PROCESSING_UNIT: 2205 { 2206 usb_audio_processing_unit_descr1_t *d = 2207 (usb_audio_processing_unit_descr1_t *)descr; 2208 2209 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2210 uacp->usb_ac_log_handle, 2211 "processing unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2212 "#pins=0x%x sourceid[0]=0x%x", 2213 d->bDescriptorType, d->bDescriptorSubType, 2214 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2215 usb_ac_alloc_unit(uacp, d->bUnitID); 2216 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2217 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2218 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2219 2220 break; 2221 } 2222 case USB_AUDIO_EXTENSION_UNIT: 2223 { 2224 usb_audio_extension_unit_descr1_t *d = 2225 (usb_audio_extension_unit_descr1_t *)descr; 2226 2227 USB_DPRINTF_L3(PRINT_MASK_ATTA, 2228 uacp->usb_ac_log_handle, 2229 "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2230 "#pins=0x%x sourceid[0]=0x%x", 2231 d->bDescriptorType, d->bDescriptorSubType, 2232 d->bUnitID, d->bNrInPins, d->baSourceID[0]); 2233 usb_ac_alloc_unit(uacp, d->bUnitID); 2234 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr; 2235 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2]; 2236 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len; 2237 2238 break; 2239 } 2240 default: 2241 break; 2242 } 2243} 2244 2245 2246/* 2247 * usb_ac_alloc_unit: 2248 * check if the unit ID is less than max_unit in which case no 2249 * extra entries are needed. If more entries are needed, copy over 2250 * the existing array into a new larger array 2251 */ 2252static void 2253usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit) 2254{ 2255 usb_ac_unit_list_t *old = NULL; 2256 uint_t max_unit; 2257 2258 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2259 "usb_ac_alloc_unit: unit=%d", unit); 2260 2261 if (uacp->usb_ac_units) { 2262 if (unit < uacp->usb_ac_max_unit) { 2263 /* existing array is big enough */ 2264 2265 return; 2266 } 2267 old = uacp->usb_ac_units; 2268 max_unit = uacp->usb_ac_max_unit; 2269 } 2270 2271 /* allocate two extra ones */ 2272 unit += 2; 2273 uacp->usb_ac_max_unit = unit; 2274 uacp->usb_ac_units = kmem_zalloc(unit * 2275 sizeof (usb_ac_unit_list_t), KM_SLEEP); 2276 2277 if (old) { 2278 size_t len = max_unit * sizeof (usb_ac_unit_list_t); 2279 bcopy(old, uacp->usb_ac_units, len); 2280 2281 kmem_free(old, len); 2282 } 2283} 2284 2285 2286/* 2287 * usb_ac_free_all_units: 2288 * free the entire unit list 2289 */ 2290static void 2291usb_ac_free_all_units(usb_ac_state_t *uacp) 2292{ 2293 uint_t unit; 2294 usb_ac_unit_list_t *unitp; 2295 2296 if (uacp->usb_ac_units == NULL) { 2297 2298 return; 2299 } 2300 2301 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 2302 "usb_ac_alloc_unit: max_unit=%d", uacp->usb_ac_max_unit); 2303 2304 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) { 2305 unitp = &uacp->usb_ac_units[unit]; 2306 if (unitp) { 2307 if (unitp->acu_descriptor) { 2308 kmem_free(unitp->acu_descriptor, 2309 unitp->acu_descr_length); 2310 } 2311 } 2312 } 2313 2314 kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit * 2315 sizeof (usb_ac_unit_list_t)); 2316} 2317 2318 2319/* 2320 * usb_ac_lookup_port_type: 2321 * map term type to port type 2322 * default just return LINE_IN + LINE_OUT 2323 */ 2324static int 2325usb_ac_lookup_port_type(ushort_t termtype) 2326{ 2327 uint_t i; 2328 2329 for (i = 0; ; i++) { 2330 if (usb_ac_term_type_map[i].term_type == 0) { 2331 2332 break; 2333 } 2334 2335 if (usb_ac_term_type_map[i].term_type == termtype) { 2336 2337 return (usb_ac_term_type_map[i].port_type); 2338 } 2339 } 2340 2341 return (AUDIO_LINE_IN|AUDIO_LINE_OUT); 2342} 2343 2344 2345/* 2346 * usb_ac_update_port: 2347 * called for each terminal 2348 */ 2349/*ARGSUSED*/ 2350static int 2351usb_ac_update_port(usb_ac_state_t *uacp, uint_t id, 2352 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 2353{ 2354 if (dir & AUDIO_PLAY) { 2355 usb_audio_output_term_descr_t *d = 2356 (usb_audio_output_term_descr_t *) 2357 uacp->usb_ac_units[id].acu_descriptor; 2358 uint_t port_type = 2359 usb_ac_lookup_port_type(d->wTerminalType); 2360 2361 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2362 "usb_ac_update_port: dir=%d type=0x%x port type=%d", 2363 dir, d->wTerminalType, port_type); 2364 2365 uacp->usb_ac_output_ports |= port_type; 2366 uacp->usb_ac_output_ports &= ~AUDIO_LINE_IN; 2367 } else { 2368 usb_audio_output_term_descr_t *d = 2369 (usb_audio_output_term_descr_t *) 2370 uacp->usb_ac_units[id].acu_descriptor; 2371 uint_t port_type = 2372 usb_ac_lookup_port_type(d->wTerminalType); 2373 2374 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2375 "usb_ac_update_port: dir=%d type=0x%x port type=%d", 2376 dir, d->wTerminalType, port_type); 2377 2378 uacp->usb_ac_input_ports |= 2379 usb_ac_lookup_port_type(d->wTerminalType); 2380 uacp->usb_ac_input_ports &= ~AUDIO_LINE_OUT; 2381 } 2382 2383 return (USB_SUCCESS); 2384} 2385 2386 2387/* 2388 * usb_ac_map_termtype_to_port: 2389 * starting from a streaming termtype find all 2390 * input or output terminals and OR into uacp->usb_ac_input_ports 2391 * or uacp->usb_ac_output_ports; 2392 */ 2393static void 2394usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir) 2395{ 2396 uint_t count = 0; 2397 uint_t depth = 0; 2398 uint_t search_type = (dir & AUDIO_PLAY) ? 2399 USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL; 2400 2401 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2402 "usb_ac_map_term_to_port: dir=%d", dir); 2403 2404 (void) usb_ac_traverse_all_units(uacp, dir, search_type, 0, 2405 0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port); 2406 2407 ASSERT(depth == 0); 2408} 2409 2410 2411/* 2412 * usb_ac_set_port: 2413 * find a selector port (record side only) and set the 2414 * input to the matching pin 2415 */ 2416static uint_t 2417usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port) 2418{ 2419 uint_t count = 0; 2420 uint_t id; 2421 uint_t depth = 0; 2422 2423 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2424 "usb_ac_set_port: dir=%d port=%d", dir, port); 2425 2426 /* we only support the selector for the record side */ 2427 if (dir & AUDIO_RECORD) { 2428 id = usb_ac_traverse_all_units(uacp, dir, 2429 USB_AUDIO_SELECTOR_UNIT, 0, 2430 0, USB_AC_FIND_ONE, &count, port, &depth, 2431 usb_ac_set_selector); 2432 2433 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2434 "usb_ac_set_port: id=%d count=%d port=%d", 2435 id, count, port); 2436 2437 ASSERT(depth == 0); 2438 } 2439 2440 return (USB_SUCCESS); 2441} 2442 2443 2444/* 2445 * usb_ac_match_port: 2446 * given the requested port type, find a correspondig term type 2447 * Called from usb_ac_traverse_all_units() 2448 */ 2449/*ARGSUSED*/ 2450static int 2451usb_ac_match_port(usb_ac_state_t *uacp, uint_t id, 2452 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 2453{ 2454 uint_t port_type; 2455 2456 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2457 "usb_ac_match_port: id=%d dir=%d port=%d", 2458 id, dir, arg1); 2459 2460 if (dir & AUDIO_PLAY) { 2461 usb_audio_output_term_descr_t *d = 2462 (usb_audio_output_term_descr_t *) 2463 uacp->usb_ac_units[id].acu_descriptor; 2464 port_type = usb_ac_lookup_port_type(d->wTerminalType); 2465 2466 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2467 "usb_ac_match_port: " 2468 "dir=%d type=0x%x port_type=%d port=%d", 2469 dir, d->wTerminalType, port_type, arg1); 2470 } else { 2471 usb_audio_output_term_descr_t *d = 2472 (usb_audio_output_term_descr_t *) 2473 uacp->usb_ac_units[id].acu_descriptor; 2474 port_type = usb_ac_lookup_port_type(d->wTerminalType); 2475 2476 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2477 "usb_ac_match_port: " 2478 "dir=%d type=0x%x port_type=%d port=%d", 2479 dir, d->wTerminalType, port_type, arg1); 2480 } 2481 2482 return ((port_type & arg1) ? USB_SUCCESS : USB_FAILURE); 2483} 2484 2485 2486/* 2487 * usb_ac_set_selector: 2488 * Called from usb_ac_traverse_all_units() 2489 * Find the correct pin and set selector to this pin 2490 */ 2491/*ARGSUSED*/ 2492static int 2493usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id, 2494 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth) 2495{ 2496 uint_t count = 0; 2497 uint_t unit = USB_AC_ID_NONE; 2498 uint_t pin; 2499 uint_t search_target = 2500 (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL : 2501 USB_AUDIO_INPUT_TERMINAL; 2502 usb_audio_selector_unit_descr1_t *d = 2503 (usb_audio_selector_unit_descr1_t *) 2504 uacp->usb_ac_units[id].acu_descriptor; 2505 int n_sourceID = d->bNrInPins; 2506 int rval = USB_FAILURE; 2507 2508 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2509 "usb_ac_set_selector: id=%d dir=%d port=%d", 2510 id, dir, arg1); 2511 2512 /* 2513 * for each pin, find a term type that matches the 2514 * requested port type 2515 */ 2516 for (pin = 0; pin < n_sourceID; pin++) { 2517 if (d->baSourceID[pin] == 0) { 2518 2519 break; 2520 } 2521 unit = d->baSourceID[pin]; 2522 2523 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2524 "usb_ac_set_selector: pin=%d unit=%d", pin, unit); 2525 2526 if (uacp->usb_ac_unit_type[unit] == search_target) { 2527 if (usb_ac_match_port(uacp, unit, dir, channel, 2528 control, arg1, depth) == USB_SUCCESS) { 2529 2530 break; 2531 } else { 2532 unit = USB_AC_ID_NONE; 2533 2534 continue; 2535 } 2536 } 2537 2538 /* find units connected to this unit */ 2539 unit = usb_ac_traverse_connections(uacp, unit, 2540 dir, search_target, channel, control, 2541 USB_AC_FIND_ONE, &count, arg1, depth, 2542 usb_ac_match_port); 2543 2544 if (unit != USB_AC_ID_NONE) { 2545 2546 break; 2547 } 2548 } 2549 2550 2551 if (unit != USB_AC_ID_NONE) { 2552 mblk_t *data; 2553 usb_cr_t cr; 2554 usb_cb_flags_t cb_flags; 2555 2556 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2557 "usb_ac_set_selector: found id=%d at pin %d", unit, pin); 2558 2559 mutex_exit(&uacp->usb_ac_mutex); 2560 2561 data = allocb_wait(1, BPRI_HI, STR_NOSIG, NULL); 2562 2563 /* pins are 1-based */ 2564 *(data->b_rptr) = (char)++pin; 2565 2566 if (usb_pipe_sync_ctrl_xfer( 2567 uacp->usb_ac_dip, 2568 uacp->usb_ac_default_ph, 2569 USB_DEV_REQ_HOST_TO_DEV | 2570 USB_DEV_REQ_TYPE_CLASS | 2571 USB_DEV_REQ_RCPT_IF, /* bmRequestType */ 2572 USB_AUDIO_SET_CUR, /* bRequest */ 2573 0, /* wValue */ 2574 /* feature unit and id */ 2575 (id << 8)| uacp->usb_ac_ifno, /* wIndex */ 2576 1, /* wLength */ 2577 &data, 2578 USB_ATTRS_NONE, 2579 &cr, &cb_flags, 2580 USB_FLAGS_SLEEP) == USB_SUCCESS) { 2581 USB_DPRINTF_L3(PRINT_MASK_ALL, 2582 uacp->usb_ac_log_handle, 2583 "set current selection: %d", *data->b_rptr); 2584 2585 rval = USB_SUCCESS; 2586 } else { 2587 USB_DPRINTF_L2(PRINT_MASK_ALL, 2588 uacp->usb_ac_log_handle, 2589 "set current pin selection failed"); 2590 } 2591 freemsg(data); 2592 2593 mutex_enter(&uacp->usb_ac_mutex); 2594 } else { 2595 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2596 "usb_ac_set_selector: nothing found"); 2597 } 2598 2599 return (rval); 2600} 2601 2602 2603/* 2604 * usb_ac_set_control: 2605 * apply func to all units of search_target type for both the 2606 * requested channel and master channel 2607 */ 2608static uint_t 2609usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target, 2610 uint_t channel, uint_t control, uint_t all_or_one, 2611 uint_t *count, uint_t arg1, 2612 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2613 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2614{ 2615 uint_t id; 2616 uint_t depth = 0; 2617 2618 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2619 "usb_ac_set_control: dir=%d type=%d ch=%d cntl=%d", 2620 dir, search_target, channel, control); 2621 2622 2623 id = usb_ac_traverse_all_units(uacp, dir, search_target, channel, 2624 control, all_or_one, count, arg1, &depth, func); 2625 2626 if ((channel != 0) && 2627 (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) || 2628 (all_or_one == USB_AC_FIND_ALL))) { 2629 /* try master channel */ 2630 channel = 0; 2631 id = usb_ac_traverse_all_units(uacp, dir, search_target, 2632 channel, control, all_or_one, count, arg1, 2633 &depth, func); 2634 } 2635 2636 ASSERT(depth == 0); 2637 2638 return (id); 2639} 2640 2641 2642/* 2643 * usb_ac_traverse_all_units: 2644 * traverse all units starting with all IT or OT depending on direction. 2645 * If no unit is found for the particular channel, try master channel 2646 * If a matching unit is found, apply the function passed by 2647 * the caller 2648 */ 2649static uint_t 2650usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir, 2651 uint_t search_target, uint_t channel, uint_t control, 2652 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth, 2653 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2654 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2655{ 2656 uint_t unit, start_type, id; 2657 2658 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2659 "usb_ac_traverse_all_units: " 2660 "dir=%d type=%d ch=%d cntl=%d all=%d depth=%d", 2661 dir, search_target, channel, control, all_or_one, *depth); 2662 2663 start_type = (dir & AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL : 2664 USB_AUDIO_OUTPUT_TERMINAL; 2665 2666 /* keep track of recursion */ 2667 if ((*depth)++ > USB_AC_MAX_DEPTH) { 2668 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2669 "Unit topology too complex, giving up"); 2670 2671 return (USB_AC_ID_NONE); 2672 } 2673 2674 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2675 /* is this an IT or OT? */ 2676 if (uacp->usb_ac_unit_type[unit] != start_type) { 2677 2678 continue; 2679 } 2680 2681 /* start at streaming term types */ 2682 if (dir & AUDIO_PLAY) { 2683 usb_audio_input_term_descr_t *d = 2684 uacp->usb_ac_units[unit].acu_descriptor; 2685 if (d->wTerminalType != 2686 USB_AUDIO_TERM_TYPE_STREAMING) { 2687 2688 continue; 2689 } 2690 } else { 2691 usb_audio_output_term_descr_t *d = 2692 uacp->usb_ac_units[unit].acu_descriptor; 2693 if (d->wTerminalType != 2694 USB_AUDIO_TERM_TYPE_STREAMING) { 2695 2696 continue; 2697 } 2698 } 2699 2700 /* find units connected to this unit */ 2701 id = usb_ac_traverse_connections(uacp, unit, dir, 2702 search_target, channel, control, all_or_one, count, 2703 arg1, depth, func); 2704 2705 if ((all_or_one == USB_AC_FIND_ONE) && 2706 (id != USB_AC_ID_NONE)) { 2707 unit = id; 2708 2709 break; 2710 } 2711 } 2712 2713 (*depth)--; 2714 2715 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE); 2716} 2717 2718 2719/* 2720 * usb_ac_set_monitor_gain_control: 2721 * search for a feature unit between output terminal (OT) and 2722 * input terminal. We are looking for a path between 2723 * for example a microphone and a speaker through a feature unit 2724 * and mixer 2725 */ 2726static uint_t 2727usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir, 2728 uint_t search_target, uint_t channel, uint_t control, 2729 uint_t all_or_one, uint_t *count, uint_t arg1, 2730 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2731 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2732{ 2733 uint_t unit, id; 2734 uint_t depth = 0; 2735 2736 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2737 "usb_ac_set_monitor_gain_control: dir=%d type=%d ch=%d cntl=%d", 2738 dir, search_target, channel, control); 2739 2740 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2741 usb_audio_output_term_descr_t *d = 2742 uacp->usb_ac_units[unit].acu_descriptor; 2743 2744 /* is this an OT and not stream type? */ 2745 if ((uacp->usb_ac_unit_type[unit] == 2746 USB_AUDIO_OUTPUT_TERMINAL) && 2747 (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) { 2748 2749 /* find units connected to this unit */ 2750 id = usb_ac_traverse_connections(uacp, unit, dir, 2751 search_target, channel, control, all_or_one, count, 2752 arg1, &depth, func); 2753 2754 if ((all_or_one == USB_AC_FIND_ONE) && 2755 (id != USB_AC_ID_NONE)) { 2756 2757 break; 2758 } 2759 } 2760 } 2761 2762 ASSERT(depth == 0); 2763 2764 return (id); 2765} 2766 2767 2768/* 2769 * usb_ac_push/pop_unit 2770 * add/remove unit ID to the traverse path 2771 */ 2772static void 2773usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit) 2774{ 2775 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2776 "usb_ac_push_unit_id: pushing %d at %d", unit, 2777 uacp->usb_ac_traverse_path_index); 2778 2779 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] = 2780 (uchar_t)unit; 2781 ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit); 2782} 2783 2784 2785static void 2786usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit) 2787{ 2788 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2789 "usb_ac_push_unit_id: popping %d at %d", unit, 2790 uacp->usb_ac_traverse_path_index); 2791 2792 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0; 2793} 2794 2795 2796/* 2797 * usb_ac_show_traverse_path: 2798 * display entire path, just for debugging 2799 */ 2800static void 2801usb_ac_show_traverse_path(usb_ac_state_t *uacp) 2802{ 2803 int i; 2804 2805 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) { 2806 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2807 "traverse path %d: unit=%d type=%d", 2808 i, uacp->usb_ac_traverse_path[i], 2809 uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]); 2810 } 2811} 2812 2813 2814/* 2815 * usb_ac_check_path: 2816 * check for a specified type in the traverse path 2817 */ 2818static int 2819usb_ac_check_path(usb_ac_state_t *uacp, uint_t type) 2820{ 2821 int i; 2822 2823 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) { 2824 uint_t unit = uacp->usb_ac_traverse_path[i]; 2825 2826 if (uacp->usb_ac_unit_type[unit] == type) { 2827 2828 return (USB_SUCCESS); 2829 } 2830 } 2831 2832 return (USB_FAILURE); 2833} 2834 2835 2836/* 2837 * usb_ac_traverse_connections: 2838 * traverse all units and for each unit with the right type, call 2839 * func. If the func returns a success and search == USB_AC_FIND_ONE, 2840 * we are done. If all is set then we continue until we terminate 2841 * and input or output terminal. 2842 * For audio play, we traverse columns starting from an input terminal 2843 * to an output terminal while for record we traverse rows from output 2844 * terminal to input terminal. 2845 */ 2846static uint_t 2847usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir, 2848 uint_t search_target, uint_t channel, uint_t control, 2849 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth, 2850 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir, 2851 uint_t channel, uint_t control, uint_t arg1, uint_t *depth)) 2852{ 2853 uint_t unit, id; 2854 uint_t done = (dir & AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL : 2855 USB_AUDIO_INPUT_TERMINAL; 2856 2857 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2858 "usb_ac_traverse_connections: " 2859 "start=%d dir=%d type=%d ch=%d cntl=%d all=%d depth=%d", 2860 start_unit, dir, search_target, channel, control, 2861 all_or_one, *depth); 2862 2863 /* keep track of recursion depth */ 2864 if ((*depth)++ > USB_AC_MAX_DEPTH) { 2865 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2866 "Unit topology too complex, giving up"); 2867 2868 return (USB_AC_ID_NONE); 2869 } 2870 2871 usb_ac_push_unit_id(uacp, start_unit); 2872 2873 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) { 2874 uint_t entry = (dir & AUDIO_PLAY) ? 2875 uacp->usb_ac_connections[unit][start_unit] : 2876 uacp->usb_ac_connections[start_unit][unit]; 2877 2878 if (entry) { 2879 USB_DPRINTF_L3(PRINT_MASK_ALL, 2880 uacp->usb_ac_log_handle, 2881 "start=%d unit=%d entry=%d type=%d " 2882 "done=%d found=%d", 2883 start_unit, unit, entry, search_target, done, 2884 uacp->usb_ac_unit_type[unit]); 2885 2886 /* did we find a matching type? */ 2887 if (uacp->usb_ac_unit_type[unit] == search_target) { 2888 USB_DPRINTF_L3(PRINT_MASK_ALL, 2889 uacp->usb_ac_log_handle, 2890 "match: dir=%d unit=%d type=%d", 2891 dir, unit, search_target); 2892 2893 /* yes, no apply function to this unit */ 2894 if (func(uacp, unit, dir, channel, 2895 control, arg1, depth) == USB_SUCCESS) { 2896 (*count)++; 2897 2898 USB_DPRINTF_L3(PRINT_MASK_ALL, 2899 uacp->usb_ac_log_handle, 2900 "func returned success, " 2901 "unit=%d all=%d", unit, 2902 all_or_one); 2903 2904 /* are we done? */ 2905 if (all_or_one == USB_AC_FIND_ONE) { 2906 2907 break; 2908 } 2909 } 2910 } 2911 2912 /* did we find the terminating unit */ 2913 if (uacp->usb_ac_unit_type[unit] == done) { 2914 2915 continue; 2916 } 2917 id = usb_ac_traverse_connections(uacp, unit, dir, 2918 search_target, channel, control, 2919 all_or_one, count, arg1, depth, func); 2920 if ((id != USB_AC_ID_NONE) && 2921 (all_or_one == USB_AC_FIND_ONE)) { 2922 unit = id; 2923 2924 break; 2925 } 2926 } 2927 } 2928 2929 (*depth)--; 2930 usb_ac_pop_unit_id(uacp, start_unit); 2931 2932 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE); 2933} 2934 2935 2936/* 2937 * Event Management 2938 * 2939 * usb_ac_disconnect_event_cb: 2940 * The device has been disconnected. we either wait for 2941 * detach or a reconnect event. 2942 */ 2943static int 2944usb_ac_disconnect_event_cb(dev_info_t *dip) 2945{ 2946 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2947 usb_ac_statep, ddi_get_instance(dip)); 2948 2949 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2950 "usb_ac_disconnect_event_cb: dip=0x%p", (void *)dip); 2951 2952 usb_ac_serialize_access(uacp); 2953 2954 /* setting to disconnect state will prevent replumbing */ 2955 mutex_enter(&uacp->usb_ac_mutex); 2956 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED; 2957 2958 if (uacp->usb_ac_busy_count) { 2959 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2960 "device was disconnected while busy. " 2961 "Data may have been lost"); 2962 } 2963 mutex_exit(&uacp->usb_ac_mutex); 2964 2965 USB_DPRINTF_L3(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 2966 "usb_ac_disconnect_event_cb: done"); 2967 2968 usb_ac_release_access(uacp); 2969 2970 return (USB_SUCCESS); 2971} 2972 2973 2974/* 2975 * usb_ac_cpr_suspend: 2976 */ 2977static int 2978usb_ac_cpr_suspend(dev_info_t *dip) 2979{ 2980 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 2981 usb_ac_statep, ddi_get_instance(dip)); 2982 2983 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2984 "usb_ac_cpr_suspend: Begin"); 2985 2986 mutex_enter(&uacp->usb_ac_mutex); 2987 uacp->usb_ac_dev_state = USB_DEV_SUSPENDED; 2988 mutex_exit(&uacp->usb_ac_mutex); 2989 2990 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 2991 "usb_ac_cpr_suspend: End"); 2992 2993 return (USB_SUCCESS); 2994} 2995 2996 2997 2998/* 2999 * usb_ac_reconnect_event_cb: 3000 * The device was disconnected but this instance not detached, probably 3001 * because the device was busy. 3002 * if the same device, continue with restoring state 3003 * We should either be in the unplumbed state or the plumbed open 3004 * state. 3005 */ 3006static int 3007usb_ac_reconnect_event_cb(dev_info_t *dip) 3008{ 3009 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 3010 usb_ac_statep, ddi_get_instance(dip)); 3011 3012 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 3013 "usb_ac_reconnect_event_cb: dip=0x%p", (void *)dip); 3014 3015 mutex_enter(&uacp->usb_ac_mutex); 3016 mutex_exit(&uacp->usb_ac_mutex); 3017 3018 usb_ac_serialize_access(uacp); 3019 3020 /* check the plumbing state */ 3021 mutex_enter(&uacp->usb_ac_mutex); 3022 uacp->usb_ac_busy_count++; 3023 if (uacp->usb_ac_plumbing_state == 3024 USB_AC_STATE_PLUMBED) { 3025 mutex_exit(&uacp->usb_ac_mutex); 3026 usb_ac_restore_device_state(dip, uacp); 3027 mutex_enter(&uacp->usb_ac_mutex); 3028 } 3029 uacp->usb_ac_busy_count--; 3030 3031 if (uacp->usb_ac_busy_count) { 3032 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 3033 "busy device has been reconnected"); 3034 } 3035 mutex_exit(&uacp->usb_ac_mutex); 3036 3037 usb_ac_release_access(uacp); 3038 3039 return (USB_SUCCESS); 3040} 3041 3042 3043/* 3044 * usb_ac_cpr_resume: 3045 * Restore device state 3046 */ 3047static void 3048usb_ac_cpr_resume(dev_info_t *dip) 3049{ 3050 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state( 3051 usb_ac_statep, ddi_get_instance(dip)); 3052 3053 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle, 3054 "usb_ac_cpr_resume"); 3055 3056 usb_ac_serialize_access(uacp); 3057 3058 usb_ac_restore_device_state(dip, uacp); 3059 3060 usb_ac_release_access(uacp); 3061} 3062 3063 3064/* 3065 * usb_ac_restore_device_state: 3066 * Set original configuration of the device 3067 * enable wrq - this starts new transactions on the control pipe 3068 */ 3069static void 3070usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp) 3071{ 3072 usb_ac_power_t *uacpm; 3073 int rval; 3074 3075 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, 3076 "usb_ac_restore_device_state:"); 3077 3078 usb_ac_pm_busy_component(uacp); 3079 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR); 3080 3081 /* Check if we are talking to the same device */ 3082 if (usb_check_same_device(dip, uacp->usb_ac_log_handle, 3083 USB_LOG_L0, PRINT_MASK_ALL, 3084 USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) { 3085 usb_ac_pm_idle_component(uacp); 3086 3087 /* change the device state from suspended to disconnected */ 3088 mutex_enter(&uacp->usb_ac_mutex); 3089 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED; 3090 mutex_exit(&uacp->usb_ac_mutex); 3091 3092 return; 3093 } 3094 3095 mutex_enter(&uacp->usb_ac_mutex); 3096 uacpm = uacp->usb_ac_pm; 3097 if (uacpm) { 3098 if (uacpm->acpm_wakeup_enabled) { 3099 mutex_exit(&uacp->usb_ac_mutex); 3100 3101 if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip, 3102 USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) { 3103 3104 USB_DPRINTF_L4(PRINT_MASK_ATTA, 3105 uacp->usb_ac_log_handle, 3106 "usb_ac_restore_device_state: " 3107 "remote wakeup " 3108 "enable failed, rval=%d", rval); 3109 } 3110 3111 mutex_enter(&uacp->usb_ac_mutex); 3112 } 3113 } 3114 3115 /* prevent unplumbing */ 3116 uacp->usb_ac_busy_count++; 3117 uacp->usb_ac_dev_state = USB_DEV_ONLINE; 3118 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) { 3119 (void) usb_ac_restore_audio_state(uacp, 0); 3120 } 3121 uacp->usb_ac_busy_count--; 3122 mutex_exit(&uacp->usb_ac_mutex); 3123 usb_ac_pm_idle_component(uacp); 3124} 3125 3126 3127/* 3128 * usb_ac_am_restore_state 3129 */ 3130static void 3131usb_ac_am_restore_state(void *arg) 3132{ 3133 usb_ac_state_t *uacp = (usb_ac_state_t *)arg; 3134 3135 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3136 "usb_ac_am_restore_state: Begin"); 3137 3138 usb_ac_serialize_access(uacp); 3139 3140 mutex_enter(&uacp->usb_ac_mutex); 3141 3142 if (uacp->usb_ac_plumbing_state == 3143 USB_AC_STATE_PLUMBED_RESTORING) { 3144 mutex_exit(&uacp->usb_ac_mutex); 3145 3146 /* 3147 * allow hid and usb_as to restore themselves 3148 * (some handshake would have been preferable though) 3149 */ 3150 delay(USB_AC_RESTORE_DELAY); 3151 3152 (void) audio_sup_restore_state(uacp->usb_ac_audiohdl, 3153 AUDIO_ALL_DEVICES, AUDIO_BOTH); 3154 3155 mutex_enter(&uacp->usb_ac_mutex); 3156 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED; 3157 } 3158 3159 /* allow unplumbing */ 3160 uacp->usb_ac_busy_count--; 3161 mutex_exit(&uacp->usb_ac_mutex); 3162 3163 usb_ac_release_access(uacp); 3164 3165 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3166 "usb_ac_am_restore_state: End"); 3167} 3168 3169 3170/* 3171 * usb_ac_restore_audio_state: 3172 */ 3173static int 3174usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag) 3175{ 3176 ASSERT(mutex_owned(&uacp->usb_ac_mutex)); 3177 3178 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3179 "usb_ac_restore_audio_state: flag=%d", flag); 3180 3181 switch (uacp->usb_ac_plumbing_state) { 3182 case USB_AC_STATE_PLUMBED: 3183 uacp->usb_ac_plumbing_state = 3184 USB_AC_STATE_PLUMBED_RESTORING; 3185 3186 break; 3187 case USB_AC_STATE_UNPLUMBED: 3188 3189 return (USB_SUCCESS); 3190 case USB_AC_STATE_PLUMBED_RESTORING: 3191 default: 3192 3193 return (USB_FAILURE); 3194 } 3195 3196 /* 3197 * increment busy_count again, it will be decremented 3198 * in usb_ac_am_restore_state 3199 */ 3200 uacp->usb_ac_busy_count++; 3201 3202 if (flag & USB_FLAGS_SLEEP) { 3203 mutex_exit(&uacp->usb_ac_mutex); 3204 usb_ac_am_restore_state((void *)uacp); 3205 mutex_enter(&uacp->usb_ac_mutex); 3206 } else { 3207 mutex_exit(&uacp->usb_ac_mutex); 3208 if (usb_async_req(uacp->usb_ac_dip, 3209 usb_ac_am_restore_state, 3210 (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) { 3211 3212 mutex_enter(&uacp->usb_ac_mutex); 3213 uacp->usb_ac_busy_count--; 3214 3215 return (USB_FAILURE); 3216 } 3217 mutex_enter(&uacp->usb_ac_mutex); 3218 } 3219 3220 return (USB_SUCCESS); 3221} 3222 3223 3224/* 3225 * Mixer Callback Management 3226 * NOTE: all mixer callbacks are serialized. we cannot be closed while 3227 * we are in the middle of a callback. There needs to be a 3228 * teardown first. We cannot be unplumbed as long as we are 3229 * still open. 3230 * 3231 * usb_ac_setup: 3232 * Send setup to usb_as if the first setup 3233 * Check power is done in usb_ac_send_as_cmd() 3234 */ 3235static int 3236usb_ac_setup(audiohdl_t ahdl, int stream, int flag) 3237{ 3238 int rval = AUDIO_SUCCESS; 3239 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3240 3241 ASSERT(uacp != NULL); 3242 3243 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3244 "usb_ac_setup: Begin ahdl=0x%p, stream=%d, flag=%d", 3245 (void *)ahdl, stream, flag); 3246 3247 mutex_enter(&uacp->usb_ac_mutex); 3248 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) { 3249 mutex_exit(&uacp->usb_ac_mutex); 3250 3251 return (AUDIO_FAILURE); 3252 } 3253 mutex_exit(&uacp->usb_ac_mutex); 3254 3255 usb_ac_serialize_access(uacp); 3256 3257 if (flag & AUDIO_PLAY) { 3258 rval = usb_ac_do_setup(ahdl, stream, AUDIO_PLAY); 3259 } 3260 3261 if ((rval == USB_SUCCESS) && (flag & AUDIO_RECORD)) { 3262 rval = usb_ac_do_setup(ahdl, stream, AUDIO_RECORD); 3263 } 3264 3265 usb_ac_release_access(uacp); 3266 3267 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3268 "usb_ac_setup: rval=%d", rval); 3269 3270 return ((rval == USB_SUCCESS) ? AUDIO_SUCCESS : AUDIO_FAILURE); 3271} 3272 3273 3274/* 3275 * usb_ac_do_setup: 3276 * Wrapper function for usb_ac_setup which can be called 3277 * either from audio framework for usb_ac_set_format 3278 */ 3279static int 3280usb_ac_do_setup(audiohdl_t ahdl, int stream, int flag) 3281{ 3282 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3283 usb_ac_plumbed_t *plumb_infop = NULL; 3284 usb_ac_streams_info_t *streams_infop = NULL; 3285 int dir; 3286 3287 ASSERT(uacp != NULL); 3288 3289 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3290 "usb_ac_do_setup: Begin ahdl=0x%p, stream=%d, flag=%d", 3291 (void *)ahdl, stream, flag); 3292 3293 mutex_enter(&uacp->usb_ac_mutex); 3294 3295 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3296 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3297 ASSERT(plumb_infop != NULL); 3298 3299 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3300 ASSERT(streams_infop != NULL); 3301 3302 /* 3303 * Handle multiple setup calls. Pass the setup call to usb_as only 3304 * the first time so isoc pipe will be opened only once 3305 */ 3306 if (streams_infop->acs_setup_teardown_count++) { 3307 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3308 "usb_ac_do_setup: more than one setup, cnt=%d", 3309 streams_infop->acs_setup_teardown_count); 3310 3311 mutex_exit(&uacp->usb_ac_mutex); 3312 3313 return (USB_SUCCESS); 3314 } 3315 3316 /* Send setup command to usb_as */ 3317 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_SETUP, 0) != 3318 USB_SUCCESS) { 3319 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3320 "usb_ac_do_setup: failure"); 3321 3322 streams_infop->acs_setup_teardown_count--; 3323 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3324 3325 mutex_exit(&uacp->usb_ac_mutex); 3326 3327 return (USB_FAILURE); 3328 } 3329 3330 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3331 3332 mutex_exit(&uacp->usb_ac_mutex); 3333 3334 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3335 "usb_ac_do_setup: End"); 3336 3337 return (USB_SUCCESS); 3338} 3339 3340 3341/* 3342 * usb_ac_teardown: 3343 * Send teardown to usb_as if the last teardown 3344 * Check power is done in usb_ac_send_as_cmd() 3345 * NOTE: allow teardown when disconnected 3346 */ 3347static void 3348usb_ac_teardown(audiohdl_t ahdl, int stream, int flag) 3349{ 3350 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3351 3352 ASSERT(uacp != NULL); 3353 3354 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3355 "usb_ac_teardown: Begin ahdl=0x%p, stream=%d", 3356 (void *)ahdl, stream); 3357 3358 usb_ac_serialize_access(uacp); 3359 3360 if (flag & AUDIO_PLAY) { 3361 usb_ac_do_teardown(ahdl, stream, AUDIO_PLAY); 3362 } 3363 3364 if (flag & AUDIO_RECORD) { 3365 usb_ac_do_teardown(ahdl, stream, AUDIO_RECORD); 3366 } 3367 3368 usb_ac_release_access(uacp); 3369 3370 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3371 "usb_ac_teardown: End"); 3372} 3373 3374 3375/* 3376 * usb_ac_do_teardown() 3377 * Check power is done in usb_ac_send_as_cmd() 3378 */ 3379static void 3380usb_ac_do_teardown(audiohdl_t ahdl, int stream, int flag) 3381{ 3382 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3383 usb_ac_plumbed_t *plumb_infop = NULL; 3384 usb_ac_streams_info_t *streams_infop = NULL; 3385 int dir; 3386 3387 ASSERT(uacp != NULL); 3388 3389 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3390 "usb_ac_do_teardown: Begin ahdl=0x%p, stream=%d", 3391 (void *)ahdl, stream); 3392 3393 mutex_enter(&uacp->usb_ac_mutex); 3394 3395 dir = (flag & AUDIO_PLAY) ? AUDIO_PLAY : AUDIO_RECORD; 3396 plumb_infop = usb_ac_get_plumb_info(uacp, "usb_as", dir); 3397 ASSERT(plumb_infop != NULL); 3398 3399 streams_infop = (usb_ac_streams_info_t *)plumb_infop->acp_data; 3400 ASSERT(streams_infop != NULL); 3401 3402 /* There should be at least one matching setup call */ 3403 ASSERT(streams_infop->acs_setup_teardown_count); 3404 3405 /* 3406 * Handle multiple setup/teardown calls. Pass the call to usb_as 3407 * only this is the last teardown so that isoc pipe is closed 3408 * only once 3409 */ 3410 if (--(streams_infop->acs_setup_teardown_count)) { 3411 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3412 "usb_ac_do_teardown: more than one setup/teardown, " 3413 "cnt=%d", 3414 streams_infop->acs_setup_teardown_count); 3415 3416 mutex_exit(&uacp->usb_ac_mutex); 3417 3418 return; 3419 } 3420 3421 /* Send teardown command to usb_as */ 3422 if (usb_ac_send_as_cmd(uacp, plumb_infop, USB_AUDIO_TEARDOWN, 3423 (void *)NULL) != USB_SUCCESS) { 3424 3425 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3426 "usb_ac_do_teardown: failure"); 3427 3428 streams_infop->acs_setup_teardown_count++; 3429 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3430 3431 mutex_exit(&uacp->usb_ac_mutex); 3432 3433 return; 3434 } 3435 3436 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 3437 3438 mutex_exit(&uacp->usb_ac_mutex); 3439 3440 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3441 "usb_ac_do_teardown: End"); 3442} 3443 3444 3445/* 3446 * usb_ac_set_config: 3447 * This routine will send control commands to get the max 3448 * and min gain balance, calculate the gain to be set from the 3449 * arguments and send another control command to set it. 3450 * Check power is done here since we will access the default pipe 3451 */ 3452static int 3453usb_ac_set_config(audiohdl_t ahdl, int stream, int command, int flag, 3454 int arg1, int arg2) 3455{ 3456 usb_ac_state_t *uacp = audio_sup_get_private(ahdl); 3457 char *what; 3458 int rval = AUDIO_FAILURE; 3459 uint_t channel; 3460 uchar_t n_channels = 0; 3461 uint_t dir, count; 3462 short muteval; 3463 3464 ASSERT(uacp != NULL); 3465 3466 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 3467 "usb_ac_set_config: Begin ahdl=0x%p\n\t" 3468 "stream=%d, cmd=%d, flag=%d, arg1=%d, arg2=%d", 3469 (void *)ahdl, stream, command, flag, arg1, arg2); 3470 3471 mutex_enter(&uacp->usb_ac_mutex); 3472 if (uacp->usb_ac_plumbing_state < USB_AC_STATE_PLUMBED) { 3473 mutex_exit(&uacp->usb_ac_mutex); 3474 3475 return (AUDIO_FAILURE); 3476 } 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 3618done: 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 */ 3636static int 3637usb_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 */ 3724static int 3725usb_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 */ 3829static int 3830usb_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", (void *)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 */ 3962static int 3963usb_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 */ 3975static usb_audio_formats_t * 3976usb_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 */ 4004static int 4005usb_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", (void *)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 (void *)plumb_infop, (void *)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 */ 4099static int 4100usb_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 (void *)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 (void *)plumb_infop, (void *)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 */ 4184static void 4185usb_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 (void *)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 */ 4216static void 4217usb_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 (void *)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 */ 4259static void 4260usb_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 (void *)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 */ 4282static int 4283usb_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 (void *)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 */ 4343static void 4344usb_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 (void *)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 */ 4368static void 4369usb_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 (void *)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 */ 4414static int 4415usb_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, (void *)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(MBLKL(data) == 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 */ 4472static int 4473usb_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 */ 4522static int 4523usb_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 */ 4580static int 4581usb_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 (void *)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 if (rval == -1) { 4676 USB_DPRINTF_L3(PRINT_MASK_ALL, 4677 uacp->usb_ac_log_handle, 4678 "usb_ac_send_as_cmd:" 4679 " timeout happen before cmd complete."); 4680 } else { 4681 USB_DPRINTF_L3(PRINT_MASK_ALL, 4682 uacp->usb_ac_log_handle, 4683 "usb_ac_send_as_cmd:" 4684 " not signaled by USB_AS_PLUMBED."); 4685 } 4686 } 4687#endif 4688 } 4689 4690 /* Wait is over, get the reply data */ 4691 mp = streams_infop->acs_ac_to_as_req.acr_reply_mp; 4692 ASSERT(mp != NULL); 4693 4694 iocp = (struct iocblk *)mp->b_rptr; 4695 4696 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4697 "usb_ac_send_as_cmd: db_type=0x%x cmd=0x%x", 4698 mp->b_datap->db_type, iocp->ioc_cmd); 4699 4700 switch (mp->b_datap->db_type) { 4701 case M_CTL: 4702 switch (iocp->ioc_cmd) { 4703 case USB_AUDIO_SET_FORMAT: 4704 /* 4705 * This command sets mixer format data 4706 * and returns alternate setting that matches 4707 */ 4708 ASSERT(mp->b_cont != NULL); 4709 ASSERT(MBLKL(mp->b_cont) == sizeof (int)); 4710 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4711 "alternate returned %d", 4712 *((int *)(mp->b_cont->b_rptr))); 4713 4714 streams_infop->acs_ac_to_as_req.acr_curr_format. 4715 fmt_alt = *((int *)(mp->b_cont->b_rptr)); 4716 4717 /*FALLTHROUGH*/ 4718 case USB_AUDIO_SET_SAMPLE_FREQ: 4719 case USB_AUDIO_SETUP: 4720 case USB_AUDIO_START_PLAY: 4721 case USB_AUDIO_PAUSE_PLAY: 4722 case USB_AUDIO_START_RECORD: 4723 case USB_AUDIO_STOP_RECORD: 4724 case USB_AUDIO_TEARDOWN: 4725 error = USB_SUCCESS; 4726 break; 4727 default: 4728 break; 4729 } 4730 break; 4731 case M_ERROR: 4732 default: 4733 error = USB_FAILURE; 4734 } 4735 4736 if (mp) { 4737 usb_ac_free_mblk(mp); 4738 streams_infop->acs_ac_to_as_req.acr_reply_mp = NULL; 4739 } 4740 4741 return (error); 4742} 4743 4744 4745/* 4746 * usb_ac_allocate_req_mblk: 4747 * Allocate a message block with the specified M_CTL cmd, 4748 * The 2nd mblk contains the data for the command with a length len 4749 */ 4750static mblk_t * 4751usb_ac_allocate_req_mblk(usb_ac_state_t *uacp, int cmd, void *buf, uint_t len) 4752{ 4753 mblk_t *mp, *mp2; 4754 struct iocblk *mctlmsg; 4755 4756 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4757 "usb_ac_allocate_req_mblk: cmd=0x%x, buf=0x%p, len=%d", 4758 cmd, buf, len); 4759 4760 mp = allocb_wait(sizeof (struct iocblk), BPRI_HI, STR_NOSIG, NULL); 4761 mp->b_datap->db_type = M_CTL; 4762 mctlmsg = (struct iocblk *)mp->b_datap->db_base; 4763 mctlmsg->ioc_cmd = cmd; 4764 mctlmsg->ioc_count = len; 4765 4766 mp->b_wptr = mp->b_wptr + sizeof (struct iocblk); 4767 4768 if ((len == 0) || (buf == NULL)) { 4769 4770 return (mp); 4771 } 4772 4773 mp2 = allocb_wait(len, BPRI_HI, STR_NOSIG, NULL); 4774 mp->b_cont = mp2; 4775 bcopy(buf, mp->b_cont->b_datap->db_base, len); 4776 mp->b_cont->b_wptr = mp->b_cont->b_wptr + len; 4777 4778 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle, 4779 "usb_ac_allocate_req_mblk: mp=0x%p", (void *)mp); 4780 4781 return (mp); 4782} 4783 4784 4785/* 4786 * usb_ac_free_mblk: 4787 * Free the message block 4788 */ 4789static void 4790usb_ac_free_mblk(mblk_t *mp) 4791{ 4792 if (mp->b_cont) { 4793 freemsg(mp->b_cont); 4794 mp->b_cont = NULL; 4795 } 4796 freemsg(mp); 4797} 4798 4799 4800/* 4801 * usb_ac_serialize/release_access: 4802 */ 4803static void 4804usb_ac_serialize_access(usb_ac_state_t *uacp) 4805{ 4806 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0); 4807} 4808 4809static void 4810usb_ac_release_access(usb_ac_state_t *uacp) 4811{ 4812 usb_release_access(uacp->usb_ac_ser_acc); 4813} 4814 4815 4816static void 4817usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep) 4818{ 4819 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 4820 4821 if (usb_ac_statep->usb_ac_pm != NULL) { 4822 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4823 usb_ac_statep->usb_ac_pm->acpm_pm_busy++; 4824 4825 USB_DPRINTF_L4(PRINT_MASK_PM, 4826 usb_ac_statep->usb_ac_log_handle, 4827 "usb_ac_pm_busy_component: %d", 4828 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4829 4830 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4831 4832 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) != 4833 DDI_SUCCESS) { 4834 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4835 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 4836 4837 USB_DPRINTF_L2(PRINT_MASK_PM, 4838 usb_ac_statep->usb_ac_log_handle, 4839 "usb_ac_pm_busy_component failed: %d", 4840 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4841 4842 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4843 } 4844 } 4845} 4846 4847 4848static void 4849usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep) 4850{ 4851 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex)); 4852 4853 if (usb_ac_statep->usb_ac_pm != NULL) { 4854 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) == 4855 DDI_SUCCESS) { 4856 mutex_enter(&usb_ac_statep->usb_ac_mutex); 4857 ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0); 4858 usb_ac_statep->usb_ac_pm->acpm_pm_busy--; 4859 4860 USB_DPRINTF_L4(PRINT_MASK_PM, 4861 usb_ac_statep->usb_ac_log_handle, 4862 "usb_ac_pm_idle_component: %d", 4863 usb_ac_statep->usb_ac_pm->acpm_pm_busy); 4864 4865 mutex_exit(&usb_ac_statep->usb_ac_mutex); 4866 } 4867 } 4868} 4869