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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * AUDIO CONTROL Driver:
  28  *
  29  * usb_ac is a multiplexor that sits on top of usb_as and hid and is
  30  * responsible for (1) providing the entry points to audio mixer framework,
  31  * (2) passing control commands to and from usb_as and hid and (3) processing
  32  * control messages from hid/usb_ah 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: A competing thread can't be allowed to interfere with
  47  * (1) pipe, (2) streams state.
  48  * So we need some kind of serialization among the asynchronous
  49  * threads that can run in the driver. The serialization is mostly
  50  * needed to avoid races among open/close/events/power entry points
  51  * etc. Once a routine takes control, it checks if the resource (pipe or
  52  * stream or dev state) is still accessible. If so, it proceeds with
  53  * its job and until it completes, no other thread requiring the same
  54  * resource can run.
  55  *
  56  * PM model in usb_ac: Raise power during attach. If a device is not at full
  57  * power, raise power in the entry points. After the command is over,
  58  * pm_idle_component() is called. The power is lowered in detach().
  59  */
  60 #include <sys/usb/usba/usbai_version.h>
  61 #include <sys/usb/usba.h>
  62 #include <sys/sunndi.h>
  63 #include <sys/strsubr.h>
  64 #include <sys/strsun.h>
  65 #include <sys/ddi.h>
  66 #include <sys/sunddi.h>
  67 #include <sys/sunldi.h>
  68 
  69 #include <sys/audio/audio_driver.h>
  70 
  71 #include <sys/usb/clients/audio/usb_audio.h>
  72 #include <sys/usb/clients/audio/usb_mixer.h>
  73 #include <sys/usb/clients/audio/usb_ac/usb_ac.h>
  74 
  75 /* for getting the minor node info from hid */
  76 #include <sys/usb/clients/hid/hidminor.h>
  77 #include <sys/usb/clients/audio/usb_as/usb_as.h>
  78 
  79 
  80 /* debug support */
  81 uint_t  usb_ac_errlevel         = USB_LOG_L4;
  82 uint_t  usb_ac_errmask          = (uint_t)-1;
  83 uint_t  usb_ac_instance_debug   = (uint_t)-1;
  84 
  85 /*
  86  * wait period in seconds for the HID message processing thread
  87  * used primarily to check when the stream has closed
  88  */
  89 uint_t usb_ac_wait_hid = 1;
  90 
  91 /*
  92  * table for converting term types of input and output terminals
  93  * to OSS port types (pretty rough mapping)
  94  */
  95 static const char *usb_audio_dtypes[] = {
  96         AUDIO_PORT_LINEIN,
  97         AUDIO_PORT_LINEOUT,
  98         AUDIO_PORT_SPEAKER,
  99         AUDIO_PORT_HEADPHONES,
 100         AUDIO_PORT_HANDSET,
 101         AUDIO_PORT_CD,
 102         AUDIO_PORT_MIC,
 103         AUDIO_PORT_PHONE,
 104         AUDIO_PORT_SPDIFIN,
 105         AUDIO_PORT_OTHER,
 106         NULL,
 107 };
 108 enum {
 109         USB_PORT_LINEIN = 0,
 110         USB_PORT_LINEOUT,
 111         USB_PORT_SPEAKER,
 112         USB_PORT_HEADPHONES,
 113         USB_PORT_HANDSET,
 114         USB_PORT_CD,
 115         USB_PORT_MIC,
 116         USB_PORT_PHONE,
 117         USB_PORT_SPDIFIN,
 118         USB_PORT_UNKNOWN
 119 };
 120 
 121 static struct {
 122         ushort_t        term_type;
 123         uint_t  port_type;
 124 } usb_ac_term_type_map[] = {
 125 
 126         /* Input Terminal Types */
 127 { USB_AUDIO_TERM_TYPE_MICROPHONE,               USB_PORT_MIC },
 128 { USB_AUDIO_TERM_TYPE_DT_MICROPHONE,            USB_PORT_MIC },
 129 { USB_AUDIO_TERM_TYPE_PERS_MICROPHONE,          USB_PORT_MIC },
 130 { USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE,      USB_PORT_MIC },
 131 { USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY,         USB_PORT_MIC },
 132 { USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY,     USB_PORT_MIC },
 133 
 134         /* Output Terminal Types */
 135 { USB_AUDIO_TERM_TYPE_SPEAKER,                  USB_PORT_SPEAKER },
 136 { USB_AUDIO_TERM_TYPE_HEADPHONES,               USB_PORT_HEADPHONES },
 137 { USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO,            USB_PORT_LINEOUT },
 138 { USB_AUDIO_TERM_TYPE_DT_SPEAKER,               USB_PORT_SPEAKER },
 139 { USB_AUDIO_TERM_TYPE_ROOM_SPEAKER,             USB_PORT_SPEAKER },
 140 { USB_AUDIO_TERM_TYPE_COMM_SPEAKER,             USB_PORT_SPEAKER },
 141 { USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER,       USB_PORT_SPEAKER },
 142 
 143         /* Bi-directional Terminal Types */
 144 { USB_AUDIO_TERM_TYPE_HANDSET,          USB_PORT_HANDSET },
 145 
 146         /* Telephony Terminal Types */
 147 { USB_AUDIO_TERM_TYPE_PHONE_LINE,       USB_PORT_PHONE},
 148 { USB_AUDIO_TERM_TYPE_TELEPHONE,        USB_PORT_PHONE},
 149 { USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE,  USB_PORT_PHONE },
 150 
 151         /* External Terminal Types */
 152 { USB_AUDIO_TERM_TYPE_SPDIF_IF,         USB_PORT_SPDIFIN },
 153         /* Embedded Function Terminal Types */
 154 { USB_AUDIO_TERM_TYPE_CD_PLAYER,        USB_PORT_CD },
 155 { 0, 0 }
 156 };
 157 
 158 
 159 /*
 160  * Module linkage routines for the kernel
 161  */
 162 static int      usb_ac_attach(dev_info_t *, ddi_attach_cmd_t);
 163 static int      usb_ac_detach(dev_info_t *, ddi_detach_cmd_t);
 164 static int      usb_ac_power(dev_info_t *, int, int);
 165 
 166 static uint_t   usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
 167                                 uint_t);
 168 
 169 /* module entry points */
 170 int             usb_ac_open(dev_info_t *);
 171 void            usb_ac_close(dev_info_t *);
 172 
 173 /* descriptor handling */
 174 static int      usb_ac_handle_descriptors(usb_ac_state_t *);
 175 static void     usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t);
 176 static void     usb_ac_alloc_unit(usb_ac_state_t *, uint_t);
 177 static void     usb_ac_free_all_units(usb_ac_state_t *);
 178 static void     usb_ac_setup_connections(usb_ac_state_t *);
 179 static void     usb_ac_map_termtype_to_port(usb_ac_state_t *, uint_t);
 180 
 181 /* power management */
 182 static int      usb_ac_pwrlvl0(usb_ac_state_t *);
 183 static int      usb_ac_pwrlvl1(usb_ac_state_t *);
 184 static int      usb_ac_pwrlvl2(usb_ac_state_t *);
 185 static int      usb_ac_pwrlvl3(usb_ac_state_t *);
 186 static void     usb_ac_create_pm_components(dev_info_t *, usb_ac_state_t *);
 187 static void     usb_ac_pm_busy_component(usb_ac_state_t *);
 188 static void     usb_ac_pm_idle_component(usb_ac_state_t *);
 189 
 190 /* event handling */
 191 static int      usb_ac_disconnect_event_cb(dev_info_t *);
 192 static int      usb_ac_reconnect_event_cb(dev_info_t *);
 193 static int      usb_ac_cpr_suspend(dev_info_t *);
 194 static void     usb_ac_cpr_resume(dev_info_t *);
 195 
 196 static usb_event_t usb_ac_events = {
 197         usb_ac_disconnect_event_cb,
 198         usb_ac_reconnect_event_cb,
 199         NULL, NULL
 200 };
 201 
 202 /* misc. support */
 203 static void     usb_ac_restore_device_state(dev_info_t *, usb_ac_state_t *);
 204 static int      usb_ac_cleanup(dev_info_t *, usb_ac_state_t *);
 205 static void     usb_ac_serialize_access(usb_ac_state_t *);
 206 static void     usb_ac_release_access(usb_ac_state_t *);
 207 
 208 static void     usb_ac_push_unit_id(usb_ac_state_t *, uint_t);
 209 static void     usb_ac_pop_unit_id(usb_ac_state_t *, uint_t);
 210 static void     usb_ac_show_traverse_path(usb_ac_state_t *);
 211 static int      usb_ac_check_path(usb_ac_state_t *, uint_t);
 212 
 213 static uint_t   usb_ac_traverse_connections(usb_ac_state_t *, uint_t, uint_t,
 214                                 uint_t, uint_t, uint_t, uint_t,
 215                                 uint_t *, uint_t, uint_t *,
 216                                 int (*func)(usb_ac_state_t *, uint_t, uint_t,
 217                                 uint_t, uint_t, uint_t, uint_t *));
 218 static uint_t   usb_ac_set_port(usb_ac_state_t *, uint_t, uint_t);
 219 static uint_t   usb_ac_set_control(usb_ac_state_t *, uint_t, uint_t,
 220                                 uint_t, uint_t, uint_t,
 221                                 uint_t *, uint_t,
 222                                 int (*func)(usb_ac_state_t *, uint_t, uint_t,
 223                                 uint_t, uint_t, uint_t, uint_t *));
 224 static uint_t   usb_ac_set_monitor_gain_control(usb_ac_state_t *, uint_t,
 225                                 uint_t, uint_t, uint_t, uint_t,
 226                                 uint_t *, uint_t,
 227                                 int (*func)(usb_ac_state_t *, uint_t, uint_t,
 228                                 uint_t, uint_t, uint_t, uint_t *));
 229 static uint_t   usb_ac_traverse_all_units(usb_ac_state_t *, uint_t, uint_t,
 230                                 uint_t, uint_t, uint_t, uint_t *,
 231                                 uint_t, uint_t *,
 232                                 int (*func)(usb_ac_state_t *, uint_t, uint_t,
 233                                 uint_t, uint_t, uint_t, uint_t *));
 234 static int      usb_ac_update_port(usb_ac_state_t *, uint_t,
 235                                 uint_t, uint_t, uint_t, uint_t, uint_t *);
 236 static int      usb_ac_set_selector(usb_ac_state_t *, uint_t,
 237                                 uint_t, uint_t, uint_t, uint_t, uint_t *);
 238 static int      usb_ac_feature_unit_check(usb_ac_state_t *, uint_t,
 239                                 uint_t, uint_t, uint_t, uint_t, uint_t *);
 240 static int      usb_ac_set_gain(usb_ac_state_t *, uint_t,
 241                                 uint_t, uint_t, uint_t, uint_t, uint_t *);
 242 static int      usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t,
 243                                 uint_t, uint_t, uint_t, uint_t, uint_t *);
 244 static int      usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir,
 245                                 int);
 246 static int      usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int,
 247                                 int, short *);
 248 static int      usb_ac_send_as_cmd(usb_ac_state_t *, usb_audio_eng_t *,
 249                                 int, void *);
 250 static int      usb_ac_set_format(usb_ac_state_t *, usb_audio_eng_t *);
 251 static int      usb_ac_do_setup(usb_ac_state_t *, usb_audio_eng_t *);
 252 
 253 /*  usb audio basic function entries */
 254 static int      usb_ac_setup(usb_ac_state_t *, usb_audio_eng_t *);
 255 static void     usb_ac_teardown(usb_ac_state_t *, usb_audio_eng_t *);
 256 static int      usb_ac_start_play(usb_ac_state_t *, usb_audio_eng_t *);
 257 static int      usb_ac_start_record(usb_ac_state_t *, usb_audio_eng_t *);
 258 static void     usb_ac_stop_record(usb_ac_state_t *, usb_audio_eng_t *);
 259 static int      usb_ac_restore_audio_state(usb_ac_state_t *, int);
 260 
 261 static int      usb_ac_ctrl_restore(usb_ac_state_t *);
 262 /*
 263  * Mux
 264  */
 265 static int      usb_ac_mux_walk_siblings(usb_ac_state_t *);
 266 static void     usb_ac_print_reg_data(usb_ac_state_t *,
 267                                 usb_as_registration_t *);
 268 static int      usb_ac_get_reg_data(usb_ac_state_t *, ldi_handle_t, int);
 269 static int      usb_ac_setup_plumbed(usb_ac_state_t *, int, int);
 270 static int      usb_ac_mixer_registration(usb_ac_state_t *);
 271 static void     usb_ac_hold_siblings(usb_ac_state_t *);
 272 static int      usb_ac_online_siblings(usb_ac_state_t *);
 273 static void     usb_ac_rele_siblings(usb_ac_state_t *);
 274 static int      usb_ac_mux_plumbing(usb_ac_state_t *);
 275 static void     usb_ac_mux_plumbing_tq(void *);
 276 static int      usb_ac_mux_unplumbing(usb_ac_state_t *);
 277 static void     usb_ac_mux_unplumbing_tq(void *);
 278 static int      usb_ac_plumb(usb_ac_plumbed_t *);
 279 static void     usb_ac_unplumb(usb_ac_plumbed_t *);
 280 static void     usb_ac_reader(void *);
 281 static int      usb_ac_read_msg(usb_ac_plumbed_t *, mblk_t *);
 282 static int      usb_ac_do_plumbing(usb_ac_state_t *);
 283 static int      usb_ac_do_unplumbing(usb_ac_state_t *);
 284 
 285 
 286 static int usb_change_phy_vol(usb_ac_state_t *, int);
 287 static void usb_restore_engine(usb_ac_state_t *);
 288 
 289 /* anchor for soft state structures */
 290 void    *usb_ac_statep;
 291 
 292 /*
 293  * DDI Structures
 294  */
 295 
 296 /* Device operations structure */
 297 static struct dev_ops usb_ac_dev_ops = {
 298         DEVO_REV,               /* devo_rev */
 299         0,                      /* devo_refcnt */
 300         NULL,                   /* devo_getinfo */
 301         nulldev,                /* devo_identify - obsolete */
 302         nulldev,                /* devo_probe - not needed */
 303         usb_ac_attach,          /* devo_attach */
 304         usb_ac_detach,          /* devo_detach */
 305         nodev,                  /* devo_reset */
 306         NULL,                   /* devi_cb_ops */
 307         NULL,                   /* devo_busb_ac_ops */
 308         usb_ac_power,           /* devo_power */
 309         ddi_quiesce_not_needed, /* devo_quiesce */
 310 };
 311 
 312 /* Linkage structure for loadable drivers */
 313 static struct modldrv usb_ac_modldrv = {
 314         &mod_driverops,                             /* drv_modops */
 315         "USB Audio Control Driver",             /* drv_linkinfo */
 316         &usb_ac_dev_ops                             /* drv_dev_ops */
 317 };
 318 
 319 /* Module linkage structure */
 320 static struct modlinkage usb_ac_modlinkage = {
 321         MODREV_1,                       /* ml_rev */
 322         (void *)&usb_ac_modldrv,    /* ml_linkage */
 323         NULL                            /* NULL terminates the list */
 324 };
 325 
 326 static int usb_audio_register(usb_ac_state_t *);
 327 static int usb_audio_unregister(usb_ac_state_t *);
 328 
 329 static int usb_engine_open(void *, int, unsigned *, caddr_t *);
 330 static void usb_engine_close(void *);
 331 static uint64_t usb_engine_count(void *);
 332 static int usb_engine_start(void *);
 333 static void usb_engine_stop(void *);
 334 static int usb_engine_format(void *);
 335 static int usb_engine_channels(void *);
 336 static int usb_engine_rate(void *);
 337 static void usb_engine_sync(void *, unsigned);
 338 static unsigned usb_engine_qlen(void *);
 339 
 340 /* engine buffer size in terms of fragments */
 341 
 342 audio_engine_ops_t usb_engine_ops = {
 343         AUDIO_ENGINE_VERSION,
 344         usb_engine_open,
 345         usb_engine_close,
 346         usb_engine_start,
 347         usb_engine_stop,
 348         usb_engine_count,
 349         usb_engine_format,
 350         usb_engine_channels,
 351         usb_engine_rate,
 352         usb_engine_sync,
 353         usb_engine_qlen,
 354 };
 355 
 356 
 357 
 358 _NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
 359 
 360 /* standard entry points */
 361 int
 362 _init(void)
 363 {
 364         int rval;
 365 
 366         /* initialize the soft state */
 367         if ((rval = ddi_soft_state_init(&usb_ac_statep,
 368             sizeof (usb_ac_state_t), 1)) != DDI_SUCCESS) {
 369                 return (rval);
 370         }
 371 
 372         audio_init_ops(&usb_ac_dev_ops, "usb_ac");
 373 
 374         if ((rval = mod_install(&usb_ac_modlinkage)) != 0) {
 375                 ddi_soft_state_fini(&usb_ac_statep);
 376                 audio_fini_ops(&usb_ac_dev_ops);
 377         }
 378 
 379         return (rval);
 380 }
 381 
 382 int
 383 _fini(void)
 384 {
 385         int rval;
 386 
 387         if ((rval = mod_remove(&usb_ac_modlinkage)) == 0) {
 388                 /* Free the soft state internal structures */
 389                 ddi_soft_state_fini(&usb_ac_statep);
 390                 audio_fini_ops(&usb_ac_dev_ops);
 391         }
 392 
 393         return (rval);
 394 }
 395 
 396 int
 397 _info(struct modinfo *modinfop)
 398 {
 399         return (mod_info(&usb_ac_modlinkage, modinfop));
 400 }
 401 
 402 extern  uint_t          nproc;
 403 #define INIT_PROCESS_CNT 3
 404 
 405 static int
 406 usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 407 {
 408         usb_ac_state_t          *uacp = NULL;
 409         int                     instance = ddi_get_instance(dip);
 410 
 411         switch (cmd) {
 412                 case DDI_ATTACH:
 413                         break;
 414                 case DDI_RESUME:
 415                         usb_ac_cpr_resume(dip);
 416 
 417                         return (DDI_SUCCESS);
 418                 default:
 419                         return (DDI_FAILURE);
 420         }
 421 
 422         /*
 423          * wait  until all processes are started from main.
 424          * USB enumerates early in boot (ie. consconfig time).
 425          * If the plumbing takes place early, the file descriptors
 426          * are owned by the init process and can never be closed anymore
 427          * Consequently, hot removal is not possible and the dips
 428          * never go away. By waiting some time, e.g. INIT_PROCESS_CNT,
 429          * the problem is avoided.
 430          */
 431         if (nproc < INIT_PROCESS_CNT) {
 432                 USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL,
 433                     "usb_ac%d attach too early", instance);
 434 
 435                 return (DDI_FAILURE);
 436         }
 437 
 438         /*
 439          * Allocate soft state information.
 440          */
 441         if (ddi_soft_state_zalloc(usb_ac_statep, instance) != DDI_SUCCESS) {
 442 
 443                 goto fail;
 444         }
 445 
 446         /*
 447          * get soft state space and initialize
 448          */
 449         uacp = (usb_ac_state_t *)ddi_get_soft_state(usb_ac_statep, instance);
 450         if (uacp == NULL) {
 451 
 452                 goto fail;
 453         }
 454 
 455         /* get log handle */
 456         uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac",
 457             &usb_ac_errlevel,
 458             &usb_ac_errmask, &usb_ac_instance_debug,
 459             0);
 460 
 461         uacp->usb_ac_instance = instance;
 462         uacp->usb_ac_dip = dip;
 463 
 464         (void) snprintf(uacp->dstr, sizeof (uacp->dstr), "%s#%d",
 465             ddi_driver_name(dip), instance);
 466 
 467         if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
 468                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 469                     "usb_client_attach failed");
 470 
 471                 usb_free_log_hdl(uacp->usb_ac_log_handle);
 472                 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
 473 
 474                 return (DDI_FAILURE);
 475         }
 476 
 477         if (usb_get_dev_data(dip, &uacp->usb_ac_dev_data,
 478             USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
 479                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 480                     "usb_get_dev_data failed");
 481 
 482                 usb_client_detach(dip, NULL);
 483                 usb_free_log_hdl(uacp->usb_ac_log_handle);
 484                 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
 485 
 486                 return (DDI_FAILURE);
 487         }
 488 
 489         /* initialize mutex & cv */
 490         mutex_init(&uacp->usb_ac_mutex, NULL, MUTEX_DRIVER,
 491             uacp->usb_ac_dev_data->dev_iblock_cookie);
 492 
 493         uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph;
 494 
 495         /* parse all class specific descriptors */
 496         if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) {
 497 
 498                 goto fail;
 499         }
 500 
 501         /* we no longer need the descr tree */
 502         usb_free_descr_tree(dip, uacp->usb_ac_dev_data);
 503 
 504         uacp->usb_ac_ser_acc = usb_init_serialization(dip,
 505             USB_INIT_SER_CHECK_SAME_THREAD);
 506 
 507         mutex_enter(&uacp->usb_ac_mutex);
 508 
 509         /* we are online */
 510         uacp->usb_ac_dev_state = USB_DEV_ONLINE;
 511 
 512         /*
 513          * safe guard the postattach to be executed
 514          * only two states arepossible: plumbed / unplumbed
 515          */
 516         uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
 517         uacp->usb_ac_current_plumbed_index = -1;
 518 
 519         mutex_exit(&uacp->usb_ac_mutex);
 520 
 521         /* create components to power manage this device */
 522         usb_ac_create_pm_components(dip, uacp);
 523 
 524         /* Register for events */
 525         if (usb_register_event_cbs(dip, &usb_ac_events, 0) != USB_SUCCESS) {
 526                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 527                     "usb_ac_attach: couldn't register for events");
 528 
 529                 goto fail;
 530         }
 531 
 532         USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 533             "usb_ac_attach: End");
 534 
 535         /* report device */
 536         ddi_report_dev(dip);
 537 
 538         if (usb_ac_do_plumbing(uacp) != USB_SUCCESS)
 539                 goto fail;
 540 
 541         return (DDI_SUCCESS);
 542 
 543 fail:
 544         if (uacp) {
 545                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 546                     "attach failed");
 547 
 548                 /* wait for plumbing thread to finish */
 549                 if (uacp->tqp != NULL) {
 550                         ddi_taskq_wait(uacp->tqp);
 551                         ddi_taskq_destroy(uacp->tqp);
 552                         uacp->tqp = NULL;
 553                 }
 554                 (void) usb_ac_cleanup(dip, uacp);
 555         }
 556 
 557         return (DDI_FAILURE);
 558 }
 559 
 560 
 561 static int
 562 usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 563 {
 564         int instance = ddi_get_instance(dip);
 565         usb_ac_state_t  *uacp;
 566         int rval = USB_FAILURE;
 567 
 568         uacp = ddi_get_soft_state(usb_ac_statep, instance);
 569 
 570         switch (cmd) {
 571         case DDI_DETACH:
 572                 USB_DPRINTF_L4(PRINT_MASK_ATTA,
 573                     uacp->usb_ac_log_handle, "usb_ac_detach: detach");
 574 
 575                 /* wait for plumbing thread to finish */
 576                 if (uacp->tqp != NULL)
 577                         ddi_taskq_wait(uacp->tqp);
 578 
 579                 mutex_enter(&uacp->usb_ac_mutex);
 580 
 581                 /* do not allow detach if still busy */
 582                 if (uacp->usb_ac_busy_count) {
 583                         USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 584                             "usb_ac_detach:still busy, usb_ac_busy_count = %d",
 585                             uacp->usb_ac_busy_count);
 586 
 587                         mutex_exit(&uacp->usb_ac_mutex);
 588                         return (USB_FAILURE);
 589                 }
 590                 mutex_exit(&uacp->usb_ac_mutex);
 591 
 592                 (void) usb_audio_unregister(uacp);
 593 
 594 
 595 
 596                 /*
 597                  * unplumb to stop activity from other modules, then
 598                  * cleanup, which will also teardown audio framework state
 599                  */
 600                 if (usb_ac_do_unplumbing(uacp) == USB_SUCCESS)
 601                         rval = usb_ac_cleanup(dip, uacp);
 602 
 603                 if (rval != USB_SUCCESS) {
 604                         USB_DPRINTF_L2(PRINT_MASK_ATTA,
 605                             uacp->usb_ac_log_handle, "detach failed: %s%d",
 606                             ddi_driver_name(dip), instance);
 607                 }
 608 
 609                 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
 610         case DDI_SUSPEND:
 611                 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 612                     "usb_ac_detach: suspending");
 613 
 614                 rval = usb_ac_cpr_suspend(dip);
 615 
 616                 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
 617         default:
 618 
 619                 return (DDI_FAILURE);
 620         }
 621 }
 622 
 623 
 624 /*
 625  * usb_ac_cleanup:
 626  *      cleanup on attach failure and detach
 627  */
 628 static int
 629 usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
 630 {
 631         usb_ac_power_t  *uacpm;
 632         int     rval = USB_FAILURE;
 633 
 634 
 635         mutex_enter(&uacp->usb_ac_mutex);
 636         uacpm = uacp->usb_ac_pm;
 637 
 638         USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
 639             "usb_ac_cleanup:begain");
 640 
 641         ASSERT(uacp->usb_ac_busy_count == 0);
 642 
 643         ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED);
 644 
 645         mutex_exit(&uacp->usb_ac_mutex);
 646 
 647         /*
 648          * Disable the event callbacks, after this point, event
 649          * callbacks will never get called. Note we shouldn't hold
 650          * the mutex while unregistering events because there may be a
 651          * competing event callback thread. Event callbacks are done
 652          * with ndi mutex held and this can cause a potential deadlock.
 653          */
 654         usb_unregister_event_cbs(dip, &usb_ac_events);
 655 
 656         mutex_enter(&uacp->usb_ac_mutex);
 657 
 658         if (uacpm && (uacp->usb_ac_dev_state != USB_DEV_DISCONNECTED)) {
 659                 if (uacpm->acpm_wakeup_enabled) {
 660                         mutex_exit(&uacp->usb_ac_mutex);
 661                         usb_ac_pm_busy_component(uacp);
 662                         (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
 663 
 664                         rval = usb_handle_remote_wakeup(dip,
 665                             USB_REMOTE_WAKEUP_DISABLE);
 666                         if (rval != USB_SUCCESS) {
 667                                 USB_DPRINTF_L2(PRINT_MASK_PM,
 668                                     uacp->usb_ac_log_handle,
 669                                     "usb_ac_cleanup: disable remote "
 670                                     "wakeup failed, rval=%d", rval);
 671                         }
 672                         usb_ac_pm_idle_component(uacp);
 673                 } else {
 674                         mutex_exit(&uacp->usb_ac_mutex);
 675                 }
 676 
 677                 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
 678 
 679                 mutex_enter(&uacp->usb_ac_mutex);
 680         }
 681 
 682         if (uacpm) {
 683                 kmem_free(uacpm,  sizeof (usb_ac_power_t));
 684                 uacp->usb_ac_pm = NULL;
 685         }
 686 
 687         usb_client_detach(dip, uacp->usb_ac_dev_data);
 688 
 689         /* free descriptors */
 690         usb_ac_free_all_units(uacp);
 691 
 692         mutex_exit(&uacp->usb_ac_mutex);
 693 
 694         mutex_destroy(&uacp->usb_ac_mutex);
 695 
 696         usb_fini_serialization(uacp->usb_ac_ser_acc);
 697 
 698         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
 699             "usb_ac_cleanup: Ending");
 700 
 701         usb_free_log_hdl(uacp->usb_ac_log_handle);
 702         kmem_free(uacp->usb_ac_connections, uacp->usb_ac_connections_len);
 703         kmem_free(uacp->usb_ac_connections_a, uacp->usb_ac_connections_a_len);
 704         kmem_free(uacp->usb_ac_unit_type, uacp->usb_ac_max_unit);
 705         kmem_free(uacp->usb_ac_traverse_path, uacp->usb_ac_max_unit);
 706 
 707         ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
 708 
 709         ddi_prop_remove_all(dip);
 710 
 711         return (USB_SUCCESS);
 712 }
 713 
 714 
 715 int
 716 usb_ac_open(dev_info_t *dip)
 717 {
 718         int inst = ddi_get_instance(dip);
 719         usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
 720 
 721         mutex_enter(&uacp->usb_ac_mutex);
 722 
 723         uacp->usb_ac_busy_count++;
 724 
 725         mutex_exit(&uacp->usb_ac_mutex);
 726 
 727         usb_ac_pm_busy_component(uacp);
 728         (void) pm_raise_power(uacp->usb_ac_dip, 0, USB_DEV_OS_FULL_PWR);
 729 
 730         return (0);
 731 }
 732 
 733 
 734 void
 735 usb_ac_close(dev_info_t *dip)
 736 {
 737         int inst = ddi_get_instance(dip);
 738         usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
 739 
 740         mutex_enter(&uacp->usb_ac_mutex);
 741 
 742         if (uacp->usb_ac_busy_count > 0)
 743                 uacp->usb_ac_busy_count--;
 744 
 745         mutex_exit(&uacp->usb_ac_mutex);
 746 
 747         usb_ac_pm_idle_component(uacp);
 748 }
 749 
 750 
 751 /*
 752  * usb_ac_read_msg:
 753  *      Handle asynchronous response from opened streams
 754  */
 755 static int
 756 usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
 757 {
 758         usb_ac_state_t  *uacp = plumb_infop->acp_uacp;
 759         int error = DDI_SUCCESS;
 760         int     val;
 761         char    val1;
 762         struct iocblk *iocp;
 763 
 764 
 765         ASSERT(mutex_owned(&uacp->usb_ac_mutex));
 766 
 767         /*
 768          * typically an M_CTL is used between modules but in order to pass
 769          * through the streamhead, an M_PROTO type must be used instead
 770          */
 771         switch (mp->b_datap->db_type) {
 772         case M_PROTO:
 773         case M_ERROR:
 774                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
 775                     "M_CTL/M_ERROR");
 776 
 777                 switch (plumb_infop->acp_driver) {
 778                 case USB_AH_PLUMBED:
 779                         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
 780                             "message from hid, instance=%d",
 781                             ddi_get_instance(plumb_infop->acp_dip));
 782 
 783                         iocp = (struct iocblk *)(void *)mp->b_rptr;
 784                         ASSERT(mp->b_cont != NULL);
 785 
 786                         if (uacp->usb_ac_registered_with_mixer) {
 787 
 788                                 val1 = *((char *)mp->b_cont->b_rptr);
 789                                 val = (int)val1;
 790 
 791                                 USB_DPRINTF_L4(PRINT_MASK_ALL,
 792                                     uacp->usb_ac_log_handle, "val1=0x%x(%d),"
 793                                     "val=0x%x(%d)", val1, val1, val, val);
 794 
 795                                 switch (iocp->ioc_cmd) {
 796                                 /* Handle relative volume change */
 797                                 case USB_AUDIO_VOL_CHANGE:
 798                                         /* prevent unplumbing */
 799                                         uacp->usb_ac_busy_count++;
 800                                         if (uacp->usb_ac_plumbing_state ==
 801                                             USB_AC_STATE_PLUMBED) {
 802                                                 mutex_exit(&uacp->usb_ac_mutex);
 803                                                 (void) usb_change_phy_vol(
 804                                                     uacp, val);
 805                                                 mutex_enter(&uacp->
 806                                                     usb_ac_mutex);
 807                                         }
 808                                         uacp->usb_ac_busy_count--;
 809                                         /* FALLTHRU */
 810                                 case USB_AUDIO_MUTE:
 811                                 default:
 812                                         freemsg(mp);
 813                                         break;
 814                                 }
 815                         } else {
 816                                 freemsg(mp);
 817                         }
 818 
 819                         break;
 820                 default:
 821                         USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
 822                             "message from unknown module(%s)",
 823                             ddi_driver_name(plumb_infop->acp_dip));
 824                         freemsg(mp);
 825                 }
 826 
 827                 break;
 828         default:
 829                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
 830                     "Unknown type=%d", mp->b_datap->db_type);
 831                 freemsg(mp);
 832         }
 833 
 834 
 835         return (error);
 836 }
 837 
 838 
 839 /*
 840  * Power Management
 841  * usb_ac_power:
 842  *      power entry point
 843  */
 844 static int
 845 usb_ac_power(dev_info_t *dip, int comp, int level)
 846 {
 847         _NOTE(ARGUNUSED(comp));
 848         int             instance = ddi_get_instance(dip);
 849         usb_ac_state_t  *uacp;
 850         usb_ac_power_t  *uacpm;
 851         int             rval = DDI_FAILURE;
 852 
 853         uacp = ddi_get_soft_state(usb_ac_statep, instance);
 854 
 855         mutex_enter(&uacp->usb_ac_mutex);
 856         uacpm = uacp->usb_ac_pm;
 857 
 858         if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) {
 859                 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
 860                     "usb_ac_power: illegal level=%d pwr_states=%d",
 861                     level, uacpm->acpm_pwr_states);
 862 
 863                 goto done;
 864         }
 865 
 866         switch (level) {
 867         case USB_DEV_OS_PWR_OFF:
 868                 rval = usb_ac_pwrlvl0(uacp);
 869                 break;
 870         case USB_DEV_OS_PWR_1:
 871                 rval = usb_ac_pwrlvl1(uacp);
 872                 break;
 873         case USB_DEV_OS_PWR_2:
 874                 rval = usb_ac_pwrlvl2(uacp);
 875                 break;
 876         case USB_DEV_OS_FULL_PWR:
 877                 rval = usb_ac_pwrlvl3(uacp);
 878                 break;
 879         }
 880 
 881 done:
 882         mutex_exit(&uacp->usb_ac_mutex);
 883 
 884         return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
 885 }
 886 
 887 
 888 /*
 889  * functions to handle power transition for various levels
 890  * These functions act as place holders to issue USB commands
 891  * to the devices to change their power levels
 892  * Level 0 = Device is powered off
 893  * Level 3 = Device if full powered
 894  * Level 1,2 = Intermediate power level of the device as implemented
 895  *      by the hardware.
 896  * Note that Level 0 is OS power-off and Level 3 is OS full-power.
 897  */
 898 static int
 899 usb_ac_pwrlvl0(usb_ac_state_t *uacp)
 900 {
 901         usb_ac_power_t  *uacpm;
 902         int             rval;
 903 
 904         uacpm = uacp->usb_ac_pm;
 905 
 906         switch (uacp->usb_ac_dev_state) {
 907         case USB_DEV_ONLINE:
 908                 /* Deny the powerdown request if the device is busy */
 909                 if (uacpm->acpm_pm_busy != 0) {
 910 
 911                         return (USB_FAILURE);
 912                 }
 913 
 914                 /* Issue USB D3 command to the device here */
 915                 rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip);
 916                 ASSERT(rval == USB_SUCCESS);
 917 
 918                 uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN;
 919                 uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF;
 920 
 921                 /* FALLTHRU */
 922         case USB_DEV_DISCONNECTED:
 923         case USB_DEV_SUSPENDED:
 924         case USB_DEV_PWRED_DOWN:
 925         default:
 926                 return (USB_SUCCESS);
 927         }
 928 }
 929 
 930 
 931 /* ARGSUSED */
 932 static int
 933 usb_ac_pwrlvl1(usb_ac_state_t *uacp)
 934 {
 935         int             rval;
 936 
 937         /* Issue USB D2 command to the device here */
 938         rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip);
 939         ASSERT(rval == USB_SUCCESS);
 940 
 941         return (USB_FAILURE);
 942 }
 943 
 944 
 945 /* ARGSUSED */
 946 static int
 947 usb_ac_pwrlvl2(usb_ac_state_t *uacp)
 948 {
 949         int             rval;
 950 
 951         rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip);
 952         ASSERT(rval == USB_SUCCESS);
 953 
 954         return (USB_FAILURE);
 955 }
 956 
 957 
 958 static int
 959 usb_ac_pwrlvl3(usb_ac_state_t *uacp)
 960 {
 961         usb_ac_power_t  *uacpm;
 962         int             rval;
 963 
 964         uacpm = uacp->usb_ac_pm;
 965 
 966         switch (uacp->usb_ac_dev_state) {
 967         case USB_DEV_PWRED_DOWN:
 968                 /* Issue USB D0 command to the device here */
 969                 rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip);
 970                 ASSERT(rval == USB_SUCCESS);
 971 
 972                 uacp->usb_ac_dev_state = USB_DEV_ONLINE;
 973                 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
 974                 /* FALLTHRU */
 975         case USB_DEV_ONLINE:
 976                 /* we are already in full power */
 977 
 978                 /* FALLTHRU */
 979         case USB_DEV_DISCONNECTED:
 980         case USB_DEV_SUSPENDED:
 981 
 982                 return (USB_SUCCESS);
 983         default:
 984                 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
 985                     "usb_ac_pwerlvl3: Illegal dev_state");
 986 
 987                 return (USB_FAILURE);
 988         }
 989 }
 990 
 991 
 992 static void
 993 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
 994 {
 995         usb_ac_power_t  *uacpm;
 996         uint_t          pwr_states;
 997 
 998         USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
 999             "usb_ac_create_pm_components: begin");
