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