1000 
1001         /* Allocate the state structure */
1002         uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP);
1003         uacp->usb_ac_pm = uacpm;
1004         uacpm->acpm_state = uacp;
1005         uacpm->acpm_capabilities = 0;
1006         uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1007 
1008         if (usb_create_pm_components(dip, &pwr_states) ==
1009             USB_SUCCESS) {
1010                 if (usb_handle_remote_wakeup(dip,
1011                     USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1012                         uacpm->acpm_wakeup_enabled = 1;
1013 
1014                         USB_DPRINTF_L4(PRINT_MASK_PM,
1015                             uacp->usb_ac_log_handle,
1016                             "remote Wakeup enabled");
1017                 }
1018                 uacpm->acpm_pwr_states = (uint8_t)pwr_states;
1019                 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1020         } else {
1021                 if (uacpm) {
1022                         kmem_free(uacpm,  sizeof (usb_ac_power_t));
1023                         uacp->usb_ac_pm = NULL;
1024                 }
1025                 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1026                     "pm not enabled");
1027         }
1028 
1029 }
1030 
1031 /*
1032  * usb_ac_get_featureID:
1033  *      find out if there is at least one feature unit that supports
1034  *      the request controls.
1035  *      Return featureID or USB_AC_ID_NONE.
1036  */
1037 static uint_t
1038 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir,
1039     uint_t channel, uint_t control)
1040 {
1041         uint_t count = 0;
1042 
1043         return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT,
1044             channel, control, USB_AC_FIND_ONE, &count, 0,
1045             usb_ac_feature_unit_check));
1046 }
1047 
1048 
1049 /*
1050  * usb_ac_feature_unit_check:
1051  *      check if a feature unit can support the required channel
1052  *      and control combination. Return USB_SUCCESS or USB_FAILURE.
1053  *      Called for each matching unit from usb_ac_traverse_connections.
1054  */
1055 /*ARGSUSED*/
1056 static int
1057 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
1058     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1059 {
1060         usb_audio_feature_unit_descr1_t *feature_descrp;
1061         int                             n_channel_controls;
1062 
1063 
1064         ASSERT(featureID < uacp->usb_ac_max_unit);
1065 
1066         /*
1067          * check if this control is supported on this channel
1068          */
1069         feature_descrp = (usb_audio_feature_unit_descr1_t *)
1070             uacp->usb_ac_units[featureID].acu_descriptor;
1071         ASSERT(feature_descrp->bUnitID == featureID);
1072 
1073         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1074             "bControlSize=%d", feature_descrp->bControlSize);
1075 
1076         if (feature_descrp->bControlSize == 0) {
1077                 featureID = USB_AC_ID_NONE;
1078         } else {
1079                 uint_t index;
1080 
1081                 n_channel_controls = (feature_descrp->bLength -
1082                     offsetof(usb_audio_feature_unit_descr1_t,
1083                     bmaControls))/feature_descrp->bControlSize;
1084 
1085                 USB_DPRINTF_L3(PRINT_MASK_ALL,
1086                     uacp->usb_ac_log_handle,
1087                     "#controls: %d index=%d", n_channel_controls,
1088                     feature_descrp->bControlSize * channel);
1089 
1090                 if (channel > n_channel_controls) {
1091                         featureID = USB_AC_ID_NONE;
1092                 } else {
1093                         /*
1094                          * we only support MUTE and VOLUME
1095                          * which are in the first byte
1096                          */
1097                         index = feature_descrp->bControlSize *
1098                             channel;
1099 
1100                         USB_DPRINTF_L3(PRINT_MASK_ALL,
1101                             uacp->usb_ac_log_handle,
1102                             "control: 0x%x",
1103                             feature_descrp->bmaControls[index]);
1104 
1105                         if ((feature_descrp->bmaControls[index] &
1106                             control) == 0) {
1107                                 featureID = USB_AC_ID_NONE;
1108                         }
1109                 }
1110         }
1111 
1112         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1113             "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
1114             dir, featureID);
1115 
1116         return ((featureID != USB_AC_ID_NONE) ?
1117             USB_SUCCESS : USB_FAILURE);
1118 }
1119 
1120 
1121 /*
1122  * Descriptor Management
1123  *
1124  * usb_ac_handle_descriptors:
1125  *      extract interesting descriptors from the config cloud
1126  */
1127 static int
1128 usb_ac_handle_descriptors(usb_ac_state_t *uacp)
1129 {
1130         int                     len, index;
1131         int                     rval = USB_FAILURE;
1132         usb_audio_cs_if_descr_t descr;
1133         usb_client_dev_data_t   *dev_data = uacp->usb_ac_dev_data;
1134         usb_alt_if_data_t       *altif_data;
1135         usb_cvs_data_t          *cvs;
1136 
1137 
1138         altif_data = &dev_data->dev_curr_cfg->
1139             cfg_if[dev_data->dev_curr_if].if_alt[0];
1140 
1141         uacp->usb_ac_ifno    = dev_data->dev_curr_if;
1142         uacp->usb_ac_if_descr        = altif_data->altif_descr;
1143 
1144         /* find USB_AUDIO_CS_INTERFACE type descriptor */
1145         for (index = 0; index < altif_data->altif_n_cvs; index++) {
1146                 cvs = &altif_data->altif_cvs[index];
1147                 if (cvs->cvs_buf == NULL) {
1148                         continue;
1149                 }
1150                 if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) {
1151                         break;
1152                 }
1153         }
1154 
1155         if (index == altif_data->altif_n_cvs) {
1156                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1157                     "usb_ac_handle_descriptors:cannot find descriptor type %d",
1158                     USB_AUDIO_CS_INTERFACE);
1159 
1160                 return (rval);
1161         }
1162 
1163         len = usb_parse_data(
1164             CS_AC_IF_HEADER_FORMAT,
1165             cvs->cvs_buf, cvs->cvs_buf_len,
1166             (void *)&descr, sizeof (usb_audio_cs_if_descr_t));
1167 
1168         /* is this a sane header descriptor */
1169         if (!((len >= CS_AC_IF_HEADER_SIZE) &&
1170             (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
1171             (descr.bDescriptorSubType == USB_AUDIO_HEADER))) {
1172                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1173                     "invalid header");
1174 
1175                 return (rval);
1176         }
1177 
1178         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1179             "index %d, header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
1180             "total=0x%x InCol=0x%x",
1181             index,
1182             descr.bDescriptorType,
1183             descr.bDescriptorSubType,
1184             descr.bcdADC,
1185             descr.wTotalLength,
1186             descr.blnCollection);
1187 
1188         /*
1189          * we read descriptors by index and store them in ID array.
1190          * the actual parsing is done in usb_ac_add_unit_descriptor()
1191          */
1192         for (index++; index < altif_data->altif_n_cvs; index++) {
1193                 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1194                     "index=%d", index);
1195 
1196                 cvs = &altif_data->altif_cvs[index];
1197                 if (cvs->cvs_buf == NULL) {
1198                         continue;
1199                 }
1200 
1201                 /* add to ID array */
1202                 usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf,
1203                     cvs->cvs_buf_len);
1204         }
1205         rval = USB_SUCCESS;
1206 
1207         usb_ac_setup_connections(uacp);
1208 
1209         /* determine port types */
1210         usb_ac_map_termtype_to_port(uacp, USB_AUDIO_PLAY);
1211         usb_ac_map_termtype_to_port(uacp, USB_AUDIO_RECORD);
1212 
1213 
1214         return (rval);
1215 }
1216 
1217 
1218 /*
1219  * usb_ac_setup_connections:
1220  *      build a matrix reflecting all connections
1221  */
1222 static void
1223 usb_ac_setup_connections(usb_ac_state_t *uacp)
1224 {
1225         usb_ac_unit_list_t      *units = uacp->usb_ac_units;
1226         uchar_t                 *a, **p, i, unit;
1227         size_t                  a_len, p_len;
1228 
1229         /* allocate array for unit types for quick reference */
1230         uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit,
1231             KM_SLEEP);
1232         /* allocate array for traversal path */
1233         uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit,
1234             KM_SLEEP);
1235 
1236 
1237         /* allocate the connection matrix and set it up */
1238         a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit;
1239         p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *);
1240 
1241         /* trick to create a 2 dimensional array */
1242         a = kmem_zalloc(a_len, KM_SLEEP);
1243         p = kmem_zalloc(p_len, KM_SLEEP);
1244         for (i = 0; i < uacp->usb_ac_max_unit; i++) {
1245                 p[i] = a + i * uacp->usb_ac_max_unit;
1246         }
1247         uacp->usb_ac_connections = p;
1248         uacp->usb_ac_connections_len = p_len;
1249         uacp->usb_ac_connections_a = a;
1250         uacp->usb_ac_connections_a_len = a_len;
1251 
1252         /* traverse all units and set connections */
1253         for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1254 
1255                 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1256                     "--------traversing unit=0x%x type=0x%x--------",
1257                     unit, units[unit].acu_type);
1258 
1259                 /* store type in the first unused column */
1260                 uacp->usb_ac_unit_type[unit] = units[unit].acu_type;
1261 
1262                 /* save the Unit ID in the unit it points to */
1263                 switch (units[unit].acu_type) {
1264                 case USB_AUDIO_FEATURE_UNIT:
1265                 {
1266                         usb_audio_feature_unit_descr1_t *d =
1267                             units[unit].acu_descriptor;
1268 
1269                         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1270                             "USB_AUDIO_FEATURE_UNIT:sourceID=0x%x type=0x%x",
1271                             d->bSourceID, units[d->bSourceID].acu_type);
1272 
1273                         if (d->bSourceID != 0) {
1274                                 ASSERT(p[unit][d->bSourceID] == B_FALSE);
1275                                 p[unit][d->bSourceID] = B_TRUE;
1276                         }
1277 
1278                         break;
1279                 }
1280                 case USB_AUDIO_OUTPUT_TERMINAL:
1281                 {
1282                         usb_audio_output_term_descr_t *d =
1283                             units[unit].acu_descriptor;
1284 
1285                         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1286                             "USB_AUDIO_OUTPUT_TERMINAL:sourceID=0x%x type=0x%x",
1287                             d->bSourceID, units[d->bSourceID].acu_type);
1288 
1289                         if (d->bSourceID != 0) {
1290                                 ASSERT(p[unit][d->bSourceID] == B_FALSE);
1291                                 p[unit][d->bSourceID] = B_TRUE;
1292                         }
1293 
1294                         break;
1295                 }
1296                 case USB_AUDIO_MIXER_UNIT:
1297                 {
1298                         usb_audio_mixer_unit_descr1_t *d =
1299                             units[unit].acu_descriptor;
1300                         int n_sourceID = d->bNrInPins;
1301                         int id;
1302 
1303                         for (id = 0; id < n_sourceID; id++) {
1304                                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1305                                     uacp->usb_ac_log_handle,
1306                                     "USB_AUDIO_MIXER_UNIT:sourceID=0x%x"
1307                                     "type=0x%x c=%d",
1308                                     d->baSourceID[id],
1309                                     units[d->baSourceID[id]].acu_type,
1310                                     p[unit][d->baSourceID[id]]);
1311 
1312                                 if (d->baSourceID[id] != 0) {
1313                                         ASSERT(p[unit][d->baSourceID[id]] ==
1314                                             B_FALSE);
1315                                         p[unit][d->baSourceID[id]] = B_TRUE;
1316                                 }
1317                         }
1318 
1319                         break;
1320                 }
1321                 case USB_AUDIO_SELECTOR_UNIT:
1322                 {
1323                         usb_audio_selector_unit_descr1_t *d =
1324                             units[unit].acu_descriptor;
1325                         int n_sourceID = d->bNrInPins;
1326                         int id;
1327 
1328                         for (id = 0; id < n_sourceID; id++) {
1329                                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1330                                     uacp->usb_ac_log_handle,
1331                                     "USB_AUDIO_SELECTOR_UNIT:sourceID=0x%x"
1332                                     " type=0x%x", d->baSourceID[id],
1333                                     units[d->baSourceID[id]].acu_type);
1334 
1335                                 if (d->baSourceID[id] != 0) {
1336                                         ASSERT(p[unit][d->baSourceID[id]] ==
1337                                             B_FALSE);
1338                                         p[unit][d->baSourceID[id]] = B_TRUE;
1339                                 }
1340                         }
1341 
1342                         break;
1343                 }
1344                 case USB_AUDIO_PROCESSING_UNIT:
1345                 {
1346                         usb_audio_mixer_unit_descr1_t *d =
1347                             units[unit].acu_descriptor;
1348                         int n_sourceID = d->bNrInPins;
1349                         int id;
1350 
1351                         for (id = 0; id < n_sourceID; id++) {
1352                                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1353                                     uacp->usb_ac_log_handle,
1354                                     "USB_AUDIO_PROCESSING_UNIT:sourceID=0x%x"
1355                                     " type=0x%x", d->baSourceID[id],
1356                                     units[d->baSourceID[id]].acu_type);
1357 
1358                                 if (d->baSourceID[id] != 0) {
1359                                         ASSERT(p[unit][d->baSourceID[id]] ==
1360                                             B_FALSE);
1361                                         p[unit][d->baSourceID[id]] = B_TRUE;
1362                                 }
1363                         }
1364 
1365                         break;
1366                 }
1367                 case USB_AUDIO_EXTENSION_UNIT:
1368                 {
1369                         usb_audio_extension_unit_descr1_t *d =
1370                             units[unit].acu_descriptor;
1371                         int n_sourceID = d->bNrInPins;
1372                         int id;
1373 
1374                         for (id = 0; id < n_sourceID; id++) {
1375                                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1376                                     uacp->usb_ac_log_handle,
1377                                     "USB_AUDIO_EXTENSION_UNIT:sourceID=0x%x"
1378                                     "type=0x%x", d->baSourceID[id],
1379                                     units[d->baSourceID[id]].acu_type);
1380 
1381                                 if (d->baSourceID[id] != 0) {
1382                                         ASSERT(p[unit][d->baSourceID[id]] ==
1383                                             B_TRUE);
1384                                         p[unit][d->baSourceID[id]] = B_FALSE;
1385                                 }
1386                         }
1387 
1388                         break;
1389                 }
1390                 case USB_AUDIO_INPUT_TERMINAL:
1391 
1392                         break;
1393                 default:
1394                         /*
1395                          * Ignore the rest because they are not support yet
1396                          */
1397                         break;
1398                 }
1399         }
1400 
1401 #ifdef DEBUG
1402         /* display topology in log buffer */
1403 {
1404         uint_t i, j, l;
1405         char *buf;
1406 
1407         l = uacp->usb_ac_max_unit * 5;
1408 
1409         buf = kmem_alloc(l, KM_SLEEP);
1410 
1411         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1412             "unit types:");
1413 
1414         /* two  strings so they won't be replaced accidentily by tab */
1415         (void) sprintf(&buf[0], "    ""    ");
1416         for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1417                 (void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1418         }
1419         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1420 
1421         (void) sprintf(&buf[0], "  +-------");
1422         for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1423                 (void) sprintf(&buf[5+((i-1)*3)], "---");
1424         }
1425         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1426 
1427         (void) sprintf(&buf[0], "    ""    ");
1428         for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1429                 (void) sprintf(&buf[2 + (i*3)], "%02d ",
1430                     uacp->usb_ac_unit_type[i]);
1431         }
1432         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1433         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " ");
1434 
1435         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1436             "adjacency matrix:");
1437         (void) sprintf(&buf[0], "    ""    ");
1438         for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1439                 (void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1440         }
1441         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1442 
1443         (void) sprintf(&buf[0], "  +-------");
1444         for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1445                 (void) sprintf(&buf[5+((i-1)*3)], "---");
1446         }
1447         USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1448 
1449         for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1450                 (void) sprintf(&buf[0], "%02d| "" ", i);
1451                 for (j = 1; j < uacp->usb_ac_max_unit; j++) {
1452                         (void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]);
1453                 }
1454                 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1455         }
1456         kmem_free(buf, l);
1457 }
1458 #endif
1459 }
1460 
1461 
1462 /*
1463  * usb_ac_add_unit_descriptor:
1464  *      take the parsed descriptor in the buffer and store it in the ID unit
1465  *      array. we grow the unit array if the ID exceeds the current max
1466  */
1467 static void
1468 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
1469         size_t buflen)
1470 {
1471         void    *descr;
1472         int     len;
1473         char    *format;
1474         size_t  size;
1475 
1476 
1477         /* doubling the length should allow for padding */
1478         len = 2 * buffer[0];
1479         descr = kmem_zalloc(len, KM_SLEEP);
1480 
1481         switch (buffer[2]) {
1482         case USB_AUDIO_INPUT_TERMINAL:
1483                 format = CS_AC_INPUT_TERM_FORMAT;
1484                 size = CS_AC_INPUT_TERM_SIZE;
1485 
1486                 break;
1487         case USB_AUDIO_OUTPUT_TERMINAL:
1488                 format = CS_AC_OUTPUT_TERM_FORMAT;
1489                 size = CS_AC_OUTPUT_TERM_SIZE;
1490 
1491                 break;
1492         case USB_AUDIO_MIXER_UNIT:
1493                 format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c";
1494                 size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1;
1495 
1496                 break;
1497         case USB_AUDIO_SELECTOR_UNIT:
1498                 format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c";
1499                 size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1;
1500 
1501                 break;
1502         case USB_AUDIO_FEATURE_UNIT:
1503                 format = CS_AC_FEATURE_UNIT_FORMAT "255c";
1504                 size = CS_AC_FEATURE_UNIT_SIZE;
1505 
1506                 break;
1507         case USB_AUDIO_PROCESSING_UNIT:
1508                 format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c";
1509                 size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1;
1510 
1511                 break;
1512         case USB_AUDIO_EXTENSION_UNIT:
1513                 format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c";
1514                 size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1;
1515 
1516                 break;
1517         default:
1518                 USB_DPRINTF_L2(PRINT_MASK_ATTA,
1519                     uacp->usb_ac_log_handle,
1520                     "unsupported descriptor %d", buffer[2]);
1521 
1522                 /* ignore this descriptor */
1523                 kmem_free(descr, len);
1524 
1525                 return;
1526         }
1527 
1528         if (usb_parse_data(format, buffer, buflen, descr, len) < size) {
1529                 /* ignore this descriptor */
1530                 kmem_free(descr, len);
1531 
1532                 return;
1533         }
1534 
1535         switch (buffer[2]) {
1536         case USB_AUDIO_INPUT_TERMINAL:
1537         {
1538                 usb_audio_input_term_descr_t *d =
1539                     (usb_audio_input_term_descr_t *)descr;
1540 
1541                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1542                     uacp->usb_ac_log_handle,
1543                     "usb_ac_units[%d] ---input term: type=0x%x sub=0x%x"
1544                     "termid=0x%x\n\t"
1545                     "termtype=0x%x assoc=0x%x #ch=%d "
1546                     "chconf=0x%x ich=0x%x iterm=0x%x",
1547                     d->bTerminalID,
1548                     d->bDescriptorType, d->bDescriptorSubType,
1549                     d->bTerminalID, d->wTerminalType,
1550                     d->bAssocTerminal, d->bNrChannels,
1551                     d->wChannelConfig, d->iChannelNames,
1552                     d->iTerminal);
1553 
1554                 usb_ac_alloc_unit(uacp, d->bTerminalID);
1555                 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1556                 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1557                 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1558 
1559                 break;
1560         }
1561         case USB_AUDIO_OUTPUT_TERMINAL:
1562         {
1563                 usb_audio_output_term_descr_t *d =
1564                     (usb_audio_output_term_descr_t *)descr;
1565 
1566                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1567                     uacp->usb_ac_log_handle,
1568                     "usb_ac_units[%d] ---output term: type=0x%x sub=0x%x"
1569                     " termid=0x%x\n\t"
1570                     "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
1571                     d->bTerminalID,
1572                     d->bDescriptorType, d->bDescriptorSubType,
1573                     d->bTerminalID, d->wTerminalType,
1574                     d->bAssocTerminal, d->bSourceID,
1575                     d->iTerminal);
1576 
1577                 usb_ac_alloc_unit(uacp, d->bTerminalID);
1578                 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1579                 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1580                 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1581 
1582                 break;
1583         }
1584         case USB_AUDIO_MIXER_UNIT:
1585         {
1586                 usb_audio_mixer_unit_descr1_t *d =
1587                     (usb_audio_mixer_unit_descr1_t *)descr;
1588 
1589                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1590                     uacp->usb_ac_log_handle,
1591                     "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1592                     " unitid=0x%x\n\t"
1593                     "#pins=0x%x sourceid[0]=0x%x",
1594                     d->bUnitID,
1595                     d->bDescriptorType, d->bDescriptorSubType,
1596                     d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1597                 usb_ac_alloc_unit(uacp, d->bUnitID);
1598                 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1599                 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1600                 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1601 
1602                 break;
1603         }
1604         case USB_AUDIO_SELECTOR_UNIT:
1605         {
1606                 usb_audio_selector_unit_descr1_t *d =
1607                     (usb_audio_selector_unit_descr1_t *)descr;
1608 
1609                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1610                     uacp->usb_ac_log_handle,
1611                     "usb_ac_units[%d] ---selector unit: type=0x%x sub=0x%x"
1612                     " unitid=0x%x\n\t"
1613                     "#pins=0x%x sourceid[0]=0x%x",
1614                     d->bUnitID,
1615                     d->bDescriptorType, d->bDescriptorSubType,
1616                     d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1617                 usb_ac_alloc_unit(uacp, d->bUnitID);
1618                 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1619                 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1620                 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1621 
1622                 break;
1623         }
1624         case USB_AUDIO_FEATURE_UNIT:
1625         {
1626                 usb_audio_feature_unit_descr1_t *d =
1627                     (usb_audio_feature_unit_descr1_t *)descr;
1628 
1629                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1630                     uacp->usb_ac_log_handle,
1631                     "usb_ac_units[%d] ---feature unit: type=0x%x sub=0x%x"
1632                     " unitid=0x%x\n\t"
1633                     "sourceid=0x%x size=0x%x",
1634                     d->bUnitID,
1635                     d->bDescriptorType, d->bDescriptorSubType,
1636                     d->bUnitID, d->bSourceID, d->bControlSize);
1637 
1638                 usb_ac_alloc_unit(uacp, d->bUnitID);
1639                 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1640                 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1641                 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1642 
1643                 break;
1644         }
1645         case USB_AUDIO_PROCESSING_UNIT:
1646         {
1647                 usb_audio_processing_unit_descr1_t *d =
1648                     (usb_audio_processing_unit_descr1_t *)descr;
1649 
1650                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1651                     uacp->usb_ac_log_handle,
1652                     "usb_ac_units[%d] ---processing unit: type=0x%x sub=0x%x"
1653                     " unitid=0x%x\n\t"
1654                     "#pins=0x%x sourceid[0]=0x%x",
1655                     d->bUnitID,
1656                     d->bDescriptorType, d->bDescriptorSubType,
1657                     d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1658                 usb_ac_alloc_unit(uacp, d->bUnitID);
1659                 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1660                 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1661                 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1662 
1663                 break;
1664         }
1665         case USB_AUDIO_EXTENSION_UNIT:
1666         {
1667                 usb_audio_extension_unit_descr1_t *d =
1668                     (usb_audio_extension_unit_descr1_t *)descr;
1669 
1670                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1671                     uacp->usb_ac_log_handle,
1672                     "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1673                     " unitid=0x%x\n\t"
1674                     "#pins=0x%x sourceid[0]=0x%x",
1675                     d->bUnitID,
1676                     d->bDescriptorType, d->bDescriptorSubType,
1677                     d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1678                 usb_ac_alloc_unit(uacp, d->bUnitID);
1679                 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1680                 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1681                 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1682 
1683                 break;
1684         }
1685         default:
1686                 break;
1687         }
1688 }
1689 
1690 
1691 /*
1692  * usb_ac_alloc_unit:
1693  *      check if the unit ID is less than max_unit in which case no
1694  *      extra entries are needed. If more entries are needed, copy over
1695  *      the existing array into a new larger array
1696  */
1697 static void
1698 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
1699 {
1700         usb_ac_unit_list_t *old = NULL;
1701         uint_t  max_unit;
1702 
1703 
1704         if (uacp->usb_ac_units) {
1705                 if (unit < uacp->usb_ac_max_unit) {
1706                         /* existing array is big enough */
1707 
1708                         return;
1709                 }
1710                 old = uacp->usb_ac_units;
1711                 max_unit = uacp->usb_ac_max_unit;
1712         }
1713 
1714         /* allocate two extra ones */
1715         unit += 2;
1716         uacp->usb_ac_max_unit = unit;
1717         uacp->usb_ac_units = kmem_zalloc(unit *
1718             sizeof (usb_ac_unit_list_t), KM_SLEEP);
1719 
1720         if (old) {
1721                 size_t len = max_unit * sizeof (usb_ac_unit_list_t);
1722                 bcopy(old, uacp->usb_ac_units, len);
1723 
1724                 kmem_free(old, len);
1725         }
1726 }
1727 
1728 
1729 /*
1730  * usb_ac_free_all_units:
1731  *      free the entire unit list
1732  */
1733 static void
1734 usb_ac_free_all_units(usb_ac_state_t *uacp)
1735 {
1736         uint_t  unit;
1737         usb_ac_unit_list_t *unitp;
1738 
1739         if (uacp->usb_ac_units == NULL) {
1740 
1741                 return;
1742         }
1743 
1744 
1745         for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1746                 unitp = &uacp->usb_ac_units[unit];
1747                 if (unitp) {
1748                         if (unitp->acu_descriptor) {
1749                                 kmem_free(unitp->acu_descriptor,
1750                                     unitp->acu_descr_length);
1751                         }
1752                 }
1753         }
1754 
1755         kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit *
1756             sizeof (usb_ac_unit_list_t));
1757 }
1758 
1759 
1760 /*
1761  * usb_ac_lookup_port_type:
1762  *      map term type to port type
1763  *      default just return LINE_IN + LINE_OUT
1764  */
1765 static int
1766 usb_ac_lookup_port_type(ushort_t termtype)
1767 {
1768         uint_t i;
1769 
1770         /*
1771          * Looking for a input/ouput terminal type to match the port
1772          * type, it should not be common streaming type
1773          */
1774         ASSERT(termtype != USB_AUDIO_TERM_TYPE_STREAMING);
1775 
1776         for (i = 0; ; i++) {
1777                 if (usb_ac_term_type_map[i].term_type == 0) {
1778 
1779                         break;
1780                 }
1781 
1782                 if (usb_ac_term_type_map[i].term_type == termtype) {
1783 
1784                         return (usb_ac_term_type_map[i].port_type);
1785                 }
1786         }
1787 
1788         return (USB_PORT_UNKNOWN);
1789 }
1790 
1791 
1792 /*
1793  * usb_ac_update_port:
1794  *      called for each terminal
1795  */
1796 /*ARGSUSED*/
1797 static int
1798 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
1799     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1800 {
1801         if (dir & USB_AUDIO_PLAY) {
1802                 usb_audio_output_term_descr_t *d =
1803                     (usb_audio_output_term_descr_t *)
1804                     uacp->usb_ac_units[id].acu_descriptor;
1805                 uint_t port_type =
1806                     usb_ac_lookup_port_type(d->wTerminalType);
1807 
1808                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1809                     "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
1810                     dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1811 
1812                 uacp->usb_ac_output_ports |= (1U << port_type);
1813         } else {
1814                 usb_audio_input_term_descr_t *d =
1815                     (usb_audio_input_term_descr_t *)
1816                     uacp->usb_ac_units[id].acu_descriptor;
1817                 uint_t port_type =
1818                     usb_ac_lookup_port_type(d->wTerminalType);
1819 
1820                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1821                     "usb_ac_update_port: dir=%d wTerminalType=0x%x,  name=%s",
1822                     dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1823 
1824                 uacp->usb_ac_input_ports |= (1U << port_type);
1825 
1826         }
1827 
1828         return (USB_SUCCESS);
1829 }
1830 
1831 
1832 /*
1833  * usb_ac_map_termtype_to_port:
1834  *      starting from a streaming termtype find all
1835  *      input or output terminals and OR into uacp->usb_ac_input_ports
1836  *      or uacp->usb_ac_output_ports;
1837  */
1838 static void
1839 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
1840 {
1841         uint_t count = 0;
1842         uint_t depth = 0;
1843         uint_t search_type = (dir & USB_AUDIO_PLAY) ?
1844             USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
1845 
1846 
1847         (void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
1848             0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
1849 
1850         ASSERT(depth == 0);
1851 }
1852 
1853 
1854 /*
1855  * usb_ac_set_port:
1856  *      find a selector port (record side only) and set the
1857  *      input to the matching pin
1858  */
1859 static uint_t
1860 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
1861 {
1862         uint_t count = 0;
1863         uint_t id;
1864         uint_t depth = 0;
1865 
1866 
1867         /* we only support the selector for the record side */
1868         if (dir & USB_AUDIO_RECORD) {
1869                 id = usb_ac_traverse_all_units(uacp, dir,
1870                     USB_AUDIO_SELECTOR_UNIT, 0,
1871                     0, USB_AC_FIND_ONE, &count, port, &depth,
1872                     usb_ac_set_selector);
1873 
1874                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1875                     "usb_ac_set_port: id=%d count=%d port=%d",
1876                     id, count, port);
1877 
1878                 ASSERT(depth == 0);
1879         }
1880 
1881         return (USB_SUCCESS);
1882 }
1883 
1884 
1885 /*
1886  * usb_ac_match_port:
1887  *      given the requested port type, find a correspondig term type
1888  *      Called from usb_ac_traverse_all_units()
1889  */
1890 /*ARGSUSED*/
1891 static int
1892 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
1893     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1894 {
1895         uint_t port_type;
1896 
1897 
1898         if (dir & USB_AUDIO_PLAY) {
1899                 usb_audio_output_term_descr_t *d =
1900                     (usb_audio_output_term_descr_t *)
1901                     uacp->usb_ac_units[id].acu_descriptor;
1902                 port_type = usb_ac_lookup_port_type(d->wTerminalType);
1903 
1904                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1905                     "usb_ac_match_port: "
1906                     "dir=%d type=0x%x port_type=%d port=%d",
1907                     dir, d->wTerminalType, port_type, arg1);
1908         } else {
1909                 usb_audio_output_term_descr_t *d =
1910                     (usb_audio_output_term_descr_t *)
1911                     uacp->usb_ac_units[id].acu_descriptor;
1912                 port_type = usb_ac_lookup_port_type(d->wTerminalType);
1913 
1914                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1915                     "usb_ac_match_port: "
1916                     "dir=%d type=0x%x port_type=%d port=%d",
1917                     dir, d->wTerminalType, port_type, arg1);
1918         }
1919 
1920         return (((1U << port_type) & arg1) ? USB_SUCCESS : USB_FAILURE);
1921 }
1922 
1923 
1924 /*
1925  * usb_ac_set_selector:
1926  *      Called from usb_ac_traverse_all_units()
1927  *      Find the correct pin and set selector to this pin
1928  */
1929 /*ARGSUSED*/
1930 static int
1931 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
1932     uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1933 {
1934         uint_t count = 0;
1935         uint_t unit = USB_AC_ID_NONE;
1936         uint_t pin;
1937         uint_t search_target =
1938             (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
1939             USB_AUDIO_INPUT_TERMINAL;
1940         usb_audio_selector_unit_descr1_t *d =
1941             (usb_audio_selector_unit_descr1_t *)
1942             uacp->usb_ac_units[id].acu_descriptor;
1943         int n_sourceID = d->bNrInPins;
1944         int rval = USB_FAILURE;
1945 
1946 
1947         /*
1948          * for each pin, find a term type that matches the
1949          * requested port type
1950          */
1951         for (pin = 0; pin < n_sourceID; pin++) {
1952                 if (d->baSourceID[pin] == 0) {
1953 
1954                         break;
1955                 }
1956                 unit = d->baSourceID[pin];
1957 
1958                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1959                     "usb_ac_set_selector: pin=%d unit=%d", pin, unit);
1960 
1961                 if (uacp->usb_ac_unit_type[unit] == search_target) {
1962                         if (usb_ac_match_port(uacp, unit, dir, channel,
1963                             control, arg1, depth) == USB_SUCCESS) {
1964 
1965                                 break;
1966                         } else {
1967                                 unit = USB_AC_ID_NONE;
1968 
1969                                 continue;
1970                         }
1971                 }
1972 
1973                 /* find units connected to this unit */
1974                 unit = usb_ac_traverse_connections(uacp, unit,
1975                     dir, search_target, channel, control,
1976                     USB_AC_FIND_ONE, &count, arg1, depth,
1977                     usb_ac_match_port);
1978 
1979                 if (unit != USB_AC_ID_NONE) {
1980 
1981                         break;
1982                 }
1983         }
1984 
1985 
1986         if (unit != USB_AC_ID_NONE) {
1987                 mblk_t          *data;
1988                 usb_cr_t        cr;
1989                 usb_cb_flags_t  cb_flags;
1990 
1991                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1992                     "usb_ac_set_selector: found id=%d at pin %d", unit, pin);
1993 
1994                 mutex_exit(&uacp->usb_ac_mutex);
1995 
1996                 data = allocb(1, BPRI_HI);
1997                 if (!data) {
1998                         USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1999                             "usb_ac_set_selector: allocate data failed");
2000                         mutex_enter(&uacp->usb_ac_mutex);
2001 
2002                         return (USB_FAILURE);
2003                 }
2004 
2005                 /* pins are 1-based */
2006                 *(data->b_rptr) = (char)++pin;
2007 
2008                 if (usb_pipe_sync_ctrl_xfer(
2009                     uacp->usb_ac_dip,
2010                     uacp->usb_ac_default_ph,
2011                     USB_DEV_REQ_HOST_TO_DEV |
2012                     USB_DEV_REQ_TYPE_CLASS |
2013                     USB_DEV_REQ_RCPT_IF,        /* bmRequestType */
2014                     USB_AUDIO_SET_CUR,          /* bRequest */
2015                     0,                          /* wValue */
2016                                                 /* feature unit and id */
2017                     (id << 8)| uacp->usb_ac_ifno, /* wIndex */
2018                     1,                          /* wLength */
2019                     &data,
2020                     USB_ATTRS_NONE,
2021                     &cr, &cb_flags,
2022                     USB_FLAGS_SLEEP) == USB_SUCCESS) {
2023                         USB_DPRINTF_L3(PRINT_MASK_ALL,
2024                             uacp->usb_ac_log_handle,
2025                             "set current selection: %d", *data->b_rptr);
2026 
2027                         rval = USB_SUCCESS;
2028                 } else {
2029                         USB_DPRINTF_L2(PRINT_MASK_ALL,
2030                             uacp->usb_ac_log_handle,
2031                             "set current pin selection failed");
2032                 }
2033                 freemsg(data);
2034 
2035                 mutex_enter(&uacp->usb_ac_mutex);
2036         } else {
2037                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2038                     "usb_ac_set_selector: nothing found");
2039         }
2040 
2041         return (rval);
2042 }
2043 
2044 
2045 /*
2046  * usb_ac_set_control:
2047  *      apply func to all units of search_target type for both the
2048  *      requested channel and master channel
2049  */
2050 static uint_t
2051 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
2052         uint_t channel, uint_t control, uint_t all_or_one,
2053         uint_t *count, uint_t arg1,
2054         int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2055                 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2056 {
2057         uint_t id;
2058         uint_t depth = 0;
2059 
2060         id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
2061             control, all_or_one, count, arg1, &depth, func);
2062 
2063         if ((channel != 0) &&
2064             (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) ||
2065             (all_or_one == USB_AC_FIND_ALL)))  {
2066                 /* try master channel */
2067                 channel = 0;
2068                 id = usb_ac_traverse_all_units(uacp, dir, search_target,
2069                     channel, control, all_or_one, count, arg1,
2070                     &depth, func);
2071         }
2072 
2073         ASSERT(depth == 0);
2074 
2075         return (id);
2076 }
2077 
2078 
2079 /*
2080  * usb_ac_traverse_all_units:
2081  *      traverse all units starting with all IT or OT depending on direction.
2082  *      If no unit is found for the particular channel, try master channel
2083  *      If a matching unit is found, apply the function passed by
2084  *      the caller
2085  */
2086 static uint_t
2087 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
2088         uint_t search_target, uint_t channel, uint_t control,
2089         uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2090         int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2091                 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2092 {
2093         uint_t unit, start_type, id;
2094 
2095         start_type = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
2096             USB_AUDIO_OUTPUT_TERMINAL;
2097 
2098         /* keep track of recursion */
2099         if ((*depth)++ > USB_AC_MAX_DEPTH) {
2100                 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2101                     "Unit topology too complex, giving up");
2102 
2103                 return (USB_AC_ID_NONE);
2104         }
2105 
2106         for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2107                 /* is this an IT or OT? */
2108                 if (uacp->usb_ac_unit_type[unit] != start_type) {
2109 
2110                         continue;
2111                 }
2112 
2113                 /* start at streaming term types */
2114                 if (dir & USB_AUDIO_PLAY) {
2115                         usb_audio_input_term_descr_t *d =
2116                             uacp->usb_ac_units[unit].acu_descriptor;
2117                         if (d->wTerminalType !=
2118                             USB_AUDIO_TERM_TYPE_STREAMING) {
2119 
2120                                 continue;
2121                         }
2122                 } else {
2123                         usb_audio_output_term_descr_t *d =
2124                             uacp->usb_ac_units[unit].acu_descriptor;
2125                         if (d->wTerminalType !=
2126                             USB_AUDIO_TERM_TYPE_STREAMING) {
2127 
2128                                 continue;
2129                         }
2130                 }
2131 
2132                 /* find units connected to this unit */
2133                 id = usb_ac_traverse_connections(uacp, unit, dir,
2134                     search_target, channel, control, all_or_one, count,
2135                     arg1, depth, func);
2136 
2137                 if ((all_or_one == USB_AC_FIND_ONE) &&
2138                     (id != USB_AC_ID_NONE)) {
2139                         unit = id;
2140 
2141                         break;
2142                 }
2143         }
2144 
2145         (*depth)--;
2146 
2147         return  ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2148 }
2149 
2150 
2151 /*
2152  * usb_ac_set_monitor_gain_control:
2153  *      search for a feature unit between output terminal (OT) and
2154  *      input terminal. We are looking for a path between
2155  *      for example a microphone and a speaker through a feature unit
2156  *      and mixer
2157  */
2158 static uint_t
2159 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
2160         uint_t search_target, uint_t channel, uint_t control,
2161         uint_t all_or_one, uint_t *count, uint_t arg1,
2162         int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2163                 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2164 {
2165         uint_t unit, id;
2166         uint_t depth = 0;
2167 
2168 
2169         for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2170                 usb_audio_output_term_descr_t *d =
2171                     uacp->usb_ac_units[unit].acu_descriptor;
2172 
2173                 /* is this an OT and not stream type? */
2174                 if ((uacp->usb_ac_unit_type[unit] ==
2175                     USB_AUDIO_OUTPUT_TERMINAL) &&
2176                     (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) {
2177 
2178                         /* find units connected to this unit */
2179                         id = usb_ac_traverse_connections(uacp, unit, dir,
2180                             search_target, channel, control, all_or_one, count,
2181                             arg1, &depth, func);
2182 
2183                         if ((all_or_one == USB_AC_FIND_ONE) &&
2184                             (id != USB_AC_ID_NONE)) {
2185 
2186                                 break;
2187                         }
2188                 }
2189         }
2190 
2191         ASSERT(depth == 0);
2192 
2193         return (id);
2194 }
2195 
2196 
2197 /*
2198  * usb_ac_push/pop_unit
2199  *      add/remove unit ID to the traverse path
2200  */
2201 static void
2202 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
2203 {
2204         uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] =
2205             (uchar_t)unit;
2206         ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
2207 }
2208 
2209 
2210 /* ARGSUSED */
2211 static void
2212 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
2213 {
2214         uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
2215 }
2216 
2217 
2218 /*
2219  * usb_ac_show_traverse_path:
2220  *      display entire path, just for debugging
2221  */
2222 static void
2223 usb_ac_show_traverse_path(usb_ac_state_t *uacp)
2224 {
2225         int i;
2226 
2227         for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2228                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2229                     "traverse path %d: unit=%d type=%d",
2230                     i, uacp->usb_ac_traverse_path[i],
2231                     uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]);
2232         }
2233 }
2234 
2235 
2236 /*
2237  * usb_ac_check_path:
2238  *      check for a specified type in the traverse path
2239  */
2240 static int
2241 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type)
2242 {
2243         int i;
2244 
2245         for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2246                 uint_t unit = uacp->usb_ac_traverse_path[i];
2247 
2248                 if (uacp->usb_ac_unit_type[unit] == type) {
2249 
2250                         return (USB_SUCCESS);
2251                 }
2252         }
2253 
2254         return (USB_FAILURE);
2255 }
2256 
2257 
2258 /*
2259  * usb_ac_traverse_connections:
2260  *      traverse all units and for each unit with the right type, call
2261  *      func. If the func returns a success and search == USB_AC_FIND_ONE,
2262  *      we are done. If all is set then we continue until we terminate
2263  *      and input or output terminal.
2264  *      For audio play, we traverse columns starting from an input terminal
2265  *      to an output terminal while for record we traverse rows from output
2266  *      terminal to input terminal.
2267  */
2268 static uint_t
2269 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
2270         uint_t search_target, uint_t channel, uint_t control,
2271         uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2272         int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2273                 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2274 {
2275         uint_t unit, id;
2276         uint_t done = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2277             USB_AUDIO_INPUT_TERMINAL;
2278 
2279 
2280         /* keep track of recursion depth */
2281         if ((*depth)++ > USB_AC_MAX_DEPTH) {
2282                 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2283                     "Unit topology too complex, giving up");
2284 
2285                 return (USB_AC_ID_NONE);
2286         }
2287 
2288         usb_ac_push_unit_id(uacp, start_unit);
2289 
2290         for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2291                 uint_t entry = (dir & USB_AUDIO_PLAY) ?
2292                     uacp->usb_ac_connections[unit][start_unit] :
2293                     uacp->usb_ac_connections[start_unit][unit];
2294 
2295                 if (entry) {
2296                         USB_DPRINTF_L3(PRINT_MASK_ALL,
2297                             uacp->usb_ac_log_handle,
2298                             "start=%d unit=%d entry=%d type=%d "
2299                             "done=%d found=%d",
2300                             start_unit, unit, entry, search_target, done,
2301                             uacp->usb_ac_unit_type[unit]);
2302 
2303                         /* did we find a matching type? */
2304                         if (uacp->usb_ac_unit_type[unit] == search_target) {
2305                                 USB_DPRINTF_L3(PRINT_MASK_ALL,
2306                                     uacp->usb_ac_log_handle,
2307                                     "match: dir=%d unit=%d type=%d",
2308                                     dir, unit, search_target);
2309 
2310                                 /* yes, no apply function to this unit */
2311                                 if (func(uacp, unit, dir, channel,
2312                                     control, arg1, depth) == USB_SUCCESS) {
2313                                         (*count)++;
2314 
2315                                         USB_DPRINTF_L3(PRINT_MASK_ALL,
2316                                             uacp->usb_ac_log_handle,
2317                                             "func returned success, "
2318                                             "unit=%d all=%d", unit,
2319                                             all_or_one);
2320 
2321                                         /* are we done? */
2322                                         if (all_or_one == USB_AC_FIND_ONE) {
2323 
2324                                                 break;
2325                                         }
2326                                 }
2327                         }
2328 
2329                         /* did we find the terminating unit */
2330                         if (uacp->usb_ac_unit_type[unit] == done) {
2331 
2332                                 continue;
2333                         }
2334                         id = usb_ac_traverse_connections(uacp, unit, dir,
2335                             search_target, channel, control,
2336                             all_or_one, count, arg1, depth, func);
2337                         if ((id != USB_AC_ID_NONE) &&
2338                             (all_or_one == USB_AC_FIND_ONE)) {
2339                                 unit = id;
2340 
2341                                 break;
2342                         }
2343                 }
2344         }
2345 
2346         (*depth)--;
2347         usb_ac_pop_unit_id(uacp, start_unit);
2348 
2349         return  ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2350 }
2351 
2352 
2353 /*
2354  * Event Management
2355  *
2356  * usb_ac_disconnect_event_cb:
2357  *      The device has been disconnected. we either wait for
2358  *      detach or a reconnect event.
2359  */
2360 static int
2361 usb_ac_disconnect_event_cb(dev_info_t *dip)
2362 {
2363         usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2364             usb_ac_statep, ddi_get_instance(dip));
2365 
2366         USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2367             "usb_ac_disconnect_event_cb:start");
2368 
2369         usb_ac_serialize_access(uacp);
2370         mutex_enter(&uacp->usb_ac_mutex);
2371 
2372         /* setting to disconnect state will prevent replumbing */
2373         uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2374 
2375         if (uacp->usb_ac_busy_count) {
2376                 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2377                     "device was disconnected while busy. "
2378                     "Data may have been lost");
2379         }
2380         mutex_exit(&uacp->usb_ac_mutex);
2381 
2382         usb_ac_release_access(uacp);
2383         USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2384             "usb_ac_disconnect_event_cb:done");
2385 
2386 
2387         return (USB_SUCCESS);
2388 }
2389 
2390 
2391 /*
2392  * usb_ac_cpr_suspend:
2393  */
2394 static int
2395 usb_ac_cpr_suspend(dev_info_t *dip)
2396 {
2397         usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2398             usb_ac_statep, ddi_get_instance(dip));
2399 
2400         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2401             "usb_ac_cpr_suspend: Begin");
2402 
2403         mutex_enter(&uacp->usb_ac_mutex);
2404         uacp->usb_ac_dev_state = USB_DEV_SUSPENDED;
2405         mutex_exit(&uacp->usb_ac_mutex);
2406 
2407         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2408             "usb_ac_cpr_suspend: End");
2409 
2410         return (USB_SUCCESS);
2411 }
2412 
2413 
2414 
2415 /*
2416  * usb_ac_reconnect_event_cb:
2417  *      The device was disconnected but this instance not detached, probably
2418  *      because the device was busy.
2419  *      if the same device, continue with restoring state
2420  *      We should either be in the unplumbed state or the plumbed open
2421  *      state.
2422  */
2423 static int
2424 usb_ac_reconnect_event_cb(dev_info_t *dip)
2425 {
2426         usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2427             usb_ac_statep, ddi_get_instance(dip));
2428 
2429         USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2430             "usb_ac_reconnect_event_cb:begain");
2431 
2432         mutex_enter(&uacp->usb_ac_mutex);
2433         mutex_exit(&uacp->usb_ac_mutex);
2434 
2435         usb_ac_serialize_access(uacp);
2436 
2437         /* check the plumbing state */
2438         mutex_enter(&uacp->usb_ac_mutex);
2439         uacp->usb_ac_busy_count++;
2440         if (uacp->usb_ac_plumbing_state ==
2441             USB_AC_STATE_PLUMBED) {
2442                 mutex_exit(&uacp->usb_ac_mutex);
2443                 usb_ac_restore_device_state(dip, uacp);
2444                 mutex_enter(&uacp->usb_ac_mutex);
2445         }
2446         uacp->usb_ac_busy_count--;
2447 
2448         if (uacp->usb_ac_busy_count) {
2449                 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2450                     "busy device has been reconnected");
2451         }
2452 
2453         mutex_exit(&uacp->usb_ac_mutex);
2454 
2455         usb_ac_release_access(uacp);
2456         USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2457             "usb_ac_reconnect_event_cb:done");
2458 
2459         return (USB_SUCCESS);
2460 }
2461 
2462 
2463 /*
2464  * usb_ac_cpr_resume:
2465  *      Restore device state
2466  */
2467 static void
2468 usb_ac_cpr_resume(dev_info_t *dip)
2469 {
2470         usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2471             usb_ac_statep, ddi_get_instance(dip));
2472 
2473         USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2474             "usb_ac_cpr_resume");
2475 
2476         usb_ac_serialize_access(uacp);
2477 
2478         usb_ac_restore_device_state(dip, uacp);
2479 
2480         usb_ac_release_access(uacp);
2481 }
2482 
2483 
2484 /*
2485  * usb_ac_restore_device_state:
2486  *      Set original configuration of the device
2487  *      enable wrq - this starts new transactions on the control pipe
2488  */
2489 static void
2490 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp)
2491 {
2492         usb_ac_power_t  *uacpm;
2493         int     rval;
2494 
2495         USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2496             "usb_ac_restore_device_state:");
2497 
2498         usb_ac_pm_busy_component(uacp);
2499         (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2500 
2501         /* Check if we are talking to the same device */
2502         if (usb_check_same_device(dip, uacp->usb_ac_log_handle,
2503             USB_LOG_L0, PRINT_MASK_ALL,
2504             USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
2505                 usb_ac_pm_idle_component(uacp);
2506 
2507                 /* change the device state from suspended to disconnected */
2508                 mutex_enter(&uacp->usb_ac_mutex);
2509                 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2510                 mutex_exit(&uacp->usb_ac_mutex);
2511 
2512                 return;
2513         }
2514 
2515         mutex_enter(&uacp->usb_ac_mutex);
2516         uacpm = uacp->usb_ac_pm;
2517         if (uacpm) {
2518                 if (uacpm->acpm_wakeup_enabled) {
2519                         mutex_exit(&uacp->usb_ac_mutex);
2520 
2521                         if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip,
2522                             USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
2523 
2524                                 USB_DPRINTF_L4(PRINT_MASK_ATTA,
2525                                     uacp->usb_ac_log_handle,
2526                                     "usb_ac_restore_device_state: "
2527                                     "remote wakeup "
2528                                     "enable failed, rval=%d", rval);
2529                         }
2530 
2531                         mutex_enter(&uacp->usb_ac_mutex);
2532                 }
2533         }
2534 
2535         /* prevent unplumbing */
2536         uacp->usb_ac_busy_count++;
2537         uacp->usb_ac_dev_state = USB_DEV_ONLINE;
2538         if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) {
2539                 (void) usb_ac_restore_audio_state(uacp, 0);
2540         }
2541         uacp->usb_ac_busy_count--;
2542         mutex_exit(&uacp->usb_ac_mutex);
2543         usb_ac_pm_idle_component(uacp);
2544 }
2545 
2546 
2547 /*
2548  * usb_ac_am_restore_state
2549  */
2550 static void
2551 usb_ac_am_restore_state(void *arg)
2552 {
2553         usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
2554 
2555         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2556             "usb_ac_am_restore_state: Begin");
2557 
2558         usb_ac_serialize_access(uacp);
2559 
2560         mutex_enter(&uacp->usb_ac_mutex);
2561 
2562         if (uacp->usb_ac_plumbing_state ==
2563             USB_AC_STATE_PLUMBED_RESTORING) {
2564                 mutex_exit(&uacp->usb_ac_mutex);
2565 
2566                 /*
2567                  * allow hid and usb_as to restore themselves
2568                  * (some handshake would have been preferable though)
2569                  */
2570                 delay(USB_AC_RESTORE_DELAY);
2571 
2572                 usb_restore_engine(uacp);
2573 
2574                 mutex_enter(&uacp->usb_ac_mutex);
2575                 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
2576         }
2577 
2578         /* allow unplumbing */
2579         uacp->usb_ac_busy_count--;
2580         mutex_exit(&uacp->usb_ac_mutex);
2581 
2582         usb_ac_release_access(uacp);
2583 
2584         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2585             "usb_ac_am_restore_state: End");
2586 }
2587 
2588 
2589 /*
2590  * usb_ac_restore_audio_state:
2591  */
2592 static int
2593 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
2594 {
2595         ASSERT(mutex_owned(&uacp->usb_ac_mutex));
2596 
2597 
2598         switch (uacp->usb_ac_plumbing_state) {
2599         case USB_AC_STATE_PLUMBED:
2600                 uacp->usb_ac_plumbing_state =
2601                     USB_AC_STATE_PLUMBED_RESTORING;
2602 
2603                 break;
2604         case USB_AC_STATE_UNPLUMBED:
2605 
2606                 return (USB_SUCCESS);
2607         case USB_AC_STATE_PLUMBED_RESTORING:
2608         default:
2609 
2610                 return (USB_FAILURE);
2611         }
2612 
2613         /*
2614          * increment busy_count again, it will be decremented
2615          * in usb_ac_am_restore_state
2616          */
2617         uacp->usb_ac_busy_count++;
2618 
2619         if (flag & USB_FLAGS_SLEEP) {
2620                 mutex_exit(&uacp->usb_ac_mutex);
2621                 usb_ac_am_restore_state((void *)uacp);
2622                 mutex_enter(&uacp->usb_ac_mutex);
2623         } else {
2624                 mutex_exit(&uacp->usb_ac_mutex);
2625                 if (usb_async_req(uacp->usb_ac_dip,
2626                     usb_ac_am_restore_state,
2627                     (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) {
2628 
2629                         mutex_enter(&uacp->usb_ac_mutex);
2630                         uacp->usb_ac_busy_count--;
2631 
2632                         return (USB_FAILURE);
2633                 }
2634                 mutex_enter(&uacp->usb_ac_mutex);
2635         }
2636 
2637         return (USB_SUCCESS);
2638 }
2639 
2640 
2641 /*
2642  * Mixer Callback Management
2643  * NOTE: all mixer callbacks are serialized. we cannot be closed while
2644  *      we are in the middle of a callback. There needs to be a
2645  *      teardown first. We cannot be unplumbed as long as we are
2646  *      still open.
2647  *
2648  * usb_ac_setup:
2649  *      Send setup to usb_as if the first setup
2650  *      Check power is done in usb_ac_send_as_cmd()
2651  */
2652 static int
2653 usb_ac_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2654 {
2655         int     rval = USB_SUCCESS;
2656 
2657 
2658         mutex_enter(&uacp->usb_ac_mutex);
2659 
2660         if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2661                 mutex_exit(&uacp->usb_ac_mutex);
2662 
2663                 return (USB_FAILURE);
2664         }
2665         mutex_exit(&uacp->usb_ac_mutex);
2666 
2667         usb_ac_serialize_access(uacp);
2668 
2669 
2670         rval = usb_ac_do_setup(uacp, engine);
2671 
2672         usb_ac_release_access(uacp);
2673 
2674         return (rval);
2675 }
2676 
2677 
2678 /*
2679  * usb_ac_do_setup:
2680  *      Wrapper function for usb_ac_setup which can be called
2681  *      either from audio framework for usb_ac_set_format
2682  */
2683 static int
2684 usb_ac_do_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2685 {
2686         usb_ac_streams_info_t   *streams_infop = NULL;
2687 
2688 
2689         mutex_enter(&uacp->usb_ac_mutex);
2690 
2691 
2692         streams_infop = (usb_ac_streams_info_t *)engine->streams;
2693 
2694         /*
2695          * Handle multiple setup calls. Pass the setup call to usb_as only
2696          * the first time so isoc pipe will be opened only once
2697          */
2698         if (streams_infop->acs_setup_teardown_count++) {
2699                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2700                     "usb_ac_do_setup: more than one setup, cnt=%d",
2701                     streams_infop->acs_setup_teardown_count);
2702 
2703                 mutex_exit(&uacp->usb_ac_mutex);
2704 
2705                 return (USB_SUCCESS);
2706         }
2707 
2708         /* Send setup command to usb_as */
2709         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SETUP, 0) !=
2710             USB_SUCCESS) {
2711                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2712                     "usb_ac_do_setup: failure");
2713 
2714                 streams_infop->acs_setup_teardown_count--;
2715 
2716                 mutex_exit(&uacp->usb_ac_mutex);
2717 
2718                 return (USB_FAILURE);
2719         }
2720 
2721         mutex_exit(&uacp->usb_ac_mutex);
2722 
2723         return (USB_SUCCESS);
2724 }
2725 
2726 
2727 /*
2728  * usb_ac_teardown:
2729  *      Send teardown to usb_as if the last teardown
2730  *      Check power is done in usb_ac_send_as_cmd()
2731  *      NOTE: allow teardown when disconnected
2732  */
2733 static void
2734 usb_ac_teardown(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2735 {
2736 
2737         usb_ac_streams_info_t   *streams_infop = NULL;
2738 
2739         usb_ac_serialize_access(uacp);
2740 
2741 
2742         streams_infop = engine->streams;
2743 
2744 
2745         mutex_enter(&uacp->usb_ac_mutex);
2746 
2747 
2748 
2749         /* There should be at least one matching setup call */
2750         ASSERT(streams_infop->acs_setup_teardown_count);
2751 
2752         /*
2753          * Handle multiple setup/teardown calls. Pass the call to usb_as
2754          * only this is the last teardown so that isoc pipe is closed
2755          * only once
2756          */
2757         if (--(streams_infop->acs_setup_teardown_count)) {
2758                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2759                     "usb_ac_teardown: more than one setup/teardown, "
2760                     "cnt=%d",
2761                     streams_infop->acs_setup_teardown_count);
2762 
2763                 goto done;
2764         }
2765 
2766         /* Send teardown command to usb_as */
2767         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_TEARDOWN,
2768             (void *)NULL) != USB_SUCCESS) {
2769 
2770                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2771                     "usb_ac_teardown: failure");
2772 
2773                 streams_infop->acs_setup_teardown_count++;
2774 
2775 
2776                 goto done;
2777         }
2778 done:
2779 
2780         mutex_exit(&uacp->usb_ac_mutex);
2781 
2782         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2783             "usb_ac_teardown: End");
2784         usb_ac_release_access(uacp);
2785 }
2786 
2787 
2788 /*
2789  * usb_ac_set_monitor_gain:
2790  *      called for each output terminal which supports
2791  *      from usb_ac_traverse_connections
2792  */
2793 static int
2794 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
2795     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2796 {
2797         usb_audio_output_term_descr_t *d =
2798             uacp->usb_ac_units[unit].acu_descriptor;
2799 
2800         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2801             "usb_ac_set_monitor_gain: ");
2802 
2803         /* log how we got here */
2804         usb_ac_push_unit_id(uacp, unit);
2805         usb_ac_show_traverse_path(uacp);
2806         usb_ac_pop_unit_id(uacp, unit);
2807 
2808         /* we only care about the ITs connected to real hw inputs */
2809         switch (d->wTerminalType) {
2810         case USB_AUDIO_TERM_TYPE_STREAMING:
2811 
2812                 return (USB_FAILURE);
2813 
2814         case USB_AUDIO_TERM_TYPE_DT_MICROPHONE:
2815         case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE:
2816         case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE:
2817         case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY:
2818         case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY:
2819         default:
2820 
2821                 break;
2822         }
2823 
2824         /*
2825          * we can only do this if the microphone is mixed into the
2826          * audio output so look for a mixer first
2827          */
2828         if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) ==
2829             USB_SUCCESS) {
2830                 int i, id;
2831 
2832                 /* now look for a feature unit */
2833                 for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0;
2834                     i--) {
2835                         id = uacp->usb_ac_traverse_path[i];
2836 
2837                         switch (uacp->usb_ac_unit_type[id]) {
2838                         case USB_AUDIO_MIXER_UNIT:
2839 
2840                                 /* the FU should be before the mixer */
2841                                 return (USB_FAILURE);
2842 
2843                         case USB_AUDIO_FEATURE_UNIT:
2844                                 /*
2845                                  * now set the volume
2846                                  */
2847                                 if (usb_ac_set_gain(uacp, id, dir, channel,
2848                                     control, gain, depth) != USB_SUCCESS) {
2849 
2850                                         /* try master channel */
2851                                         if (usb_ac_set_gain(uacp, id, dir,
2852                                             0, control, gain, depth) !=
2853                                             USB_SUCCESS) {
2854 
2855                                                 return (USB_FAILURE);
2856                                         }
2857                                 }
2858 
2859                                 return (USB_SUCCESS);
2860 
2861                         default:
2862                                 continue;
2863                         }
2864                 }
2865         }
2866 
2867         return (USB_FAILURE);
2868 }
2869 
2870 
2871 /*
2872  * usb_ac_set_gain is called for each feature unit which supports
2873  * the requested controls from usb_ac_traverse_connections
2874  * we still need to check whether this unit supports the requested
2875  * control.
2876  */
2877 static int
2878 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
2879     uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2880 {
2881         short max, min, current;
2882 
2883         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2884             "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
2885             featureID, dir, channel, control, gain);
2886 
2887         if (usb_ac_feature_unit_check(uacp, featureID,
2888             dir, channel, control, gain, depth) != USB_SUCCESS) {
2889 
2890                 return (USB_FAILURE);
2891         }
2892 
2893         if (usb_ac_get_maxmin_volume(uacp, channel,
2894             USB_AUDIO_GET_MAX, dir, featureID, &max) != USB_SUCCESS) {
2895                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2896                     "usb_ac_set_gain: getting max gain failed");
2897 
2898                 return (USB_FAILURE);
2899         }
2900 
2901         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2902             "usb_ac_set_gain: channel %d, max=%d", channel, max);
2903 
2904         if (usb_ac_get_maxmin_volume(uacp, channel,
2905             USB_AUDIO_GET_MIN, dir, featureID, &min) != USB_SUCCESS) {
2906                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2907                     "usb_ac_set_gain: getting min gain failed");
2908 
2909                 return (USB_FAILURE);
2910         }
2911 
2912         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2913             "usb_ac_set_gain: channel=%d, min=%d", channel, min);
2914 
2915         if (usb_ac_get_maxmin_volume(uacp, channel,
2916             USB_AUDIO_GET_CUR, dir, featureID, &current) != USB_SUCCESS) {
2917                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2918                     "usb_ac_set_gain: getting cur gain failed");
2919 
2920                 return (USB_FAILURE);
2921         }
2922 
2923         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2924             "usb_ac_set_gain: channel=%d, cur=%d", channel, current);
2925 
2926         /*
2927          * Set the gain for a channel. The audio mixer calculates the
2928          * impact, if any, on the channel's gain.
2929          *
2930          *      0 <= gain <= AUDIO_MAX_GAIN
2931          *
2932          *      channel #, 0 == left, 1 == right
2933          */
2934 
2935         if (gain == 0) {
2936                 gain = USB_AUDIO_VOLUME_SILENCE;
2937         } else {
2938                 gain = max - ((max - min) * (AF_MAX_GAIN - gain))/AF_MAX_GAIN;
2939         }
2940 
2941         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2942             "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
2943             channel, dir, max, min, gain);
2944 
2945         if (usb_ac_set_volume(uacp, channel, gain, dir,
2946             featureID) != USB_SUCCESS) {
2947                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2948                     "usb_ac_set_gain: setting volume failed");
2949 
2950                 return (USB_FAILURE);
2951         }
2952 
2953         /* just curious, read it back, device may round up/down */
2954         if (usb_ac_get_maxmin_volume(uacp, channel,
2955             USB_AUDIO_GET_CUR, dir, featureID, &current) != USB_SUCCESS) {
2956                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2957                     "usb_ac_set_gain: getting cur gain failed");
2958         }
2959 
2960         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2961             "usb_ac_set_gain done: "
2962             "id=%d channel=%d, cur=%d gain=%d", featureID, channel,
2963             (ushort_t)current, (ushort_t)gain);
2964 
2965         return (USB_SUCCESS);
2966 }
2967 
2968 
2969 /*
2970  * usb_ac_set_format
2971  *      This mixer callback initiates a command to be sent to
2972  *      usb_as to select an alternate with the passed characteristics
2973  *      and also to set the sample frequency.
2974  *      Note that this may be called when a playing is going on in
2975  *      the streaming interface. To handle that, first stop
2976  *      playing/recording, close the pipe by sending a teardown
2977  *      command, send the set_format command down and then reopen
2978  *      the pipe. Note : (1) audio framework will restart play/record
2979  *      after a set_format command. (2) Check power is done in
2980  *      usb_ac_send_as_cmd().
2981  */
2982 int
2983 usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2984 {
2985         usb_ac_streams_info_t   *streams_infop = NULL;
2986         usb_audio_formats_t     format;
2987         int old_setup_teardown_count = 0;
2988 
2989         mutex_enter(&uacp->usb_ac_mutex);
2990         streams_infop = (usb_ac_streams_info_t *)engine->streams;
2991 
2992         if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2993                 mutex_exit(&uacp->usb_ac_mutex);
2994 
2995                 return (USB_FAILURE);
2996         }
2997         mutex_exit(&uacp->usb_ac_mutex);
2998 
2999         usb_ac_serialize_access(uacp);
3000         mutex_enter(&uacp->usb_ac_mutex);
3001 
3002         bzero(&format, sizeof (usb_audio_formats_t));
3003 
3004         /* save format info */
3005         format.fmt_n_srs        = 1;
3006         format.fmt_srs          = (uint_t *)&(engine->fmt.sr);
3007         format.fmt_chns         = (uchar_t)engine->fmt.ch;
3008         format.fmt_precision    = (uchar_t)engine->fmt.prec;
3009         format.fmt_encoding     = (uchar_t)engine->fmt.enc;
3010 
3011         old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3012 
3013         /* isoc pipe not open and playing is not in progress */
3014         if (old_setup_teardown_count) {
3015                 streams_infop->acs_setup_teardown_count = 1;
3016 
3017                 mutex_exit(&uacp->usb_ac_mutex);
3018                 usb_ac_release_access(uacp);
3019 
3020                 usb_ac_stop_play(uacp, engine);
3021                 usb_ac_teardown(uacp, engine);
3022 
3023                 usb_ac_serialize_access(uacp);
3024                 mutex_enter(&uacp->usb_ac_mutex);
3025         }
3026 
3027         /*
3028          * Set format for the streaming interface with lower write queue
3029          * This boils down to set_alternate  interface command in
3030          * usb_as and the reply mp contains the currently active
3031          * alternate number that is stored in the as_req structure
3032          */
3033         if (usb_ac_send_as_cmd(uacp, engine,
3034             USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
3035                 USB_DPRINTF_L2(PRINT_MASK_ALL,
3036                     uacp->usb_ac_log_handle,
3037                     "usb_ac_set_format: failed");
3038                 goto fail;
3039 
3040         }
3041         int sample =  engine->fmt.sr;
3042 
3043         /* Set the sample rate */
3044         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
3045             &sample) != USB_SUCCESS) {
3046                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3047                     "usb_ac_set_format: setting format failed");
3048                 goto fail;
3049 
3050         }
3051 
3052         mutex_exit(&uacp->usb_ac_mutex);
3053 
3054         usb_ac_release_access(uacp);
3055 
3056         /* This should block until successful */
3057         if (old_setup_teardown_count) {
3058                 (void) usb_ac_setup(uacp, engine);
3059         }
3060 
3061         mutex_enter(&uacp->usb_ac_mutex);
3062         streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3063         mutex_exit(&uacp->usb_ac_mutex);
3064 
3065         return (USB_SUCCESS);
3066 fail:
3067         streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3068         mutex_exit(&uacp->usb_ac_mutex);
3069         usb_ac_release_access(uacp);
3070 
3071         return (USB_FAILURE);
3072 
3073 }
3074 
3075 /*
3076  * usb_ac_start_play
3077  *      Send a start_play command down to usb_as
3078  *      Check power is done in usb_ac_send_as_cmd()
3079  */
3080 static int
3081 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3082 {
3083         int                     samples;
3084         usb_audio_play_req_t    play_req;
3085 
3086 
3087         mutex_enter(&uacp->usb_ac_mutex);
3088         if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3089                 mutex_exit(&uacp->usb_ac_mutex);
3090 
3091                 return (USB_FAILURE);
3092         }
3093         mutex_exit(&uacp->usb_ac_mutex);
3094 
3095         usb_ac_serialize_access(uacp);
3096 
3097         mutex_enter(&uacp->usb_ac_mutex);
3098 
3099 
3100 
3101         /* Check for continuous sample rate done in usb_as */
3102         samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
3103         if (samples & engine->fmt.ch) {
3104                 samples++;
3105         }
3106 
3107         play_req.up_samples = samples;
3108         play_req.up_handle = uacp;
3109 
3110         /* Send setup command to usb_as */
3111         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
3112             (void *)&play_req) != USB_SUCCESS) {
3113 
3114                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3115                     "usb_ac_start_play: failure");
3116 
3117                 mutex_exit(&uacp->usb_ac_mutex);
3118 
3119                 usb_ac_release_access(uacp);
3120 
3121                 return (USB_FAILURE);
3122         }
3123 
3124         mutex_exit(&uacp->usb_ac_mutex);
3125 
3126         usb_ac_release_access(uacp);
3127 
3128         return (USB_SUCCESS);
3129 }
3130 
3131 
3132 /*
3133  * usb_ac_stop_play:
3134  *      Stop the play engine
3135  *      called from mixer framework.
3136  */
3137 void
3138 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3139 {
3140 
3141         if (engine == NULL) {
3142                 engine = &(uacp->engines[0]);
3143         }
3144         mutex_enter(&uacp->usb_ac_mutex);
3145         if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3146                 mutex_exit(&uacp->usb_ac_mutex);
3147 
3148                 return;
3149         }
3150         mutex_exit(&uacp->usb_ac_mutex);
3151 
3152         usb_ac_serialize_access(uacp);
3153         mutex_enter(&uacp->usb_ac_mutex);
3154 
3155         /* Send setup command to usb_as */
3156         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
3157             (void *)NULL) != USB_SUCCESS) {
3158 
3159                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3160                     "usb_ac_do_pause_play: failure");
3161         }
3162 
3163         mutex_exit(&uacp->usb_ac_mutex);
3164         usb_ac_release_access(uacp);
3165 }
3166 
3167 
3168 /*
3169  * usb_ac_start_record:
3170  *      Sends a start record command down to usb_as.
3171  *      Check power is done in usb_ac_send_as_cmd()
3172  */
3173 static int
3174 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3175 {
3176 
3177 
3178         mutex_enter(&uacp->usb_ac_mutex);
3179         if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3180                 mutex_exit(&uacp->usb_ac_mutex);
3181 
3182                 return (USB_FAILURE);
3183         }
3184         mutex_exit(&uacp->usb_ac_mutex);
3185 
3186         usb_ac_serialize_access(uacp);
3187         mutex_enter(&uacp->usb_ac_mutex);
3188 
3189 
3190         /* Send setup command to usb_as */
3191         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
3192             (void *)uacp) != USB_SUCCESS) {
3193 
3194                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3195                     "usb_ac_start_record: failure");
3196 
3197                 mutex_exit(&uacp->usb_ac_mutex);
3198 
3199                 usb_ac_release_access(uacp);
3200 
3201                 return (USB_FAILURE);
3202         }
3203 
3204         mutex_exit(&uacp->usb_ac_mutex);
3205         usb_ac_release_access(uacp);
3206 
3207         return (USB_SUCCESS);
3208 }
3209 
3210 
3211 /*
3212  * usb_ac_stop_record:
3213  *      Wrapper function for usb_ac_do_stop_record and is
3214  *      called form mixer framework.
3215  */
3216 static void
3217 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3218 {
3219 
3220         usb_ac_serialize_access(uacp);
3221         mutex_enter(&uacp->usb_ac_mutex);
3222 
3223         /* Send setup command to usb_as */
3224         if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
3225             NULL) != USB_SUCCESS) {
3226 
3227                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3228                     "usb_ac_do_stop_record: failure");
3229         }
3230 
3231         mutex_exit(&uacp->usb_ac_mutex);
3232         usb_ac_release_access(uacp);
3233 }
3234 
3235 
3236 /*
3237  * Helper Functions for Mixer callbacks
3238  *
3239  * usb_ac_get_maxmin_volume:
3240  *      Send USBA command down to get the maximum or minimum gain balance
3241  *      Calculate min or max gain balance and return that. Return
3242  *      USB_FAILURE for failure cases
3243  */
3244 /* ARGSUSED */
3245 static int
3246 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
3247     int dir, int feature_unitID, short *max_or_minp)
3248 {
3249         mblk_t          *data = NULL;
3250         usb_cr_t        cr;
3251         usb_cb_flags_t  cb_flags;
3252 
3253 
3254         mutex_exit(&uacp->usb_ac_mutex);
3255 
3256         if (usb_pipe_sync_ctrl_xfer(
3257             uacp->usb_ac_dip,
3258             uacp->usb_ac_default_ph,
3259             USB_DEV_REQ_DEV_TO_HOST |
3260             USB_DEV_REQ_TYPE_CLASS |
3261             USB_DEV_REQ_RCPT_IF,        /* bmRequestType */
3262             cmd,                        /* bRequest */
3263             (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3264                                         /* feature unit and id */
3265             (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
3266             2,                          /* wLength */
3267             &data,
3268             USB_ATTRS_NONE,
3269             &cr, &cb_flags,
3270             USB_FLAGS_SLEEP) != USB_SUCCESS) {
3271                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3272                     "usb_ac_get_maxmin_volume: failed, "
3273                     "cr=%d, cb=0x%x cmd=%d, data=0x%p",
3274                     cr, cb_flags, cmd, (void *)data);
3275 
3276                 freemsg(data);
3277                 mutex_enter(&uacp->usb_ac_mutex);
3278 
3279                 return (USB_FAILURE);
3280         }
3281 
3282         mutex_enter(&uacp->usb_ac_mutex);
3283         ASSERT(MBLKL(data) == 2);
3284 
3285         *max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr;
3286 
3287         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3288             "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp);
3289 
3290         freemsg(data);
3291 
3292         return (USB_SUCCESS);
3293 }
3294 
3295 
3296 /*
3297  * usb_ac_set_volume:
3298  *      Send USBA command down to set the gain balance
3299  */
3300 /* ARGSUSED */
3301 static int
3302 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
3303     int feature_unitID)
3304 {
3305         mblk_t          *data = NULL;
3306         usb_cr_t        cr;
3307         usb_cb_flags_t  cb_flags;
3308         int             rval = USB_FAILURE;
3309 
3310 
3311         mutex_exit(&uacp->usb_ac_mutex);
3312 
3313         /* Construct the mblk_t from gain for sending to USBA */
3314         data = allocb(4, BPRI_HI);
3315         if (!data) {
3316                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3317                     "usb_ac_set_volume: allocate data failed");
3318                 mutex_enter(&uacp->usb_ac_mutex);
3319 
3320                 return (USB_FAILURE);
3321         }
3322 
3323 
3324 
3325         *(data->b_wptr++) = (char)gain;
3326         *(data->b_wptr++) = (char)(gain >> 8);
3327 
3328         if ((rval = usb_pipe_sync_ctrl_xfer(
3329             uacp->usb_ac_dip,
3330             uacp->usb_ac_default_ph,
3331             USB_DEV_REQ_HOST_TO_DEV |
3332             USB_DEV_REQ_TYPE_CLASS |
3333             USB_DEV_REQ_RCPT_IF,                /* bmRequestType */
3334             USB_AUDIO_SET_CUR,                  /* bRequest */
3335             (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3336                                                 /* feature unit and id */
3337             (feature_unitID << 8) | uacp->usb_ac_ifno, /* wIndex */
3338             2,                                  /* wLength */
3339             &data, 0,
3340             &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
3341                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3342                     "usb_ac_set_volume: failed, cr=%d cb=0x%x",
3343                     cr, cb_flags);
3344         }
3345 
3346         freemsg(data);
3347         mutex_enter(&uacp->usb_ac_mutex);
3348 
3349         return (rval);
3350 }
3351 
3352 
3353 /*
3354  * usb_ac_set_mute is called for each unit that supports the
3355  * requested control from usb_ac_traverse_connections
3356  */
3357 int
3358 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
3359     uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
3360 {
3361         mblk_t          *data;
3362         usb_cr_t        cr;
3363         usb_cb_flags_t  cb_flags;
3364         int             rval = USB_FAILURE;
3365 
3366 
3367         if (usb_ac_feature_unit_check(uacp, featureID,
3368             dir, channel, control, 0, depth) != USB_SUCCESS) {
3369 
3370                 return (USB_FAILURE);
3371         }
3372         mutex_exit(&uacp->usb_ac_mutex);
3373 
3374         /* Construct the mblk_t for sending to USBA */
3375         data = allocb(1, BPRI_HI);
3376 
3377         if (!data) {
3378                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3379                     "usb_ac_set_mute: allocate data failed");
3380                 mutex_enter(&uacp->usb_ac_mutex);
3381 
3382                 return (USB_FAILURE);
3383         }
3384 
3385 
3386         *(data->b_wptr++) = (char)muteval;
3387 
3388         if ((rval = usb_pipe_sync_ctrl_xfer(
3389             uacp->usb_ac_dip,
3390             uacp->usb_ac_default_ph,
3391             USB_DEV_REQ_HOST_TO_DEV |
3392             USB_DEV_REQ_TYPE_CLASS |
3393             USB_DEV_REQ_RCPT_IF,                /* bmRequestType */
3394             USB_AUDIO_SET_CUR,                  /* bRequest */
3395             (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
3396                                                 /* feature unit and id */
3397             (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
3398             1,                                  /* wLength */
3399             &data,
3400             0,                                  /* attributes */
3401             &cr, &cb_flags, 0)) != USB_SUCCESS) {
3402 
3403                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3404                     "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
3405         }
3406         freemsg(data);
3407 
3408         mutex_enter(&uacp->usb_ac_mutex);
3409 
3410         return (rval);
3411 }
3412 
3413 
3414 /*
3415  * usb_ac_send_as_cmd:
3416  *      Allocate message blk, send a command down to usb_as,
3417  *      wait for the reply and free the message
3418  *
3419  *      although not really needed to raise power if sending to as
3420  *      it seems better to ensure that both interfaces are at full power
3421  */
3422 static int
3423 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
3424     int cmd, void *arg)
3425 {
3426         usb_ac_streams_info_t *streams_infop;
3427         usb_ac_plumbed_t *plumb_infop;
3428         int             rv;
3429         int             rval;
3430         ldi_handle_t    lh;
3431 
3432         ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3433         streams_infop = engine->streams;
3434         plumb_infop = streams_infop->acs_plumbed;
3435 
3436 
3437         lh = plumb_infop->acp_lh;
3438 
3439         rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval);
3440         if (rv != 0) {
3441                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3442                     "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv);
3443 
3444                 return (USB_FAILURE);
3445         }
3446 
3447         return (USB_SUCCESS);
3448 }
3449 
3450 
3451 /*
3452  * usb_ac_serialize/release_access:
3453  */
3454 static void
3455 usb_ac_serialize_access(usb_ac_state_t  *uacp)
3456 {
3457         (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3458 }
3459 
3460 static void
3461 usb_ac_release_access(usb_ac_state_t *uacp)
3462 {
3463         usb_release_access(uacp->usb_ac_ser_acc);
3464 }
3465 
3466 
3467 static void
3468 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
3469 {
3470         ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3471 
3472         if (usb_ac_statep->usb_ac_pm != NULL) {
3473                 mutex_enter(&usb_ac_statep->usb_ac_mutex);
3474                 usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
3475 
3476                 USB_DPRINTF_L4(PRINT_MASK_PM,
3477                     usb_ac_statep->usb_ac_log_handle,
3478                     "usb_ac_pm_busy_component: %d",
3479                     usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3480 
3481                 mutex_exit(&usb_ac_statep->usb_ac_mutex);
3482 
3483                 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
3484                     DDI_SUCCESS) {
3485                         mutex_enter(&usb_ac_statep->usb_ac_mutex);
3486                         usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3487 
3488                         USB_DPRINTF_L2(PRINT_MASK_PM,
3489                             usb_ac_statep->usb_ac_log_handle,
3490                             "usb_ac_pm_busy_component failed: %d",
3491                             usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3492 
3493                         mutex_exit(&usb_ac_statep->usb_ac_mutex);
3494                 }
3495         }
3496 }
3497 
3498 
3499 static void
3500 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
3501 {
3502         ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3503 
3504         if (usb_ac_statep->usb_ac_pm != NULL) {
3505                 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
3506                     DDI_SUCCESS) {
3507                         mutex_enter(&usb_ac_statep->usb_ac_mutex);
3508                         ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
3509                         usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3510 
3511                         USB_DPRINTF_L4(PRINT_MASK_PM,
3512                             usb_ac_statep->usb_ac_log_handle,
3513                             "usb_ac_pm_idle_component: %d",
3514                             usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3515 
3516                         mutex_exit(&usb_ac_statep->usb_ac_mutex);
3517                 }
3518         }
3519 }
3520 
3521 
3522 /*
3523  * handle read from plumbed drivers
3524  */
3525 static void
3526 usb_ac_reader(void *argp)
3527 {
3528         usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp;
3529         usb_ac_state_t *uacp = acp->acp_uacp;
3530         ldi_handle_t lh;
3531         mblk_t *mp;
3532         int rv;
3533         timestruc_t tv = {0};
3534 
3535         mutex_enter(&uacp->usb_ac_mutex);
3536         lh = acp->acp_lh;
3537         tv.tv_sec = usb_ac_wait_hid;
3538 
3539         while (acp->acp_flags & ACP_ENABLED) {
3540                 mp = NULL;
3541 
3542                 mutex_exit(&uacp->usb_ac_mutex);
3543 
3544                 rv = ldi_getmsg(lh, &mp, &tv);
3545 
3546                 mutex_enter(&uacp->usb_ac_mutex);
3547 
3548                 if (rv == ENODEV) {
3549                         USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3550                             "Device is not availabe");
3551                         break;
3552                 }
3553 
3554 
3555                 if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0)
3556                         rv = usb_ac_read_msg(acp, mp);
3557 
3558         }
3559         mutex_exit(&uacp->usb_ac_mutex);
3560 }
3561 
3562 
3563 /*
3564  * setup threads to read from the other usb modules that may send unsolicited
3565  * or asynchronous messages, which is only hid currently
3566  */
3567 static int
3568 usb_ac_plumb(usb_ac_plumbed_t *acp)
3569 {
3570         usb_ac_state_t  *uacp = acp->acp_uacp;
3571         dev_info_t      *dip;
3572         dev_info_t      *acp_dip;
3573         int             acp_inst;
3574         char            *acp_name;
3575         char            tq_nm[128];
3576         int             rv = USB_FAILURE;
3577 
3578         mutex_enter(&uacp->usb_ac_mutex);
3579 
3580         dip = uacp->usb_ac_dip;
3581 
3582         acp_dip = acp->acp_dip;
3583         acp_inst = ddi_get_instance(acp_dip);
3584         acp_name = (char *)ddi_driver_name(acp_dip);
3585 
3586         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3587             "usb_ac_plumb:begin");
3588 
3589         if (strcmp(acp_name, "hid") != 0) {
3590                 rv = USB_SUCCESS;
3591                 goto OUT;
3592         }
3593 
3594         (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3595             ddi_driver_name(acp_dip), acp_inst);
3596 
3597         acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3598         if (acp->acp_tqp == NULL)
3599                 goto OUT;
3600 
3601         if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp,
3602             DDI_SLEEP) != DDI_SUCCESS)
3603                 goto OUT;
3604 
3605         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3606             "usb_ac_plumb: dispatched reader");
3607 
3608         rv = USB_SUCCESS;
3609 
3610 OUT:
3611         mutex_exit(&uacp->usb_ac_mutex);
3612 
3613         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3614             "usb_ac_plumb: done, rv=%d", rv);
3615 
3616         return (rv);
3617 }
3618 
3619 
3620 static void
3621 usb_ac_mux_plumbing_tq(void *arg)
3622 {
3623         usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3624 
3625         if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS)
3626                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3627                     "usb_ac_mux_plumbing_tq:failed");
3628 }
3629 
3630 
3631 static int
3632 usb_ac_do_plumbing(usb_ac_state_t *uacp)
3633 {
3634         dev_info_t *dip = uacp->usb_ac_dip;
3635         int inst = ddi_get_instance(dip);
3636         char tq_nm[128];
3637         int rv = USB_FAILURE;
3638 
3639         (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3640             ddi_driver_name(dip), inst);
3641 
3642         uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3643         if (uacp->tqp == NULL) {
3644                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3645                     "usb_ac_do_plumbing: ddi_taskq_create failed");
3646                 goto OUT;
3647         }
3648 
3649         if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp,
3650             DDI_SLEEP) != DDI_SUCCESS) {
3651                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3652                     "usb_ac_do_plumbing: ddi_taskq_dispatch failed");
3653                 goto OUT;
3654         }
3655 
3656         rv = USB_SUCCESS;
3657 
3658 OUT:
3659         return (rv);
3660 }
3661 
3662 
3663 
3664 static void
3665 usb_ac_mux_unplumbing_tq(void *arg)
3666 {
3667         usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3668 
3669         if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS)
3670                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3671                     "usb_ac_mux_unplumbing:failed");
3672 }
3673 
3674 
3675 static int
3676 usb_ac_do_unplumbing(usb_ac_state_t *uacp)
3677 {
3678         int rv = USB_FAILURE;
3679 
3680         if (uacp->tqp == NULL)
3681                 return (USB_SUCCESS);
3682 
3683         if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq,
3684             (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) {
3685                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3686                     "usb_ac_do_unplumbing: ddi_taskq_dispatch failed");
3687                 goto OUT;
3688         }
3689 
3690         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3691             "usb_ac_do_unplumbing: waiting for unplumb thread");
3692 
3693         ddi_taskq_wait(uacp->tqp);
3694         rv = USB_SUCCESS;
3695 
3696         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3697             "usb_ac_do_unplumbing: unplumb thread done");
3698 
3699 OUT:
3700         if (uacp->tqp != NULL) {
3701                 ddi_taskq_destroy(uacp->tqp);
3702                 uacp->tqp = NULL;
3703         }
3704         return (rv);
3705 }
3706 
3707 
3708 /*
3709  * teardown threads to the other usb modules
3710  * and clear structures as part of unplumbing
3711  */
3712 static void
3713 usb_ac_unplumb(usb_ac_plumbed_t *acp)
3714 {
3715         usb_ac_streams_info_t *streams_infop;
3716         usb_ac_state_t  *uacp = acp->acp_uacp;
3717 
3718 
3719         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3720             "usb_ac_unplumb: begin");
3721 
3722         if (acp->acp_tqp != NULL) {
3723                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3724                     "usb_ac_unplumb: destroying taskq");
3725 
3726                 ddi_taskq_destroy(acp->acp_tqp);
3727         }
3728 
3729         mutex_enter(&uacp->usb_ac_mutex);
3730 
3731         if (acp->acp_driver == USB_AS_PLUMBED) {
3732                 /*
3733                  * we bzero the streams info and plumbed structure
3734                  * since there is no guarantee that the next plumbing
3735                  * will be identical
3736                  */
3737                 streams_infop = (usb_ac_streams_info_t *)acp->acp_data;
3738 
3739                 /* bzero the relevant plumbing structure */
3740                 bzero(streams_infop, sizeof (usb_ac_streams_info_t));
3741         }
3742         bzero(acp, sizeof (usb_ac_plumbed_t));
3743 
3744         mutex_exit(&uacp->usb_ac_mutex);
3745 
3746         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3747             "usb_ac_unplumb: done");
3748 }
3749 
3750 
3751 /*ARGSUSED*/
3752 static int
3753 usb_ac_mux_plumbing(usb_ac_state_t *uacp)
3754 {
3755         dev_info_t              *dip;
3756 
3757         /* get the usb_ac dip */
3758         dip = uacp->usb_ac_dip;
3759 
3760         /* Access to the global variables is synchronized */
3761         mutex_enter(&uacp->usb_ac_mutex);
3762 
3763         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3764             "usb_ac_mux_plumbing:state = %d",
3765             uacp->usb_ac_plumbing_state);
3766 
3767         if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) {
3768                 mutex_exit(&uacp->usb_ac_mutex);
3769                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3770                     "usb_ac_mux_plumbing: audio streams driver"
3771                     " already plumbed");
3772 
3773                 return (USB_SUCCESS);
3774         }
3775 
3776         /* usb_as and hid should be attached but double check */
3777         if (usb_ac_online_siblings(uacp) != USB_SUCCESS) {
3778                 mutex_exit(&uacp->usb_ac_mutex);
3779                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3780                 "usb_ac_mux_plumbing:no audio streams driver plumbed");
3781 
3782                 return (USB_FAILURE);
3783         }
3784 
3785         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3786             "usb_ac_mux_plumbing: raising power");
3787         mutex_exit(&uacp->usb_ac_mutex);
3788 
3789         /* bring the device to full power */
3790         usb_ac_pm_busy_component(uacp);
3791         (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3792 
3793         /* avoid dips disappearing while we are plumbing */
3794         usb_ac_hold_siblings(uacp);
3795 
3796         mutex_enter(&uacp->usb_ac_mutex);
3797 
3798         /*
3799          * walk all siblings and create the usb_ac<->usb_as and
3800          * usb_ac<->hid streams. return of 0 indicates no or
3801          * partial/failed plumbing
3802          */
3803         if (usb_ac_mux_walk_siblings(uacp) == 0) {
3804                 /* pretend that we are plumbed so we can unplumb */
3805                 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3806 
3807                 mutex_exit(&uacp->usb_ac_mutex);
3808 
3809                 (void) usb_ac_mux_unplumbing(uacp);
3810 
3811                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3812                     "usb_ac_mux_plumbing: no audio streams driver plumbed");
3813 
3814                 usb_ac_rele_siblings(uacp);
3815 
3816                 usb_ac_pm_idle_component(uacp);
3817 
3818                 return (USB_FAILURE);
3819         }
3820         uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3821 
3822         /* restore state if we have already registered with the mixer */
3823         if (uacp->usb_ac_registered_with_mixer) {
3824                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3825                     "usb_ac_mux_plumbing:already registered with mixer,"
3826                     "restoring state");
3827 
3828                 (void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP);
3829 
3830         } else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) {
3831                 mutex_exit(&uacp->usb_ac_mutex);
3832 
3833                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3834                     "usb_ac_mux_plumbing: mixer registration failed");
3835 
3836                 (void) usb_ac_mux_unplumbing(uacp);
3837 
3838                 usb_ac_rele_siblings(uacp);
3839 
3840                 usb_ac_pm_idle_component(uacp);
3841 
3842                 return (USB_FAILURE);
3843         }
3844 
3845         mutex_exit(&uacp->usb_ac_mutex);
3846         usb_ac_rele_siblings(uacp);
3847 
3848         usb_ac_pm_idle_component(uacp);
3849 
3850         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3851             "usb_ac_mux_plumbing:done");
3852 
3853         return (USB_SUCCESS);
3854 }
3855 
3856 
3857 static int
3858 usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
3859 {
3860         usb_ac_plumbed_t        *acp;
3861         ldi_handle_t            lh;
3862         dev_info_t              *acp_dip;
3863         int                     inst;
3864         int                     i;
3865         dev_t                   devt;
3866         minor_t                 minor;
3867         int                     maxlinked = 0;
3868 
3869         mutex_enter(&uacp->usb_ac_mutex);
3870 
3871 
3872         if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) {
3873                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3874                     "usb_ac_mux_unplumbing: already unplumbed!");
3875                 mutex_exit(&uacp->usb_ac_mutex);
3876 
3877                 return (USB_SUCCESS);
3878         }
3879 
3880         /* usb_ac might not have anything plumbed yet */
3881         if (uacp->usb_ac_current_plumbed_index == -1) {
3882                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3883                     "usb_ac_mux_unplumbing: nothing plumbed");
3884                 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3885                 mutex_exit(&uacp->usb_ac_mutex);
3886 
3887                 return (USB_SUCCESS);
3888         }
3889 
3890         /* do not allow detach if still busy */
3891         if (uacp->usb_ac_busy_count) {
3892                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3893                     "usb_ac_mux_unplumbing: mux still busy (%d)",
3894                     uacp->usb_ac_busy_count);
3895                 mutex_exit(&uacp->usb_ac_mutex);
3896 
3897                 return (USB_FAILURE);
3898         }
3899 
3900         uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3901 
3902         /* close ac-as and ac-hid streams */
3903         maxlinked = uacp->usb_ac_current_plumbed_index + 1;
3904         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3905             "usb_ac_mux_unplumbing: maxlinked = %d",  maxlinked);
3906 
3907         for (i = 0; i < maxlinked; i++) {
3908                 /*
3909                  * we must save members of usb_ac_plumbed[] before calling
3910                  * usb_ac_unplumb() because it clears the structure
3911                  */
3912                 acp = &uacp->usb_ac_plumbed[i];
3913                 lh = acp->acp_lh;
3914                 acp_dip = acp->acp_dip;
3915                 devt = acp->acp_devt;
3916 
3917                 if (acp_dip == NULL) {
3918                         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3919                             "usb_ac_mux_unplumbing: [%d] - skipping",  i);
3920                         continue;
3921                 }
3922 
3923                 minor = getminor(devt);
3924                 inst = ddi_get_instance(acp_dip);
3925 
3926                 uacp->usb_ac_current_plumbed_index = i;
3927 
3928                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3929                     "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x",  i,
3930                     ddi_driver_name(acp_dip), inst, minor);
3931 
3932                 if (lh != NULL) {
3933 
3934                         acp->acp_flags &= ~ACP_ENABLED;
3935 
3936                         mutex_exit(&uacp->usb_ac_mutex);
3937 
3938                         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3939                             "usb_ac_mux_unplumbing:[%d] - closing", i);
3940 
3941                         /*
3942                          * ldi_close will cause panic if ldi_getmsg
3943                          * is not finished. ddi_taskq_destroy will wait
3944                          * for the thread to complete.
3945                          */
3946                         usb_ac_unplumb(acp);
3947                         (void) ldi_close(lh, FREAD|FWRITE, kcred);
3948 
3949 
3950                         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3951                             "usb_ac_mux_unplumbing: [%d] - unplumbed", i);
3952 
3953                         mutex_enter(&uacp->usb_ac_mutex);
3954                 }
3955         }
3956 
3957         mutex_exit(&uacp->usb_ac_mutex);
3958 
3959         /* Wait till all activity in the default pipe has drained */
3960         usb_ac_serialize_access(uacp);
3961         usb_ac_release_access(uacp);
3962 
3963         mutex_enter(&uacp->usb_ac_mutex);
3964         uacp->usb_ac_current_plumbed_index = -1;
3965         mutex_exit(&uacp->usb_ac_mutex);
3966 
3967         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3968             "usb_ac_mux_unplumbing: done");
3969 
3970         return (USB_SUCCESS);
3971 }
3972 
3973 
3974 /*
3975  * walk all siblings and create the ac<->as and ac<->hid streams
3976  */
3977 static int
3978 usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
3979 {
3980         dev_info_t      *pdip;
3981         dev_info_t      *child_dip;
3982         major_t         drv_major;
3983         minor_t         drv_minor;
3984         int             drv_instance;
3985         char            *drv_name;
3986         dev_t           drv_devt;
3987         ldi_handle_t    drv_lh;
3988         ldi_ident_t     li;
3989         int             error;
3990         int             count = 0;
3991 
3992         ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3993 
3994         pdip = ddi_get_parent(uacp->usb_ac_dip);
3995         child_dip = ddi_get_child(pdip);
3996 
3997         while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) {
3998                 drv_instance = ddi_get_instance(child_dip);
3999                 drv_name = (char *)ddi_driver_name(child_dip);
4000 
4001                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4002                     "usb_ac_mux_walk_siblings: plumbing %s%d count=%d",
4003                     drv_name, drv_instance, count);
4004 
4005                 /* ignore own dip */
4006                 if (child_dip == uacp->usb_ac_dip) {
4007                         child_dip = ddi_get_next_sibling(child_dip);
4008                         continue;
4009                 }
4010                 drv_instance = ddi_get_instance(child_dip);
4011 
4012                 /* ignore other dip other than usb_as and hid */
4013                 if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) {
4014                         uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED;
4015                         drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance);
4016                 } else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) {
4017                         uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED;
4018                         drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance);
4019                 } else {
4020                         drv_minor = drv_instance;
4021                         uacp->usb_ac_plumbed[count].acp_driver =
4022                             UNKNOWN_PLUMBED;
4023                         child_dip = ddi_get_next_sibling(child_dip);
4024 
4025                         continue;
4026                 }
4027 
4028                 if (!i_ddi_devi_attached(child_dip)) {
4029                         child_dip = ddi_get_next_sibling(child_dip);
4030 
4031                         continue;
4032                 }
4033 
4034                 if (DEVI_IS_DEVICE_REMOVED(child_dip)) {
4035                         child_dip = ddi_get_next_sibling(child_dip);
4036 
4037                         continue;
4038                 }
4039 
4040                 drv_major = ddi_driver_major(child_dip);
4041 
4042                 uacp->usb_ac_current_plumbed_index = count;
4043 
4044                 mutex_exit(&uacp->usb_ac_mutex);
4045 
4046                 drv_devt = makedevice(drv_major, drv_minor);
4047 
4048                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4049                     "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)",
4050                     drv_name, drv_instance, drv_major, drv_minor);
4051 
4052                 error = ldi_ident_from_dip(uacp->usb_ac_dip, &li);
4053                 if (error == 0) {
4054                         mutex_enter(&uacp->usb_ac_mutex);
4055                         uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED;
4056                         mutex_exit(&uacp->usb_ac_mutex);
4057 
4058                         error = ldi_open_by_dev(&drv_devt, OTYP_CHR,
4059                             FREAD|FWRITE, kcred, &drv_lh, li);
4060                         ldi_ident_release(li);
4061                 }
4062 
4063                 mutex_enter(&uacp->usb_ac_mutex);
4064                 if (error) {
4065                         USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4066                             "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)"
4067                             " failed error=%d", drv_major, drv_minor, error);
4068 
4069                         return (0);
4070                 }
4071 
4072                 uacp->usb_ac_plumbed[count].acp_uacp = uacp;
4073                 uacp->usb_ac_plumbed[count].acp_devt = drv_devt;
4074                 uacp->usb_ac_plumbed[count].acp_lh = drv_lh;
4075                 uacp->usb_ac_plumbed[count].acp_dip = child_dip;
4076                 uacp->usb_ac_plumbed[count].acp_ifno =
4077                     usb_get_if_number(child_dip);
4078 
4079                 if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) {
4080                         /* get registration data */
4081                         if (usb_ac_get_reg_data(uacp, drv_lh, count) !=
4082                             USB_SUCCESS) {
4083 
4084                                 USB_DPRINTF_L3(PRINT_MASK_ALL,
4085                                     uacp->usb_ac_log_handle,
4086                                     "usb_ac_mux_walk_siblings:"
4087                                     "usb_ac_get_reg_data failed on %s%d",
4088                                     drv_name, drv_instance);
4089 
4090                                 uacp->usb_ac_plumbed[count].acp_dip = NULL;
4091 
4092                                 return (0);
4093                         }
4094                 } else if (uacp->usb_ac_plumbed[count].acp_driver ==
4095                     USB_AH_PLUMBED) {
4096                         int rval;
4097 
4098                         USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4099                             "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d",
4100                             drv_name, drv_instance);
4101 
4102                         mutex_exit(&uacp->usb_ac_mutex);
4103 
4104                         /* push usb_ah module on top of hid */
4105                         error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah",
4106                             FKIOCTL, kcred, &rval);
4107                         mutex_enter(&uacp->usb_ac_mutex);
4108 
4109                         if (error) {
4110                                 USB_DPRINTF_L2(PRINT_MASK_ALL,
4111                                     uacp->usb_ac_log_handle,
4112                                     "usb_ac_mux_walk_siblings: ldi_ioctl"
4113                                     "I_PUSH failed on %s%d, error=%d",
4114                                     drv_name, drv_instance, error);
4115 
4116                                 uacp->usb_ac_plumbed[count].acp_dip = NULL;
4117 
4118                                 /* skip plumbing the hid driver */
4119                                 child_dip = ddi_get_next_sibling(child_dip);
4120                                 continue;
4121                         }
4122                 } else {
4123                         /* should not be here */
4124                         USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4125                             "usb_ac_mux_walk_siblings:- unknown module %s%d",
4126                             drv_name, drv_instance);
4127                         count--;
4128 
4129                         uacp->usb_ac_plumbed[count].acp_dip = NULL;
4130 
4131                         /* skip plumbing an unknown module */
4132                         child_dip = ddi_get_next_sibling(child_dip);
4133                         continue;
4134                 }
4135 
4136                 mutex_exit(&uacp->usb_ac_mutex);
4137                 error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]);
4138                 mutex_enter(&uacp->usb_ac_mutex);
4139 
4140                 if (error != USB_SUCCESS) {
4141                         USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4142                             "usb_ac_mux_walk_siblings: usb_ac_plumb "
4143                             "failed for %s%d", drv_name, drv_instance);
4144 
4145                         return (0);
4146                 }
4147 
4148                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4149                     "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x",
4150                     drv_instance, drv_minor);
4151 
4152                 child_dip = ddi_get_next_sibling(child_dip);
4153                 count++;
4154         }
4155 
4156         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4157             "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux",
4158             count);
4159 
4160         return (count);
4161 }
4162 
4163 
4164 /*
4165  * Register with mixer only after first plumbing.
4166  * Also do not register if earlier reg data
4167  * couldn't be received from at least one
4168  * streaming interface
4169  */
4170 
4171 static int
4172 usb_ac_mixer_registration(usb_ac_state_t *uacp)
4173 {
4174         usb_as_registration_t *asreg;
4175         int             n;
4176 
4177         if (uacp->usb_ac_registered_with_mixer) {
4178                 return (USB_SUCCESS);
4179         }
4180 
4181         for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4182                 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4183                         break;
4184                 }
4185         }
4186 
4187         /* Haven't found a streaming interface; fail mixer registration */
4188         if (n > USB_AC_MAX_AS_PLUMBED) {
4189                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4190                 "usb_ac_mixer_registration:- no streaming interface found");
4191 
4192                 return (USB_FAILURE);
4193         }
4194 
4195         /*
4196          * Fill out streaming interface specific stuff
4197          * Note that we handle only one playing and one recording
4198          * streaming interface at the most
4199          */
4200         for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4201                 int ch, chs, id;
4202 
4203                 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) {
4204                         continue;
4205                 }
4206 
4207                 asreg = &(uacp->usb_ac_streams[n].acs_streams_reg);
4208                 if (asreg->reg_valid == 0) {
4209                         continue;
4210                 }
4211 
4212 
4213                 chs = asreg->reg_formats[0].fmt_chns;
4214 
4215                 /* check if any channel supports vol. control for this fmt */
4216                 for (ch = 0; ch <= chs; ch++) {
4217                         if ((id = usb_ac_get_featureID(uacp,
4218                             asreg->reg_mode, ch,
4219                             USB_AUDIO_VOLUME_CONTROL)) != -1) {
4220                                 USB_DPRINTF_L3(PRINT_MASK_ALL,
4221                                     uacp->usb_ac_log_handle,
4222                                     "usb_ac_mixer_registration:n= [%d]"
4223                                     "- dir=%d featureID=%d",
4224                                     n, asreg->reg_mode, id);
4225 
4226                                 break;
4227                         }
4228                 }
4229 
4230                 uacp->usb_ac_streams[n].acs_default_gain =
4231                     (id == USB_AC_ID_NONE) ?  (AF_MAX_GAIN): (AF_MAX_GAIN*3/4);
4232 
4233                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4234                     "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d"
4235                     "default_gain=%d id=%d",
4236                     n, asreg->reg_mode, chs,
4237                     uacp->usb_ac_streams[n].acs_default_gain, id);
4238 
4239         }
4240 
4241         /* the rest */
4242 
4243         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4244             "usb_ac_mixer_registration: calling usb_audio_register");
4245 
4246         mutex_exit(&uacp->usb_ac_mutex);
4247 
4248         if (usb_audio_register(uacp) != USB_SUCCESS) {
4249                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4250                     "usb_ac_mixer_registration: usb_audio_register failed");
4251 
4252                 mutex_enter(&uacp->usb_ac_mutex);
4253 
4254                 return (USB_FAILURE);
4255         }
4256 
4257         mutex_enter(&uacp->usb_ac_mutex);
4258 
4259         uacp->usb_ac_registered_with_mixer = 1;
4260 
4261         return (USB_SUCCESS);
4262 }
4263 
4264 
4265 /*
4266  * Get registriations data when driver attach
4267  */
4268 static int
4269 usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
4270 {
4271         int n, error, rval;
4272         usb_as_registration_t *streams_reg;
4273 
4274 
4275         ASSERT(uacp->usb_ac_registered_with_mixer == 0);
4276 
4277         for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4278                 /*
4279                  * We haven't received registration data
4280                  * from n-th streaming interface in the array
4281                  */
4282                 if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4283                         break;
4284                 }
4285         }
4286 
4287         if (n >= USB_AC_MAX_AS_PLUMBED) {
4288                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4289                 "More than 2 streaming interfaces (play "
4290                 "and/or record) currently not supported");
4291 
4292                 return (USB_FAILURE);
4293         }
4294 
4295         /* take the stream reg struct with the same index */
4296         streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg;
4297 
4298         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4299         "usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d",
4300             (void *)streams_reg, n);
4301 
4302         mutex_exit(&uacp->usb_ac_mutex);
4303 
4304         if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION,
4305             (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) {
4306                 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4307                     "usb_ac_get_reg_data: ldi_ioctl failed for"
4308                     "mixer registration error=%d", error);
4309 
4310                 mutex_enter(&uacp->usb_ac_mutex);
4311 
4312                 return (USB_FAILURE);
4313         } else {
4314                 mutex_enter(&uacp->usb_ac_mutex);
4315 
4316                 rval = usb_ac_setup_plumbed(uacp, index, n);
4317 
4318                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4319                 "usb_ac_get_reg_data:usb_ac_streams[%d]: "
4320                     "received_reg_data=%d type=%s",  index,
4321                     uacp->usb_ac_streams[n].acs_rcvd_reg_data,
4322                     ((streams_reg->reg_mode == USB_AUDIO_PLAY) ?
4323                     "play" : "record"));
4324 
4325                 usb_ac_print_reg_data(uacp, streams_reg);
4326 
4327                 return (rval);
4328         }
4329 }
4330 
4331 
4332 /*
4333  * setup plumbed and stream info structure
4334  */
4335 static int
4336 usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx)
4337 {
4338         uacp->usb_ac_plumbed[plb_idx].acp_data =
4339             &uacp->usb_ac_streams[str_idx];
4340         uacp->usb_ac_streams[str_idx].acs_plumbed =
4341             &uacp->usb_ac_plumbed[plb_idx];
4342         uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1;
4343 
4344 
4345         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4346             "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ",
4347             plb_idx, str_idx);
4348 
4349         return (USB_SUCCESS);
4350 }
4351 
4352 
4353 /*
4354  * function to dump registration data
4355  */
4356 static void
4357 usb_ac_print_reg_data(usb_ac_state_t *uacp,
4358     usb_as_registration_t *reg)
4359 {
4360         int n;
4361 
4362         for (n = 0; n < reg->reg_n_formats; n++) {
4363                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4364                     "format%d: alt=%d chns=%d prec=%d enc=%d", n,
4365                     reg->reg_formats[n].fmt_alt,
4366                     reg->reg_formats[n].fmt_chns,
4367                     reg->reg_formats[n].fmt_precision,
4368                     reg->reg_formats[n].fmt_encoding);
4369         }
4370 
4371         for (n = 0; n < USB_AS_N_FORMATS; n++) {
4372                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4373                     "reg_formats[%d] ptr=0x%p", n,
4374                     (void *)&reg->reg_formats[n]);
4375         }
4376 
4377         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4378             "usb_ac_print_reg_data: End");
4379 }
4380 
4381 
4382 static int
4383 usb_ac_online_siblings(usb_ac_state_t *uacp)
4384 {
4385         dev_info_t      *pdip, *child_dip;
4386         int             rval = USB_SUCCESS;
4387 
4388         ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4389 
4390         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4391             "usb_ac_online_siblings:start");
4392 
4393         pdip = ddi_get_parent(uacp->usb_ac_dip);
4394 
4395         child_dip = ddi_get_child(pdip);
4396         while (child_dip != NULL) {
4397 
4398                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4399                     "usb_ac_online_siblings: onlining %s%d ref=%d",
4400                     ddi_driver_name(child_dip),
4401                     ddi_get_instance(child_dip),
4402                     DEVI(child_dip)->devi_ref);
4403 
4404                 /* Online the child_dip of usb_as and hid,  if not already */
4405                 if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) ||
4406                     (strcmp(ddi_driver_name(child_dip), "hid") == 0)) {
4407 
4408                         mutex_exit(&uacp->usb_ac_mutex);
4409                         if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
4410                             NDI_SUCCESS) {
4411                                 USB_DPRINTF_L3(PRINT_MASK_ALL,
4412                                     uacp->usb_ac_log_handle,
4413                                     "usb_ac_online_siblings:failed to online"
4414                                     "device %s%d", ddi_driver_name(child_dip),
4415                                     ddi_get_instance(child_dip));
4416 
4417                                 /* only onlining usb_as is fatal */
4418                                 if (strcmp(ddi_driver_name(child_dip),
4419                                     "usb_as") == 0) {
4420                                         mutex_enter(&uacp->usb_ac_mutex);
4421                                         rval = USB_FAILURE;
4422                                         break;
4423                                 }
4424                         }
4425                         mutex_enter(&uacp->usb_ac_mutex);
4426                 }
4427                 child_dip = ddi_get_next_sibling(child_dip);
4428         }
4429 
4430         return (rval);
4431 }
4432 
4433 
4434 /*
4435  * hold all audio children before or after plumbing
4436  * online usb_as and hid, if not already
4437  */
4438 static void
4439 usb_ac_hold_siblings(usb_ac_state_t *uacp)
4440 {
4441         int             circ;
4442         dev_info_t      *pdip, *child_dip;
4443 
4444         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4445             "usb_ac_hold_siblings:start");
4446 
4447         /* hold all siblings and ourselves */
4448         pdip = ddi_get_parent(uacp->usb_ac_dip);
4449 
4450         /* hold the children */
4451         ndi_devi_enter(pdip, &circ);
4452         child_dip = ddi_get_child(pdip);
4453         while (child_dip != NULL) {
4454                 ndi_hold_devi(child_dip);
4455 
4456                 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4457                     "usb_ac_hold_siblings: held %s%d ref=%d",
4458                     ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4459                     DEVI(child_dip)->devi_ref);
4460 
4461                 child_dip = ddi_get_next_sibling(child_dip);
4462         }
4463         ndi_devi_exit(pdip, circ);
4464 }
4465 
4466 
4467 /*
4468  * release all audio children before or after plumbing
4469  */
4470 static void
4471 usb_ac_rele_siblings(usb_ac_state_t *uacp)
4472 {
4473         int             circ;
4474         dev_info_t      *pdip, *child_dip;
4475 
4476         USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4477             "usb_ac_rele_siblings: start");
4478 
4479         /* release all siblings and ourselves */
4480         pdip = ddi_get_parent(uacp->usb_ac_dip);
4481         ndi_devi_enter(pdip, &circ);
4482         child_dip = ddi_get_child(pdip);
4483         while (child_dip != NULL) {
4484                 ndi_rele_devi(child_dip);
4485 
4486                 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4487                     "usb_ac_rele_siblings: released %s%d ref=%d",
4488                     ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4489                     DEVI(child_dip)->devi_ref);
4490 
4491                 child_dip = ddi_get_next_sibling(child_dip);
4492         }
4493         ndi_devi_exit(pdip, circ);
4494 }
4495 static void
4496 usb_restore_engine(usb_ac_state_t *statep)
4497 {
4498         usb_audio_eng_t *engp;
4499         int i;
4500 
4501         for (i = 0; i < USB_AC_ENG_MAX; i++) {
4502 
4503                 mutex_enter(&statep->usb_ac_mutex);
4504                 engp = &statep->engines[i];
4505                 mutex_exit(&statep->usb_ac_mutex);
4506 
4507                 if (engp->af_engp == NULL)
4508                         continue;
4509                 if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
4510                         USB_DPRINTF_L2(PRINT_MASK_ATTA,
4511                             statep->usb_ac_log_handle,
4512                             "usb_restore_engine:set format fail, i=%d", i);
4513                         return;
4514                 }
4515                 if (engp->started) {
4516                         (void) usb_engine_start(engp);
4517                 }
4518 
4519         }
4520 
4521         (void) usb_ac_ctrl_restore(statep);
4522 }
4523 
4524 
4525 /*
4526  * get the maximum format specification the device supports
4527  */
4528 static void
4529 usb_ac_max_fmt(usb_as_registration_t *reg_data,
4530     usb_audio_format_t *fmtp)
4531 {
4532 
4533         uint_t ch = 0, sr = 0, prec = 0, enc = 0;
4534         int i;
4535 
4536         usb_audio_formats_t *reg_formats = reg_data->reg_formats;
4537 
4538         /* format priority: channels, sample rate, precision, encoding */
4539         for (i = 0; i < reg_data->reg_n_formats; i++) {
4540                 uint_t val, fmt_sr;
4541                 int n, keep;
4542 
4543                 val = reg_formats[i].fmt_chns;
4544                 if (val < ch)
4545                         continue;
4546                 if (val > ch)
4547                         keep = 1;
4548 
4549                 for (n = 0, fmt_sr = 0; n < reg_formats[i].fmt_n_srs; n++) {
4550                         if (fmt_sr < reg_formats[i].fmt_srs[n]) {
4551                                 fmt_sr = reg_formats[i].fmt_srs[n];
4552                         }
4553                 }
4554                 if (!keep && fmt_sr < sr)
4555                         continue;
4556                 if (fmt_sr > sr)
4557                         keep = 1;
4558 
4559                 val = reg_formats[i].fmt_precision;
4560                 if (!keep && (val < prec))
4561                         continue;
4562                 if (val > prec)
4563                         keep = 1;
4564 
4565                 val = reg_formats[i].fmt_encoding;
4566                 if (!keep && (val < enc))
4567                         continue;
4568 
4569                 ch   = reg_formats[i].fmt_chns;
4570                 sr   = fmt_sr;
4571                 prec = reg_formats[i].fmt_precision;
4572                 enc  = reg_formats[i].fmt_encoding;
4573         }
4574 
4575         fmtp->ch   = ch;
4576         fmtp->sr   = sr;
4577         fmtp->prec = prec;
4578         fmtp->enc  = enc;
4579 }
4580 
4581 
4582 static void
4583 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
4584 {
4585         if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
4586                 return;
4587 
4588         audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
4589         audio_engine_free(engp->af_engp);
4590 
4591         mutex_enter(&engp->lock);
4592         engp->af_engp = NULL;
4593         engp->streams = NULL;
4594         mutex_exit(&engp->lock);
4595 
4596         mutex_destroy(&engp->lock);
4597         cv_destroy(&engp->usb_audio_cv);
4598 }
4599 
4600 
4601 static int
4602 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t  *asinfo)
4603 {
4604         audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
4605         usb_audio_eng_t *engp;
4606         audio_engine_t *af_engp;
4607         int rv = USB_FAILURE;
4608         int dir = asinfo->acs_streams_reg.reg_mode;
4609         uint_t defgain;
4610 
4611         if (asinfo->acs_rcvd_reg_data == 0) {
4612 
4613                 return (USB_SUCCESS);
4614         }
4615         if (dir == USB_AUDIO_PLAY) {
4616                 engp = &(uacp->engines[0]);
4617         } else {
4618                 engp = &(uacp->engines[1]);
4619         }
4620 
4621         cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL);
4622 
4623         mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
4624 
4625         mutex_enter(&engp->lock);
4626 
4627         engp->af_eflags =
4628             (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
4629         engp->statep = uacp;
4630 
4631         /* Set the format for the engine */
4632         usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
4633 
4634         /* init the default gain */
4635         defgain = asinfo->acs_default_gain;
4636         if (engp->fmt.ch == 2) {
4637                 engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
4638         } else {
4639                 engp->af_defgain = defgain;
4640         }
4641         engp->streams = asinfo;
4642 
4643         mutex_exit(&engp->lock);
4644 
4645         af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
4646         if (af_engp == NULL) {
4647 
4648                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4649                     "audio_engine_alloc failed");
4650                 goto OUT;
4651         }
4652         ASSERT(engp->af_engp == 0);
4653 
4654         mutex_enter(&engp->lock);
4655         engp->af_engp = af_engp;
4656         mutex_exit(&engp->lock);
4657 
4658         audio_engine_set_private(af_engp, engp);
4659         audio_dev_add_engine(af_devp, af_engp);
4660 
4661         /*
4662          * Set the format for this engine
4663          */
4664         if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
4665                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4666                     "set format failed, dir = %d", dir);
4667                 goto OUT;
4668         }
4669         rv = USB_SUCCESS;
4670 
4671 OUT:
4672         if (rv != USB_SUCCESS)
4673                 usb_ac_rem_eng(uacp, engp);
4674 
4675         return (rv);
4676 }
4677 
4678 
4679 static int
4680 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
4681 {
4682         usb_audio_ctrl_t *ctrlp;
4683         int rv = USB_SUCCESS;
4684         USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4685             "usb_ac_ctrl_set_defaults:begin");
4686 
4687         for (int i = 0; i < CTL_NUM; i++) {
4688                 ctrlp = statep->controls[i];
4689                 if (!ctrlp) {
4690                         continue;
4691                 }
4692                 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4693                         USB_DPRINTF_L2(PRINT_MASK_ATTA,
4694                             statep->usb_ac_log_handle,
4695                             "usb_ac_ctrl_set_defaults:control write failed");
4696                         rv = USB_FAILURE;
4697                 }
4698 
4699         }
4700         USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4701             "usb_ac_ctrl_set_defaults:end");
4702         return (rv);
4703 }
4704 
4705 
4706 static int
4707 usb_ac_ctrl_restore(usb_ac_state_t *statep)
4708 {
4709         usb_audio_ctrl_t *ctrlp;
4710         int rv = USB_SUCCESS;
4711 
4712         for (int i = 0; i < CTL_NUM; i++) {
4713                 ctrlp = statep->controls[i];
4714                 if (ctrlp) {
4715                         USB_DPRINTF_L3(PRINT_MASK_ATTA,
4716                             statep->usb_ac_log_handle,
4717                             "usb_ac_ctrl_restore:i = %d", i);
4718                         if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4719                                 rv = USB_FAILURE;
4720                         }
4721                 }
4722         }
4723         return (rv);
4724 }
4725 
4726 
4727 
4728 
4729 /*
4730  * moves data between driver buffer and framework/shim buffer
4731  */
4732 static void
4733 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
4734 {
4735         size_t cpsz = sz;
4736         caddr_t *src, *dst;
4737 
4738         if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
4739                 src = &engp->bufpos;
4740                 dst = (caddr_t *)&buf;
4741         } else {
4742                 src = (caddr_t *)&buf;
4743                 dst = &engp->bufpos;
4744         }
4745 
4746         /*
4747          * Wrap.  If sz is exactly the remainder of the buffer
4748          * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
4749          * the second memcpy() should have no effect, with bufpos updated
4750          * to the head of the buffer.
4751          */
4752         if (engp->bufpos + sz >= engp->bufendp) {
4753                 cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
4754                 (void) memcpy(*dst, *src, cpsz);
4755 
4756 
4757                 buf = (caddr_t)buf + cpsz;
4758                 engp->bufpos = engp->bufp;
4759                 cpsz = sz - cpsz;
4760         }
4761 
4762         if (cpsz) {
4763                 (void) memcpy(*dst, *src, cpsz);
4764 
4765 
4766                 engp->bufpos += cpsz;
4767         }
4768         engp->bufio_count++;
4769 }
4770 
4771 
4772 /*
4773  * control read callback
4774  */
4775 static int
4776 usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
4777 {
4778         usb_audio_ctrl_t *ctrlp = arg;
4779 
4780         mutex_enter(&ctrlp->ctrl_mutex);
4781         *cvalp = ctrlp->cval;
4782         mutex_exit(&ctrlp->ctrl_mutex);
4783 
4784         return (0);
4785 }
4786 
4787 
4788 /*
4789  * stereo level control callback
4790  */
4791 static int
4792 usb_audio_write_stero_rec(void *arg, uint64_t cval)
4793 {
4794         usb_audio_ctrl_t *ctrlp = arg;
4795         usb_ac_state_t *statep = ctrlp->statep;
4796         int rv = EIO;
4797         int left, right;
4798         uint_t count = 0;
4799 
4800 
4801         left = AUDIO_CTRL_STEREO_LEFT(cval);
4802         right = AUDIO_CTRL_STEREO_RIGHT(cval);
4803 
4804         if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4805             right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4806 
4807                 return (EINVAL);
4808         }
4809 
4810         mutex_enter(&ctrlp->ctrl_mutex);
4811         ctrlp->cval = cval;
4812         mutex_exit(&ctrlp->ctrl_mutex);
4813 
4814         mutex_enter(&statep->usb_ac_mutex);
4815         (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4816             USB_AUDIO_FEATURE_UNIT, 1,
4817             USB_AUDIO_VOLUME_CONTROL,
4818             USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4819 
4820         (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4821             USB_AUDIO_FEATURE_UNIT, 2,
4822             USB_AUDIO_VOLUME_CONTROL,
4823             USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4824         rv = 0;
4825 
4826 done:
4827         mutex_exit(&statep->usb_ac_mutex);
4828         return (rv);
4829 }
4830 
4831 static int
4832 usb_audio_write_ster_vol(void *arg, uint64_t cval)
4833 {
4834         usb_audio_ctrl_t *ctrlp = arg;
4835         usb_ac_state_t *statep = ctrlp->statep;
4836         int rv = EIO;
4837         int left, right;
4838         uint_t count = 0;
4839 
4840         left = AUDIO_CTRL_STEREO_LEFT(cval);
4841         right = AUDIO_CTRL_STEREO_RIGHT(cval);
4842 
4843         if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4844             right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4845                 return (EINVAL);
4846         }
4847 
4848         mutex_enter(&ctrlp->ctrl_mutex);
4849         ctrlp->cval = cval;
4850         mutex_exit(&ctrlp->ctrl_mutex);
4851 
4852 
4853         mutex_enter(&statep->usb_ac_mutex);
4854         (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4855             USB_AUDIO_FEATURE_UNIT, 1,
4856             USB_AUDIO_VOLUME_CONTROL,
4857             USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4858 
4859         (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4860             USB_AUDIO_FEATURE_UNIT, 2,
4861             USB_AUDIO_VOLUME_CONTROL,
4862             USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4863         rv = 0;
4864 
4865 OUT:
4866         mutex_exit(&statep->usb_ac_mutex);
4867         return (rv);
4868 }
4869 
4870 
4871 /*
4872  * mono level control callback
4873  */
4874 static int
4875 usb_audio_write_mono_vol(void *arg, uint64_t cval)
4876 {
4877         usb_audio_ctrl_t *ctrlp = arg;
4878         usb_ac_state_t *statep = ctrlp->statep;
4879         int rv = EIO;
4880         int gain;
4881 
4882         uint_t count = 0;
4883 
4884         if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4885                 return (EINVAL);
4886         }
4887 
4888         mutex_enter(&ctrlp->ctrl_mutex);
4889         ctrlp->cval = cval;
4890         mutex_exit(&ctrlp->ctrl_mutex);
4891 
4892         gain = (int)(cval);
4893 
4894         mutex_enter(&statep->usb_ac_mutex);
4895         (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4896             USB_AUDIO_FEATURE_UNIT, 1,
4897             USB_AUDIO_VOLUME_CONTROL,
4898             USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4899 
4900         rv = 0;
4901 OUT:
4902         mutex_exit(&statep->usb_ac_mutex);
4903 
4904         return (rv);
4905 }
4906 
4907 
4908 /*
4909  * mono level control callback
4910  */
4911 static int
4912 usb_audio_write_monitor_gain(void *arg, uint64_t cval)
4913 {
4914         usb_audio_ctrl_t *ctrlp = arg;
4915         usb_ac_state_t *statep = ctrlp->statep;
4916         int rv = EIO;
4917         int gain;
4918         uint_t count = 0;
4919 
4920         if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4921 
4922                 return (EINVAL);
4923         }
4924 
4925         mutex_enter(&ctrlp->ctrl_mutex);
4926         ctrlp->cval = cval;
4927         mutex_exit(&ctrlp->ctrl_mutex);
4928 
4929         gain = (int)(cval);
4930 
4931         mutex_enter(&statep->usb_ac_mutex);
4932         (void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
4933             USB_AUDIO_INPUT_TERMINAL, 1,
4934             USB_AUDIO_VOLUME_CONTROL,
4935             USB_AC_FIND_ALL, &count, gain,
4936             usb_ac_set_monitor_gain);
4937 
4938         rv = 0;
4939 OUT:
4940         mutex_exit(&statep->usb_ac_mutex);
4941         return (rv);
4942 }
4943 
4944 static int
4945 usb_audio_write_mono_rec(void *arg, uint64_t cval)
4946 {
4947         usb_audio_ctrl_t *ctrlp = arg;
4948         usb_ac_state_t *statep = ctrlp->statep;
4949         int rv = EIO;
4950         int gain;
4951 
4952         uint_t count = 0;
4953 
4954         if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4955 
4956                 return (EINVAL);
4957         }
4958 
4959         mutex_enter(&ctrlp->ctrl_mutex);
4960         ctrlp->cval = cval;
4961         mutex_exit(&ctrlp->ctrl_mutex);
4962 
4963         gain = (int)(cval);
4964 
4965         mutex_enter(&statep->usb_ac_mutex);
4966         (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4967             USB_AUDIO_FEATURE_UNIT, 1,
4968             USB_AUDIO_VOLUME_CONTROL,
4969             USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4970 
4971         rv = 0;
4972 
4973         mutex_exit(&statep->usb_ac_mutex);
4974         return (rv);
4975 }
4976 
4977 static int
4978 usb_audio_write_mic_boost(void *arg, uint64_t cval)
4979 {
4980         usb_audio_ctrl_t *ctrlp = arg;
4981 
4982         mutex_enter(&ctrlp->ctrl_mutex);
4983         ctrlp->cval = cval;
4984         mutex_exit(&ctrlp->ctrl_mutex);
4985         /* do nothing here */
4986         return (0);
4987 }
4988 
4989 static int
4990 usb_audio_write_rec_src(void *arg, uint64_t cval)
4991 {
4992         usb_audio_ctrl_t *ctrlp = arg;
4993         usb_ac_state_t *statep = ctrlp->statep;
4994         int rv = 0;
4995 
4996         if (cval & ~(statep->usb_ac_input_ports))
4997                 return (EINVAL);
4998 
4999         mutex_enter(&ctrlp->ctrl_mutex);
5000         ctrlp->cval = cval;
5001         mutex_exit(&ctrlp->ctrl_mutex);
5002 
5003         mutex_enter(&statep->usb_ac_mutex);
5004         if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
5005 
5006                 USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
5007                     "usb_audio_write_rec_src: failed");
5008                 rv = EINVAL;
5009         }
5010         mutex_exit(&statep->usb_ac_mutex);
5011         rv = 0;
5012 
5013 OUT:
5014         return (rv);
5015 
5016 }
5017 
5018 
5019 int
5020 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
5021 {
5022         short   muteval;
5023         int     rval;
5024 
5025         uint_t count;
5026         muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
5027         count = 0;
5028         /* only support AUDIO_PLAY */
5029 
5030         mutex_enter(&statep->usb_ac_mutex);
5031         (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
5032             USB_AUDIO_FEATURE_UNIT, 0,
5033             USB_AUDIO_MUTE_CONTROL,
5034             USB_AC_FIND_ALL, &count, muteval,
5035             usb_ac_set_mute);
5036         mutex_exit(&statep->usb_ac_mutex);
5037 
5038         rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
5039 
5040         return (rval);
5041 }
5042 
5043 
5044 /*
5045  * port selection control callback
5046  */
5047 /*
5048  * audio control registration related routines
5049  */
5050 
5051 static usb_audio_ctrl_t *
5052 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
5053 {
5054         audio_ctrl_desc_t       desc;
5055         audio_ctrl_wr_t         fn;
5056         usb_audio_ctrl_t        *pc;
5057 
5058         pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
5059 
5060         mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
5061 
5062         bzero(&desc, sizeof (desc));
5063 
5064         switch (num) {
5065         case CTL_VOLUME_MONO:
5066                 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5067                 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5068                 desc.acd_minvalue = 0;
5069                 desc.acd_maxvalue = AF_MAX_GAIN;
5070                 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5071                     | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5072                 fn = usb_audio_write_mono_vol;
5073                 break;
5074 
5075         case CTL_VOLUME_STERO:
5076                 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5077                 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5078                 desc.acd_minvalue = 0;
5079                 desc.acd_maxvalue = AF_MAX_GAIN;
5080                 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5081                     | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5082                 fn = usb_audio_write_ster_vol;
5083 
5084                 break;
5085 
5086         case CTL_REC_MONO:
5087                 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5088                 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5089                 desc.acd_minvalue = 0;
5090                 desc.acd_maxvalue = AF_MAX_GAIN;
5091                 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5092                     | AUDIO_CTRL_FLAG_RW;
5093                 fn = usb_audio_write_mono_rec;
5094                 break;
5095         case CTL_REC_STERO:
5096 
5097                 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5098                 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5099                 desc.acd_minvalue = 0;
5100                 desc.acd_maxvalue = AF_MAX_GAIN;
5101                 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5102                     | AUDIO_CTRL_FLAG_RW;
5103                 fn = usb_audio_write_stero_rec;
5104                 break;
5105 
5106         case CTL_MONITOR_GAIN:
5107 
5108                 desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
5109                 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5110                 desc.acd_minvalue = 0;
5111                 desc.acd_maxvalue = AF_MAX_GAIN;
5112                 desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
5113                     |AUDIO_CTRL_FLAG_RW;
5114                 fn = usb_audio_write_monitor_gain;
5115                 break;
5116 
5117         case CTL_MIC_BOOST:
5118 
5119                 desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
5120                 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
5121                 desc.acd_minvalue = 0;
5122                 desc.acd_maxvalue = 1;
5123                 desc.acd_flags = AUDIO_CTRL_FLAG_RW;
5124                 fn = usb_audio_write_mic_boost;
5125                 break;
5126         case CTL_REC_SRC:
5127 
5128                 desc.acd_name = AUDIO_CTRL_ID_RECSRC;
5129                 desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
5130                 desc.acd_minvalue = statep->usb_ac_input_ports;
5131                 desc.acd_maxvalue = statep->usb_ac_input_ports;
5132                 desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
5133                 for (int i = 0; usb_audio_dtypes[i]; i++) {
5134                         desc.acd_enum[i] = usb_audio_dtypes[i];
5135                 }
5136 
5137                 fn = usb_audio_write_rec_src;
5138                 break;
5139 
5140 
5141 
5142         default:
5143 
5144                 break;
5145         }
5146 
5147         mutex_enter(&pc->ctrl_mutex);
5148 
5149         pc->statep = statep;
5150         pc->cval = val;
5151         pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
5152             usb_audio_ctrl_read, fn, pc);
5153 
5154         mutex_exit(&pc->ctrl_mutex);
5155 
5156         mutex_enter(&statep->usb_ac_mutex);
5157         statep->controls[num] = pc;
5158         mutex_exit(&statep->usb_ac_mutex);
5159 
5160 
5161         return (pc);
5162 }
5163 
5164 
5165 static void
5166 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
5167 {
5168         kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
5169 }
5170 
5171 static void
5172 usb_ac_rem_controls(usb_ac_state_t *statep)
5173 {
5174         usb_audio_ctrl_t *ctrlp;
5175 
5176         for (int i = 0; i < CTL_NUM; i++) {
5177                 ctrlp = statep->controls[i];
5178                 if (ctrlp) {
5179                         if (ctrlp->af_ctrlp != NULL)
5180                                 audio_dev_del_control(ctrlp->af_ctrlp);
5181 
5182                         usb_audio_ctrl_free(ctrlp);
5183                         mutex_enter(&statep->usb_ac_mutex);
5184                         statep->controls[i] = NULL;
5185                         mutex_exit(&statep->usb_ac_mutex);
5186                 }
5187         }
5188 
5189 }
5190 
5191 
5192 static int
5193 usb_ac_add_controls(usb_ac_state_t *statep)
5194 {
5195         int rv = USB_FAILURE;
5196         usb_audio_format_t *format;
5197 
5198 
5199         if (statep->engines[0].af_engp) {
5200                 /* Init controls for play format */
5201                 format = &(statep->engines[0].fmt);
5202                 if (format->ch == 2) {
5203                         (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
5204                             statep->engines[0].af_defgain);
5205                 } else {
5206                         (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
5207                             statep->engines[0].af_defgain);
5208                 }
5209 
5210         }
5211 
5212         /* Init controls for rec format */
5213         if (statep->engines[1].af_engp) {
5214                 format = &(statep->engines[1].fmt);
5215                 if (format->ch == 2) {
5216                         (void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
5217                             statep->engines[1].af_defgain);
5218                 } else {
5219                         (void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
5220                             statep->engines[1].af_defgain);
5221                 }
5222 
5223                 /* Add monitor control */
5224                 {
5225                         (void) usb_audio_ctrl_alloc(statep,
5226                             CTL_MONITOR_GAIN, 0);
5227                 }
5228 
5229                 /* Add ports control */
5230                 {
5231                         (void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
5232                             statep->usb_ac_input_ports);
5233                 }
5234 
5235         }
5236 
5237 
5238         rv = USB_SUCCESS;
5239 
5240 OUT:
5241         if (rv != USB_SUCCESS)
5242                 usb_ac_rem_controls(statep);
5243         return (rv);
5244 }
5245 
5246 
5247 
5248 
5249 
5250 /*ARGSUSED*/
5251 static int
5252 usb_audio_unregister(usb_ac_state_t *statep)
5253 {
5254         int i;
5255 
5256         if (statep == NULL)
5257                 return (USB_SUCCESS);
5258 
5259         if (statep->usb_ac_audio_dev == NULL)
5260                 return (USB_SUCCESS);
5261 
5262         if ((statep->flags & AF_REGISTERED) &&
5263             audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
5264                 return (USB_FAILURE);
5265         }
5266         mutex_enter(&statep->usb_ac_mutex);
5267         statep->flags &= ~AF_REGISTERED;
5268         mutex_exit(&statep->usb_ac_mutex);
5269 
5270         for (i = 0; i < USB_AC_ENG_MAX; i++)
5271                 usb_ac_rem_eng(statep, &statep->engines[i]);
5272 
5273         usb_ac_rem_controls(statep);
5274 
5275         audio_dev_free(statep->usb_ac_audio_dev);
5276 
5277         mutex_enter(&statep->usb_ac_mutex);
5278         statep->usb_ac_audio_dev = NULL;
5279         mutex_exit(&statep->usb_ac_mutex);
5280 
5281         return (USB_SUCCESS);
5282 }
5283 
5284 
5285 static int
5286 usb_audio_register(usb_ac_state_t *statep) {
5287         audio_dev_t *af_devp;
5288         int rv = USB_FAILURE;
5289         int n;
5290 
5291         af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
5292         audio_dev_set_description(af_devp,  "USB Audio");
5293         audio_dev_set_version(af_devp, "1.0");
5294 
5295         mutex_enter(&statep->usb_ac_mutex);
5296         statep->usb_ac_audio_dev = af_devp;
5297         mutex_exit(&statep->usb_ac_mutex);
5298 
5299 
5300         for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
5301                 if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
5302                     != USB_SUCCESS) {
5303                         USB_DPRINTF_L2(PRINT_MASK_ATTA,
5304                             statep->usb_ac_log_handle,
5305                             "usb_audio_register: add engine n =%d failed", n);
5306                         goto OUT;
5307                 }
5308         }
5309 
5310 
5311         if (usb_ac_add_controls(statep) != USB_SUCCESS) {
5312                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5313                     "usb_audio_register: add controls failed");
5314                 goto OUT;
5315         }
5316 
5317         if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
5318                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5319                     "usb_audio_register: set defaults failed");
5320                 goto OUT;
5321         }
5322 
5323         if (audio_dev_register(af_devp) != DDI_SUCCESS) {
5324                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5325                     "audio_dev_register() failed");
5326                 goto OUT;
5327         }
5328         mutex_enter(&statep->usb_ac_mutex);
5329         statep->flags |= AF_REGISTERED;
5330         mutex_exit(&statep->usb_ac_mutex);
5331 
5332         rv = USB_SUCCESS;
5333 
5334 OUT:
5335         if (rv != USB_SUCCESS) {
5336                 (void) usb_audio_unregister(statep);
5337         }
5338         return (rv);
5339 }
5340 
5341 
5342 int
5343 usb_ac_get_audio(void *handle, void *buf, int samples)
5344 {
5345         usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5346         usb_audio_eng_t *engp = &(statep->engines[0]);
5347         unsigned reqframes = samples >> engp->frsmshift;
5348         unsigned frames;
5349         unsigned i;
5350         size_t sz;
5351         caddr_t bp = buf;
5352 
5353         mutex_enter(&engp->lock);
5354         if (!engp->started) {
5355                 mutex_exit(&engp->lock);
5356 
5357                 return (0);
5358         }
5359         engp->busy = B_TRUE;
5360         mutex_exit(&engp->lock);
5361 
5362         /* break requests from the driver into fragment sized chunks */
5363         for (i = 0; i < reqframes; i += frames) {
5364 
5365                 mutex_enter(&engp->lock);
5366                 frames = reqframes - i;
5367                 if (frames > engp->fragfr)
5368                         frames = engp->fragfr;
5369 
5370                 sz = (frames << engp->frsmshift) << engp->smszshift;
5371 
5372                 /* must move data before updating framework */
5373                 usb_eng_bufio(engp, bp, sz);
5374                 engp->frames += frames;
5375                 bp += sz;
5376 
5377                 mutex_exit(&engp->lock);
5378         }
5379 
5380         mutex_enter(&engp->lock);
5381         engp->io_count++;
5382         engp->busy = B_FALSE;
5383         cv_signal(&engp->usb_audio_cv);
5384         mutex_exit(&engp->lock);
5385 
5386         return (samples);
5387 }
5388 
5389 
5390 
5391 void
5392 usb_ac_send_audio(void *handle, void *buf, int samples)
5393 {
5394         usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5395         usb_audio_eng_t *engp = &(statep->engines[1]);
5396         unsigned reqframes = samples >> engp->frsmshift;
5397         unsigned frames;
5398         unsigned i;
5399         size_t sz;
5400         caddr_t bp = buf;
5401 
5402         mutex_enter(&engp->lock);
5403 
5404         if (!engp->started) {
5405 
5406                 mutex_exit(&engp->lock);
5407                 return;
5408         }
5409         engp->busy = B_TRUE;
5410         mutex_exit(&engp->lock);
5411 
5412         /* break requests from the driver into fragment sized chunks */
5413         for (i = 0; i < reqframes; i += frames) {
5414                 mutex_enter(&engp->lock);
5415 
5416                 frames = reqframes - i;
5417                 if (frames > engp->fragfr)
5418                         frames = engp->fragfr;
5419 
5420                 sz = (frames << engp->frsmshift) << engp->smszshift;
5421 
5422                 /* must move data before updating framework */
5423                 usb_eng_bufio(engp, bp, sz);
5424                 engp->frames += frames;
5425                 bp += sz;
5426 
5427                 mutex_exit(&engp->lock);
5428         }
5429 
5430         mutex_enter(&engp->lock);
5431         engp->io_count++;
5432         engp->busy = B_FALSE;
5433         cv_signal(&engp->usb_audio_cv);
5434         mutex_exit(&engp->lock);
5435 }
5436 
5437 
5438 /*
5439  * **************************************************************************
5440  * audio framework engine callbacks
5441  */
5442 static int
5443 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
5444 {
5445         usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5446         usb_ac_state_t *statep = engp->statep;
5447         int rv = EIO;
5448 
5449         _NOTE(ARGUNUSED(flag));
5450 
5451         if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
5452 
5453                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5454                     "usb_ac_open() failed");
5455                 return (EIO);
5456         }
5457 
5458         mutex_enter(&engp->lock);
5459 
5460         engp->intrate =  150;
5461         engp->sampsz = engp->fmt.prec / 8;
5462         engp->framesz = engp->sampsz * engp->fmt.ch;
5463 
5464         engp->frsmshift = engp->fmt.ch / 2;
5465         engp->smszshift = engp->sampsz / 2;
5466 
5467         /*
5468          * In order to match the requested number of samples per interrupt
5469          * from SADA drivers when computing the fragment size,
5470          * we need to first truncate the floating point result from
5471          *      sample rate * channels / intr rate
5472          * then adjust up to an even number, before multiplying it
5473          * with the sample size
5474          */
5475         engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
5476         if (engp->fragsz & 1)
5477                 engp->fragsz++;
5478         engp->fragsz *= engp->sampsz;
5479         engp->fragfr = engp->fragsz / engp->framesz;
5480 
5481         engp->nfrags = 10;
5482         engp->bufsz = engp->fragsz * engp->nfrags;
5483 
5484         engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
5485         engp->bufpos = engp->bufp;
5486         engp->bufendp = engp->bufp + engp->bufsz;
5487         engp->frames = 0;
5488         engp->io_count = 0;
5489         engp->bufio_count = 0;
5490         engp->started = B_FALSE;
5491         engp->busy = B_FALSE;
5492 
5493         *nframesp = engp->nfrags * engp->fragfr;
5494         *bufp = engp->bufp;
5495 
5496         mutex_exit(&engp->lock);
5497 
5498         if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
5499                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5500                     "device setup failed");
5501                 goto OUT;
5502         }
5503 
5504 
5505 
5506         mutex_enter(&statep->usb_ac_mutex);
5507         statep->flags |= AD_SETUP;
5508         mutex_exit(&statep->usb_ac_mutex);
5509 
5510         rv = 0;
5511 
5512 
5513 OUT:
5514         if (rv != 0)
5515                 usb_engine_close(arg);
5516 
5517         return (rv);
5518 }
5519 
5520 
5521 static void
5522 usb_engine_close(void *arg)
5523 {
5524         usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5525         usb_ac_state_t *statep = engp->statep;
5526 
5527         mutex_enter(&engp->lock);
5528         while (engp->busy) {
5529                 cv_wait(&engp->usb_audio_cv, &engp->lock);
5530         }
5531 
5532         mutex_exit(&engp->lock);
5533 
5534         if (statep->flags & AD_SETUP) {
5535                 usb_ac_teardown(statep, engp);
5536                 mutex_enter(&statep->usb_ac_mutex);
5537                 statep->flags &= ~AD_SETUP;
5538                 mutex_exit(&statep->usb_ac_mutex);
5539         }
5540         mutex_enter(&engp->lock);
5541 
5542         if (engp->bufp != NULL) {
5543                 kmem_free(engp->bufp, engp->bufsz);
5544                 engp->bufp = NULL;
5545                 engp->bufpos = NULL;
5546                 engp->bufendp = NULL;
5547         }
5548 
5549         mutex_exit(&engp->lock);
5550 
5551         usb_ac_close(statep->usb_ac_dip);
5552 }
5553 
5554 
5555 
5556 static int
5557 usb_engine_start(void *arg)
5558 {
5559         usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5560         int rv = 0;
5561         int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
5562 
5563         mutex_enter(&engp->lock);
5564         engp->started = B_TRUE;
5565         mutex_exit(&engp->lock);
5566 
5567         usb_ac_state_t *statep = engp->statep;
5568 
5569         start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5570             usb_ac_start_play : usb_ac_start_record;
5571 
5572         if ((*start)(statep, engp) != USB_SUCCESS) {
5573                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5574                     "failed to start %d engine", engp->af_eflags);
5575                 rv = EIO;
5576         }
5577 
5578 
5579         return (rv);
5580 }
5581 
5582 
5583 static void
5584 usb_engine_stop(void *arg)
5585 {
5586         usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5587 
5588         mutex_enter(&engp->lock);
5589         engp->started = B_FALSE;
5590         mutex_exit(&engp->lock);
5591 
5592         usb_ac_state_t *statep = engp->statep;
5593         void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
5594 
5595         stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5596             usb_ac_stop_play : usb_ac_stop_record;
5597 
5598         (*stop)(statep, engp);
5599 }
5600 
5601 
5602 static uint64_t
5603 usb_engine_count(void *arg)
5604 {
5605         usb_audio_eng_t *engp = arg;
5606         uint64_t        val;
5607 
5608         mutex_enter(&engp->lock);
5609         val = engp->frames;
5610         mutex_exit(&engp->lock);
5611 
5612         return (val);
5613 }
5614 
5615 
5616 static int
5617 usb_engine_format(void *arg)
5618 {
5619         usb_audio_eng_t *engp = arg;
5620 
5621         switch (engp->fmt.enc) {
5622                 case USB_AUDIO_FORMAT_TYPE1_MULAW:
5623                         return (AUDIO_FORMAT_ULAW);
5624                 case USB_AUDIO_FORMAT_TYPE1_ALAW:
5625                         return (AUDIO_FORMAT_ALAW);
5626                 case USB_AUDIO_FORMAT_TYPE1_PCM8:
5627                         return (AUDIO_FORMAT_U8);
5628 
5629                 case USB_AUDIO_FORMAT_TYPE1_PCM:
5630                         break;
5631                 default:
5632                         return (AUDIO_FORMAT_NONE);
5633         }
5634 
5635         switch (engp->fmt.prec) {
5636                 case USB_AUDIO_PRECISION_8:
5637                         return (AUDIO_FORMAT_S8);
5638                 case USB_AUDIO_PRECISION_16:
5639                         return (AUDIO_FORMAT_S16_LE);
5640                 case USB_AUDIO_PRECISION_24:
5641                         return (AUDIO_FORMAT_S24_LE);
5642                 case USB_AUDIO_PRECISION_32:
5643                         return (AUDIO_FORMAT_S32_LE);
5644                 default:
5645                         break;
5646         }
5647         return (AUDIO_FORMAT_NONE);
5648 
5649 
5650 }
5651 
5652 static int
5653 usb_engine_channels(void *arg)
5654 {
5655         usb_audio_eng_t *engp = arg;
5656 
5657         return (engp->fmt.ch);
5658 }
5659 
5660 
5661 static int
5662 usb_engine_rate(void *arg)
5663 {
5664         usb_audio_eng_t *engp = arg;
5665 
5666         return (engp->fmt.sr);
5667 }
5668 
5669 
5670 /*ARGSUSED*/
5671 static void
5672 usb_engine_sync(void *arg, unsigned nframes)
5673 {
5674         /* Do nothing */
5675 }
5676 
5677 
5678 static unsigned
5679 usb_engine_qlen(void *arg)
5680 {
5681         usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5682 
5683         return (engp->fragfr);
5684 }
5685 
5686 /*
5687  * **************************************************************************
5688  * interfaces used by USB audio
5689  */
5690 
5691 /*ARGSUSED*/
5692 static int
5693 usb_change_phy_vol(usb_ac_state_t *statep, int value)
5694 {
5695         usb_audio_ctrl_t *ctrlp;
5696         uint64_t cval = 0;
5697         int64_t left, right, delta = 0;
5698 
5699         ctrlp = statep->controls[CTL_VOLUME_STERO];
5700 
5701         ASSERT(value != 0);
5702 
5703         delta = (value < 0)?-1:1;
5704 
5705         left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
5706         right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
5707 
5708         if (left > AF_MAX_GAIN)
5709                 left = AF_MAX_GAIN;
5710         if (right > AF_MAX_GAIN)
5711                 right = AF_MAX_GAIN;
5712 
5713         if (left < AF_MIN_GAIN)
5714                 left = AF_MIN_GAIN;
5715         if (right < AF_MIN_GAIN)
5716                 right = AF_MIN_GAIN;
5717 
5718         cval = AUDIO_CTRL_STEREO_VAL(left, right);
5719 
5720         if (audio_control_write(ctrlp->af_ctrlp, cval)) {
5721                 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5722                     "updateing control  to value 0x%llx by driver failed",
5723                     (long long unsigned)cval);
5724                 return (USB_FAILURE);
5725         }
5726         return (USB_SUCCESS);
5727 }