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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * USBA: Solaris USB Architecture support
  28  *
  29  * This module builds a tree of parsed USB standard descriptors and unparsed
  30  * Class/Vendor specific (C/V) descriptors.  Routines are grouped into three
  31  * groups: those which build the tree, those which take it down, and those which
  32  * dump it.
  33  *
  34  * The tree built hangs off of the dev_cfg field of the usb_client_dev_data_t
  35  * structure returned by usb_get_dev_data().  The tree consists of different
  36  * kinds of tree nodes (usb_xxx_data_t) each containing a standard USB
  37  * descriptor (usb_xxx_descr_t) and pointers to arrays of other nodes.
  38  *
  39  * Arrays are dynamically sized, as the descriptors coming from the device may
  40  * lie, but the number of descriptors from the device is a more reliable
  41  * indicator of configuration.  This makes the code more robust.  After the raw
  42  * descriptor data has been parsed into a non-sparse tree, the tree is ordered
  43  * and made sparse with a bin-sort style algorithm.
  44  *
  45  * dev_cfg is an array of configuration tree nodes. Each contains space for one
  46  * parsed standard USB configuration descriptor, a pointer to an array of c/v
  47  * tree nodes and a pointer to an array of interface tree nodes.
  48  *
  49  * Each interface tree node represents a group of interface descriptors, called
  50  * alternates, with the same interface number.  Thus, each interface tree node
  51  * has a pointer to an array of alternate-interface tree nodes each containing a
  52  * standard USB interface descriptor. Alternate-interface tree nodes also
  53  * contain a pointer to an array of c/v tree nodes and a pointer to an array of
  54  * endpoint tree nodes.
  55  *
  56  * Endpoint tree nodes contain a standard endpoint descriptor, plus a pointer to
  57  * an array of c/v tree nodes.
  58  *
  59  * Each array in the tree contains elements ranging from 0 to the largest key
  60  * value of it's elements.  Endpoints are a special case.  The direction bit is
  61  * right shifted over three unused bits before the index is determined, leaving
  62  * a range of 0..31 instead of a sparsely-populated range of 0..255.
  63  *
  64  * The indices of tree elements coincide with their USB key values.  For
  65  * example, standard USB devices have no configuration 0;  if they have one
  66  * configuration it is #1.  dev_cfg[0] is zeroed out;  dev_cfg[1] is the root
  67  * of configuration #1.
  68  *
  69  * The idea here is for a driver to be able to parse the tree to easily find a
  70  * desired descriptor.  For example, the interval of endpoint 2, alternate 3,
  71  * interface 1, configuration 1 would be:
  72  *  dv->dev_cfg[1].cfg_if[1].if_alt[3].altif_ep[2].ep_descr.bInterval
  73  *
  74  * How the tree is built:
  75  *
  76  * usb_build_descr_tree() is responsible for the whole process.
  77  *
  78  * Next, usba_build_descr_tree() coordinates parsing this byte stream,
  79  * descriptor by descriptor.  usba_build_descr_tree() calls the appropriate
  80  * usba_process_xx_descr() function to interpret and install each descriptor in
  81  * the tree, based on the descriptor's type.  When done with this phase, a
  82  * non-sparse tree exists containing tree nodes with descriptors in the order
  83  * they were found in the raw data.
  84  *
  85  * All levels of the tree, except alternates, remain non-sparse.  Alternates are
  86  * moved, possibly, within their array, so that descriptors are indexed by their
  87  * alternate ID.
  88  *
  89  * The usba_reg_state_t structure maintains state of the tree-building process,
  90  * helping coordinate all routines involved.
  91  */
  92 #define USBA_FRAMEWORK
  93 #include <sys/usb/usba.h>
  94 #include <sys/usb/usba/usba_impl.h>
  95 #include <sys/usb/usba/usba_private.h>
  96 #include <sys/usb/usba/hcdi_impl.h>
  97 #include <sys/usb/hubd/hub.h>
  98 
  99 #include <sys/usb/usba/usbai_register_impl.h>
 100 
 101 /*
 102  * Header needed for use by this module only.
 103  * However, function may be used in V0.8 drivers so needs to be global.
 104  */
 105 int usb_log_descr_tree(usb_client_dev_data_t *, usb_log_handle_t,
 106                                 uint_t, uint_t);
 107 
 108 /* Debug stuff */
 109 usb_log_handle_t        usbai_reg_log_handle;
 110 uint_t                  usbai_register_errlevel = USB_LOG_L2;
 111 uint_t                  usbai_register_dump_errlevel = USB_LOG_L2;
 112 uint_t                  usbai_register_errmask = (uint_t)-1;
 113 
 114 /* Function prototypes */
 115 static int usba_build_bos(usba_device_t *, usb_client_dev_data_t *);
 116 static int usba_build_descr_tree(dev_info_t *, usba_device_t *,
 117                                 usb_client_dev_data_t *);
 118 static void usba_process_cfg_descr(usba_reg_state_t *);
 119 static int usba_process_if_descr(usba_reg_state_t *, boolean_t *);
 120 static int usba_process_ep_descr(usba_reg_state_t *);
 121 static int usba_process_cv_descr(usba_reg_state_t *);
 122 static int usba_process_ep_comp_descr(usba_reg_state_t *);
 123 static int usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
 124     usba_reg_state_t *state);
 125 static void* usba_kmem_realloc(void *, int, int);
 126 static void usba_augment_array(void **, uint_t, uint_t);
 127 static void usba_make_alts_sparse(usb_alt_if_data_t **, uint_t *);
 128 
 129 static void usba_order_tree(usba_reg_state_t *);
 130 
 131 static void usba_free_if_array(usb_if_data_t *, uint_t);
 132 static void usba_free_ep_array(usb_ep_data_t *, uint_t);
 133 static void usba_free_cv_array(usb_cvs_data_t *, uint_t);
 134 
 135 static int usba_dump_descr_tree(dev_info_t *, usb_client_dev_data_t *,
 136                                 usb_log_handle_t, uint_t, uint_t);
 137 static void usba_dump_if(usb_if_data_t *, usb_log_handle_t,
 138                                 uint_t, uint_t, char *);
 139 static void usba_dump_ep(uint_t, usb_ep_data_t *, usb_log_handle_t, uint_t,
 140                                 uint_t, char *);
 141 static void usba_dump_cv(usb_cvs_data_t *, usb_log_handle_t, uint_t, uint_t,
 142                                 char *, int);
 143 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t,
 144                                 uint_t,  uint_t, char *, int);
 145 
 146 /* Framework initialization. */
 147 void
 148 usba_usbai_register_initialization()
 149 {
 150         usbai_reg_log_handle = usb_alloc_log_hdl(NULL, "usbreg",
 151             &usbai_register_errlevel,
 152             &usbai_register_errmask, NULL,
 153             0);
 154 
 155         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 156             "usba_usbai_register_initialization");
 157 }
 158 
 159 
 160 /* Framework destruction. */
 161 void
 162 usba_usbai_register_destroy()
 163 {
 164         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 165             "usba_usbai_register destroy");
 166 
 167         usb_free_log_hdl(usbai_reg_log_handle);
 168 }
 169 
 170 
 171 /*
 172  * usb_client_attach:
 173  *
 174  * Arguments:
 175  *      dip             - pointer to devinfo node of the client
 176  *      version         - USBA registration version number
 177  *      flags           - None used
 178  *
 179  * Return Values:
 180  *      USB_SUCCESS             - attach succeeded
 181  *      USB_INVALID_ARGS        - received null dip
 182  *      USB_INVALID_VERSION     - version argument is incorrect.
 183  *      USB_FAILURE             - other internal failure
 184  */
 185 /*ARGSUSED*/
 186 int
 187 usb_client_attach(dev_info_t *dip, uint_t version, usb_flags_t flags)
 188 {
 189         int rval;
 190         usba_device_t *usba_device;
 191 
 192         if (dip == NULL) {
 193 
 194                 return (USB_INVALID_ARGS);
 195         }
 196 
 197         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 198             "usb_client attach:");
 199 
 200         usba_device = usba_get_usba_device(dip);
 201 
 202         /*
 203          * Allow exact match for legacy (DDK 0.8/9) drivers, or same major
 204          * VERSion and smaller or same minor version for non-legacy drivers.
 205          */
 206         if ((version !=
 207             USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) &&
 208             ((USBA_GET_MAJOR(version) != USBA_MAJOR_VER) ||
 209             (USBA_GET_MINOR(version) > USBA_MINOR_VER))) {
 210                 USB_DPRINTF_L1(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 211                     "Incorrect USB driver version for %s%d: found: %d.%d, "
 212                     "expecting %d.%d",
 213                     ddi_driver_name(dip), ddi_get_instance(dip),
 214                     USBA_GET_MAJOR(version), USBA_GET_MINOR(version),
 215                     USBA_MAJOR_VER, USBA_MINOR_VER);
 216 
 217                 return (USB_INVALID_VERSION);
 218         }
 219 
 220         if (version == USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) {
 221                 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 222                     "Accepting legacy USB driver version %d.%d for %s%d",
 223                     USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER,
 224                     ddi_driver_name(dip), ddi_get_instance(dip));
 225         }
 226 
 227         rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-major",
 228             USBA_GET_MAJOR(version));
 229         if (rval != DDI_PROP_SUCCESS) {
 230 
 231                 return (USB_FAILURE);
 232         }
 233         rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-minor",
 234             USBA_GET_MINOR(version));
 235         if (rval != DDI_PROP_SUCCESS) {
 236 
 237                 return (USB_FAILURE);
 238         }
 239 
 240         mutex_enter(&usba_device->usb_mutex);
 241         if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
 242                 usba_device->usb_client_flags[usba_get_ifno(dip)] |=
 243                     USBA_CLIENT_FLAG_ATTACH;
 244                 usba_device->usb_client_attach_list->dip = dip;
 245         }
 246         mutex_exit(&usba_device->usb_mutex);
 247 
 248         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 249             "usb_client attach: done");
 250 
 251         return (USB_SUCCESS);
 252 }
 253 
 254 
 255 /*
 256  * usb_client_detach:
 257  *      free dev_data is reg != NULL, not much else to do
 258  *
 259  * Arguments:
 260  *      dip             - pointer to devinfo node of the client
 261  *      reg             - return registration data at this address
 262  */
 263 void
 264 usb_client_detach(dev_info_t *dip, usb_client_dev_data_t *reg)
 265 {
 266         usba_device_t *usba_device = usba_get_usba_device(dip);
 267 
 268         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 269             "usb_client_detach:");
 270 
 271         if (dip) {
 272                 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 273                     "Unregistering usb client %s%d: reg=0x%p",
 274                     ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg);
 275 
 276                 usb_free_dev_data(dip, reg);
 277 
 278                 mutex_enter(&usba_device->usb_mutex);
 279                 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
 280                         usba_device->usb_client_flags[usba_get_ifno(dip)] &=
 281                             ~USBA_CLIENT_FLAG_ATTACH;
 282                 }
 283                 mutex_exit(&usba_device->usb_mutex);
 284         }
 285 
 286         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 287             "usb_client_detach done");
 288 }
 289 
 290 
 291 /*
 292  * usb_register_client (deprecated):
 293  *      The client registers with USBA during attach.
 294  */
 295 /*ARGSUSED*/
 296 int
 297 usb_register_client(dev_info_t *dip, uint_t version,
 298     usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level,
 299     usb_flags_t flags)
 300 {
 301         int rval = usb_client_attach(dip, version, flags);
 302 
 303         if (rval == USB_SUCCESS) {
 304                 rval = usb_get_dev_data(dip, reg, parse_level, flags);
 305 
 306                 if (rval != USB_SUCCESS) {
 307                         usb_client_detach(dip, NULL);
 308                 }
 309         }
 310 
 311         return (rval);
 312 }
 313 
 314 
 315 /*
 316  * usb_unregister_client (deprecated):
 317  *      Undo the makings of usb_get_dev_data().  Free memory if allocated.
 318  *
 319  * Arguments:
 320  *      dip     - pointer to devinfo node of the client
 321  *      reg     - pointer to registration data to be freed
 322  */
 323 void
 324 usb_unregister_client(dev_info_t *dip, usb_client_dev_data_t *reg)
 325 {
 326         usb_client_detach(dip, reg);
 327 }
 328 
 329 
 330 /*
 331  * usb_get_dev_data:
 332  *      On completion, the registration data has been initialized.
 333  *      Most data items are straightforward.
 334  *      Among the items returned in the data is the tree of
 335  *      parsed descriptors, in dev_cfg;  the number of configurations parsed,
 336  *      in dev_n_cfg; a pointer to the current configuration in the tree,
 337  *      in dev_curr_cfg; the index of the first valid interface in the
 338  *      tree, in dev_curr_if, and a parse level that accurately reflects what
 339  *      is in the tree, in dev_parse_level.
 340  *
 341  *      This routine sets up directly-initialized fields, and calls
 342  *      usb_build_descr_tree() to parse the raw descriptors and initialize the
 343  *      tree.
 344  *
 345  *      Parse_level determines the extent to which the tree is built.  It has
 346  *      the following values:
 347  *
 348  *      USB_PARSE_LVL_NONE - Build no tree.  dev_n_cfg will return 0, dev_cfg
 349  *                           and dev_curr_cfg will return NULL.
 350  *      USB_PARSE_LVL_IF   - Parse configured interface only, if configuration#
 351  *                           and interface properties are set (as when different
 352  *                           interfaces are viewed by the OS as different device
 353  *                           instances). If an OS device instance is set up to
 354  *                           represent an entire physical device, this works
 355  *                           like USB_PARSE_LVL_ALL.
 356  *      USB_PARSE_LVL_CFG  - Parse entire configuration of configured interface
 357  *                           only.  This is like USB_PARSE_LVL_IF except entire
 358  *                           configuration is returned.
 359  *      USB_PARSE_LVL_ALL  - Parse entire device (all configurations), even
 360  *                           when driver is bound to a single interface of a
 361  *                           single configuration.
 362  *
 363  *      No tree is built for root hubs, regardless of parse_level.
 364  *
 365  * Arguments:
 366  *      dip             - pointer to devinfo node of the client
 367  *      version         - USBA registration version number
 368  *      reg             - return registration data at this address
 369  *      parse_level     - See above
 370  *      flags           - None used
 371  *
 372  * Return Values:
 373  *      USB_SUCCESS             - usb_get_dev_data succeeded
 374  *      USB_INVALID_ARGS        - received null dip or reg argument
 375  *      USB_INVALID_CONTEXT     - called from callback context
 376  *      USB_FAILURE             - bad descriptor info or other internal failure
 377  *
 378  * Note: The non-standard USB descriptors are returned in RAW format.
 379  *      returns initialized registration data.  Most data items are clear.
 380  *      Among the items returned is the tree of parsed descriptors in dev_cfg;
 381  *      and the number of configurations parsed in dev_n_cfg.
 382  *
 383  *      The registration data is not shared. each client receives its own
 384  *      copy.
 385  */
 386 /*ARGSUSED*/
 387 int
 388 usb_get_dev_data(dev_info_t *dip,
 389     usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level,
 390     usb_flags_t flags)
 391 {
 392         usb_client_dev_data_t   *usb_reg = NULL;
 393         char                    *tmpbuf = NULL;
 394         usba_device_t           *usba_device;
 395         int                     rval = USB_SUCCESS;
 396 
 397         if ((dip == NULL) || (reg == NULL)) {
 398 
 399                 return (USB_INVALID_ARGS);
 400         }
 401 
 402         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 403             "usb_get_dev_data: %s%d",
 404             ddi_driver_name(dip), ddi_get_instance(dip));
 405 
 406         *reg = NULL;
 407 
 408         /* did the client attach first? */
 409         if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 410             "driver-major", -1) == -1) {
 411 
 412                 return (USB_INVALID_VERSION);
 413         }
 414         if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 415             "driver-minor", -1) == -1) {
 416 
 417                 return (USB_INVALID_VERSION);
 418         }
 419 
 420         usb_reg = kmem_zalloc(sizeof (usb_client_dev_data_t), KM_SLEEP);
 421         usba_device = usba_get_usba_device(dip);
 422         usb_reg->dev_descr = usba_device->usb_dev_descr;
 423         usb_reg->dev_default_ph = usba_get_dflt_pipe_handle(dip);
 424         if (usb_reg->dev_default_ph == NULL) {
 425                 kmem_free(usb_reg, sizeof (usb_client_dev_data_t));
 426 
 427                 return (USB_FAILURE);
 428         }
 429 
 430         /* get parsed bos for wusb device */
 431         if (usba_device->usb_is_wireless) {
 432                 if ((rval = usba_build_bos(usba_device, usb_reg)) !=
 433                     USB_SUCCESS) {
 434                         kmem_free(usb_reg, sizeof (usb_client_dev_data_t));
 435 
 436                         return (rval);
 437                 }
 438         }
 439 
 440         usb_reg->dev_iblock_cookie = usba_hcdi_get_hcdi(
 441             usba_device->usb_root_hub_dip)->hcdi_soft_iblock_cookie;
 442 
 443         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 444             "cookie = 0x%p", (void *)usb_reg->dev_iblock_cookie);
 445 
 446         tmpbuf = (char *)kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
 447 
 448         if (usba_device->usb_mfg_str != NULL) {
 449                 usb_reg->dev_mfg = kmem_zalloc(
 450                     strlen(usba_device->usb_mfg_str) + 1, KM_SLEEP);
 451                 (void) strcpy(usb_reg->dev_mfg, usba_device->usb_mfg_str);
 452         }
 453 
 454         if (usba_device->usb_product_str != NULL) {
 455                 usb_reg->dev_product = kmem_zalloc(
 456                     strlen(usba_device->usb_product_str) + 1,
 457                     KM_SLEEP);
 458                 (void) strcpy(usb_reg->dev_product,
 459                     usba_device->usb_product_str);
 460         }
 461 
 462         if (usba_device->usb_serialno_str != NULL) {
 463                 usb_reg->dev_serial = kmem_zalloc(
 464                     strlen(usba_device->usb_serialno_str) + 1,
 465                     KM_SLEEP);
 466                 (void) strcpy(usb_reg->dev_serial,
 467                     usba_device->usb_serialno_str);
 468         }
 469 
 470         if ((usb_reg->dev_parse_level = parse_level) == USB_PARSE_LVL_NONE) {
 471                 rval = USB_SUCCESS;
 472 
 473         } else if ((rval = usba_build_descr_tree(dip, usba_device, usb_reg)) !=
 474             USB_SUCCESS) {
 475                 usb_unregister_client(dip, usb_reg);
 476                 usb_reg = NULL;
 477         } else {
 478 
 479                 /* Current tree cfg is always zero if only one cfg in tree. */
 480                 if (usb_reg->dev_n_cfg == 1) {
 481                         usb_reg->dev_curr_cfg = &usb_reg->dev_cfg[0];
 482                 } else {
 483                         mutex_enter(&usba_device->usb_mutex);
 484                         usb_reg->dev_curr_cfg =
 485                             &usb_reg->dev_cfg[usba_device->usb_active_cfg_ndx];
 486                         mutex_exit(&usba_device->usb_mutex);
 487                         ASSERT(usb_reg->dev_curr_cfg != NULL);
 488                         ASSERT(usb_reg->dev_curr_cfg->cfg_descr.bLength ==
 489                             USB_CFG_DESCR_SIZE);
 490                 }
 491 
 492                 /*
 493                  * Keep dev_curr_if at device's single interface only if that
 494                  * particular interface has been explicitly defined by the
 495                  * device.
 496                  */
 497                 usb_reg->dev_curr_if = usba_get_ifno(dip);
 498 #ifdef DEBUG
 499                 (void) usb_log_descr_tree(usb_reg, usbai_reg_log_handle,
 500                     usbai_register_dump_errlevel, (uint_t)-1);
 501 #endif
 502                 /*
 503                  * Fail if interface and configuration of dev_curr_if and
 504                  * dev_curr_cfg don't exist or are invalid.  (Shouldn't happen.)
 505                  * These indices must be reliable for tree traversal.
 506                  */
 507                 if ((usb_reg->dev_curr_cfg->cfg_n_if <= usb_reg->dev_curr_if) ||
 508                     (usb_reg->dev_curr_cfg->cfg_descr.bLength == 0) ||
 509                     (usb_reg->dev_curr_cfg->cfg_if[usb_reg->dev_curr_if].
 510                     if_n_alt == 0)) {
 511                         USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle,
 512                             "usb_get_dev_data: dev_curr_cfg or "
 513                             "dev_curr_if have no descriptors");
 514                         usb_unregister_client(dip, usb_reg);
 515                         usb_reg = NULL;
 516                         rval = USB_FAILURE;
 517                 }
 518         }
 519 
 520         *reg = usb_reg;
 521         kmem_free(tmpbuf, USB_MAXSTRINGLEN);
 522 
 523         if (rval == USB_SUCCESS) {
 524                 usb_client_dev_data_list_t *entry = kmem_zalloc(
 525                     sizeof (*entry), KM_SLEEP);
 526                 mutex_enter(&usba_device->usb_mutex);
 527 
 528                 usba_device->usb_client_flags[usba_get_ifno(dip)] |=
 529                     USBA_CLIENT_FLAG_DEV_DATA;
 530 
 531                 entry->cddl_dip = dip;
 532                 entry->cddl_dev_data = usb_reg;
 533                 entry->cddl_ifno = usba_get_ifno(dip);
 534 
 535                 entry->cddl_next =
 536                     usba_device->usb_client_dev_data_list.cddl_next;
 537                 if (entry->cddl_next) {
 538                         entry->cddl_next->cddl_prev = entry;
 539                 }
 540                 entry->cddl_prev = &usba_device->usb_client_dev_data_list;
 541                 usba_device->usb_client_dev_data_list.cddl_next = entry;
 542 
 543                 mutex_exit(&usba_device->usb_mutex);
 544         }
 545 
 546         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 547             "usb_get_dev_data rval=%d", rval);
 548 
 549         return (rval);
 550 }
 551 
 552 
 553 /*
 554  * usb_free_dev_data
 555  *      undoes what usb_get_dev_data does
 556  *
 557  * Arguments:
 558  *      dip             - pointer to devinfo node of the client
 559  *      reg             - return registration data at this address
 560  */
 561 void
 562 usb_free_dev_data(dev_info_t *dip, usb_client_dev_data_t *reg)
 563 {
 564         if (dip == NULL) {
 565 
 566                 return;
 567         }
 568 
 569         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 570             "usb_free_dev_data %s%d: reg=0x%p",
 571             ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg);
 572 
 573         if (reg != NULL) {
 574                 usba_device_t *usba_device = usba_get_usba_device(dip);
 575                 usb_client_dev_data_list_t *next, *prev, *entry;
 576                 int     matches = 0;
 577 
 578                 if (reg->dev_serial != NULL) {
 579                         kmem_free((char *)reg->dev_serial,
 580                             strlen((char *)reg->dev_serial) + 1);
 581                 }
 582 
 583                 if (reg->dev_product != NULL) {
 584                         kmem_free((char *)reg->dev_product,
 585                             strlen((char *)reg->dev_product) + 1);
 586                 }
 587 
 588                 if (reg->dev_mfg != NULL) {
 589                         kmem_free((char *)reg->dev_mfg,
 590                             strlen((char *)reg->dev_mfg) + 1);
 591                 }
 592 
 593                 /* Free config tree under reg->dev_cfg. */
 594                 if (reg->dev_cfg != NULL) {
 595                         usb_free_descr_tree(dip, reg);
 596                 }
 597 
 598                 if (reg->dev_bos != NULL) {
 599                         kmem_free(reg->dev_bos, sizeof (usb_bos_data_t));
 600                 }
 601 
 602                 mutex_enter(&usba_device->usb_mutex);
 603                 prev = &usba_device->usb_client_dev_data_list;
 604                 entry = usba_device->usb_client_dev_data_list.cddl_next;
 605 
 606                 /* free the entries in usb_client_data_list */
 607                 while (entry) {
 608                         next = entry->cddl_next;
 609                         if ((dip == entry->cddl_dip) &&
 610                             (reg == entry->cddl_dev_data)) {
 611                                 prev->cddl_next = entry->cddl_next;
 612                                 if (entry->cddl_next) {
 613                                         entry->cddl_next->cddl_prev = prev;
 614                                 }
 615                                 kmem_free(entry, sizeof (*entry));
 616                         } else {
 617                                 /*
 618                                  * any other entries for this interface?
 619                                  */
 620                                 if (usba_get_ifno(dip) == entry->cddl_ifno) {
 621                                         matches++;
 622                                 }
 623                                 prev = entry;
 624                         }
 625                         entry = next;
 626                 }
 627 
 628                 USB_DPRINTF_L3(DPRINT_MASK_REGISTER,
 629                     usbai_reg_log_handle,
 630                     "usb_free_dev_data: next=0x%p flags[%d]=0x%x",
 631                     (void *)usba_device->usb_client_dev_data_list.cddl_next,
 632                     usba_get_ifno(dip),
 633                     usba_device->usb_client_flags[usba_get_ifno(dip)]);
 634 
 635                 if (matches == 0) {
 636                         usba_device->
 637                             usb_client_flags[usba_get_ifno(dip)] &=
 638                             ~USBA_CLIENT_FLAG_DEV_DATA;
 639                 }
 640                 mutex_exit(&usba_device->usb_mutex);
 641 
 642                 kmem_free(reg, sizeof (usb_client_dev_data_t));
 643         }
 644 
 645         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 646             "usb_free_dev_data done");
 647 }
 648 
 649 /*
 650  * This builds the BOS descriptors for WUSB device
 651  */
 652 static int
 653 usba_build_bos(usba_device_t *usba_device, usb_client_dev_data_t *usb_reg)
 654 {
 655         uint8_t         *buf;
 656         size_t          size, buflen;
 657 
 658         buf = usba_device->usb_wireless_data->wusb_bos;
 659         buflen = usba_device->usb_wireless_data->wusb_bos_length;
 660 
 661         usb_reg->dev_bos = kmem_zalloc(sizeof (usb_bos_data_t),
 662             KM_SLEEP);
 663         size = usb_parse_bos_descr(buf, buflen, &usb_reg->dev_bos->bos_descr,
 664             sizeof (usb_bos_descr_t));
 665         if (size != USB_BOS_DESCR_SIZE) {
 666                 kmem_free(usb_reg->dev_bos, sizeof (usb_bos_data_t));
 667 
 668                 return (USB_FAILURE);
 669         }
 670 
 671         size = usb_parse_uwb_bos_descr(buf, buflen,
 672             &usb_reg->dev_bos->bos_uwb_cap, sizeof (usb_uwb_cap_descr_t));
 673         if (size != USB_UWB_CAP_DESCR_SIZE) {
 674                 kmem_free(usb_reg->dev_bos, sizeof (usb_bos_data_t));
 675 
 676                 return (USB_FAILURE);
 677         }
 678 
 679         return (USB_SUCCESS);
 680 }
 681 
 682 
 683 /*
 684  * usba_build_descr_tree:
 685  *      This builds the descriptor tree.  See module header comment for tree
 686  *      description.
 687  *
 688  * Arguments:
 689  *      dip             - devinfo pointer - cannot be NULL.
 690  *      usba_device     - pointer to usba_device structure.
 691  *      usb_reg         - pointer to area returned to client describing device.
 692  *                        number of configuration (dev_n_cfg) and array of
 693  *                        configurations (dev_cfg) are initialized here -
 694  *                        dev_parse_level used and may be modified to fit
 695  *                        current configuration.
 696  * Return values:
 697  *      USB_SUCCESS      - Tree build succeeded
 698  *      USB_INVALID_ARGS - dev_parse_level in usb_reg is invalid.
 699  *      USB_FAILURE      - Bad descriptor info or other internal failure
 700  */
 701 static int
 702 usba_build_descr_tree(dev_info_t *dip, usba_device_t *usba_device,
 703     usb_client_dev_data_t *usb_reg)
 704 {
 705         usba_reg_state_t state;                 /* State of tree construction */
 706         int             cfg_len_so_far = 0;     /* Bytes found, this config. */
 707         uint8_t         *last_byte;     /* Ptr to the end of the cfg cloud. */
 708         uint_t          this_cfg_ndx;           /* Configuration counter. */
 709         uint_t          high_cfg_bound;         /* High config index + 1. */
 710         uint_t          low_cfg_bound;          /* Low config index. */
 711         boolean_t       process_this_if_tree = B_FALSE; /* Save alts, eps, */
 712                                                         /* of this interface. */
 713 
 714         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 715             "usba_build_descr_tree starting");
 716 
 717         bzero(&state, sizeof (usba_reg_state_t));
 718         state.dip = dip;
 719 
 720         /*
 721          * Set config(s) and interface(s) to parse based on parse level.
 722          * Adjust parse_level according to which configs and interfaces are
 723          * made available by the device.
 724          */
 725         state.st_dev_parse_level = usb_reg->dev_parse_level;
 726         if (usba_set_parse_values(dip, usba_device, &state) != USB_SUCCESS) {
 727 
 728                 return (USB_INVALID_ARGS);
 729         }
 730         usb_reg->dev_parse_level = state.st_dev_parse_level;
 731 
 732         /* Preallocate configurations based on parse level. */
 733         if (usb_reg->dev_parse_level == USB_PARSE_LVL_ALL) {
 734                 usb_reg->dev_n_cfg = usba_device->usb_n_cfgs;
 735                 low_cfg_bound = 0;
 736                 high_cfg_bound = usba_device->usb_n_cfgs;
 737         } else {
 738                 usb_reg->dev_n_cfg = 1;
 739                 mutex_enter(&usba_device->usb_mutex);
 740                 low_cfg_bound = usba_device->usb_active_cfg_ndx;
 741                 high_cfg_bound = usba_device->usb_active_cfg_ndx + 1;
 742                 mutex_exit(&usba_device->usb_mutex);
 743         }
 744         usb_reg->dev_cfg = state.st_dev_cfg = kmem_zalloc(
 745             (usb_reg->dev_n_cfg * sizeof (usb_cfg_data_t)),
 746             KM_SLEEP);
 747         /*
 748          * this_cfg_ndx loops through all configurations presented;
 749          * state.st_dev_n_cfg limits the cfgs checked to the number desired.
 750          */
 751         state.st_dev_n_cfg = 0;
 752         for (this_cfg_ndx = low_cfg_bound; this_cfg_ndx < high_cfg_bound;
 753             this_cfg_ndx++) {
 754 
 755                 state.st_curr_raw_descr =
 756                     usba_device->usb_cfg_array[this_cfg_ndx];
 757                 ASSERT(state.st_curr_raw_descr != NULL);
 758 
 759                 /* Clear the following for config cloud sanity checking. */
 760                 last_byte = NULL;
 761                 state.st_curr_cfg = NULL;
 762                 state.st_curr_if = NULL;
 763                 state.st_curr_alt = NULL;
 764                 state.st_curr_ep = NULL;
 765 
 766                 do {
 767                         /* All descr have length and type at offset 0 and 1 */
 768                         state.st_curr_raw_descr_len =
 769                             state.st_curr_raw_descr[0];
 770                         state.st_curr_raw_descr_type =
 771                             state.st_curr_raw_descr[1];
 772 
 773                         /* First descr in cloud must be a config descr. */
 774                         if ((last_byte == NULL) &&
 775                             (state.st_curr_raw_descr_type !=
 776                             USB_DESCR_TYPE_CFG)) {
 777 
 778                                 return (USB_FAILURE);
 779                         }
 780 
 781                         /*
 782                          * Bomb if we don't find a new cfg descr when expected.
 783                          * cfg_len_so_far = total_cfg_length = 0 1st time thru.
 784                          */
 785                         if (cfg_len_so_far > state.st_total_cfg_length) {
 786                                 USB_DPRINTF_L2(DPRINT_MASK_ALL,
 787                                     usbai_reg_log_handle,
 788                                     "usba_build_descr_tree: Configuration (%d) "
 789                                     "larger than wTotalLength (%d).",
 790                                     cfg_len_so_far, state.st_total_cfg_length);
 791 
 792                                 return (USB_FAILURE);
 793                         }
 794 
 795                         USB_DPRINTF_L3(DPRINT_MASK_REGISTER,
 796                             usbai_reg_log_handle,
 797                             "usba_build_descr_tree: Process type %d descr "
 798                             "(addr=0x%p)", state.st_curr_raw_descr_type,
 799                             (void *)state.st_curr_raw_descr);
 800 
 801                         switch (state.st_curr_raw_descr_type) {
 802                         case USB_DESCR_TYPE_CFG:
 803                                 cfg_len_so_far = 0;
 804                                 process_this_if_tree = B_FALSE;
 805 
 806                                 state.st_curr_cfg_str = usba_device->
 807                                     usb_cfg_str_descr[this_cfg_ndx];
 808                                 usba_process_cfg_descr(&state);
 809                                 state.st_last_processed_descr_type =
 810                                     USB_DESCR_TYPE_CFG;
 811                                 last_byte = state.st_curr_raw_descr +
 812                                     (state.st_total_cfg_length *
 813                                     sizeof (uchar_t));
 814 
 815                                 break;
 816 
 817                         case USB_DESCR_TYPE_IF:
 818                                 /*
 819                                  * process_this_if_tree == TRUE means this
 820                                  * interface, plus all eps and c/vs in it are
 821                                  * to be processed.
 822                                  */
 823                                 if (usba_process_if_descr(&state,
 824                                     &process_this_if_tree) != USB_SUCCESS) {
 825 
 826                                         return (USB_FAILURE);
 827                                 }
 828                                 state.st_last_processed_descr_type =
 829                                     USB_DESCR_TYPE_IF;
 830 
 831                                 break;
 832 
 833                         case USB_DESCR_TYPE_EP:
 834                                 /*
 835                                  * Skip if endpoints of a specific interface are
 836                                  * desired and this endpoint is associated with
 837                                  * a different interface.
 838                                  */
 839                                 if (process_this_if_tree) {
 840                                         if (usba_process_ep_descr(&state) !=
 841                                             USB_SUCCESS) {
 842 
 843                                                 return (USB_FAILURE);
 844                                         }
 845                                         state.st_last_processed_descr_type =
 846                                             USB_DESCR_TYPE_EP;
 847                                 }
 848 
 849                                 break;
 850                         case USB_DESCR_TYPE_WIRELESS_EP_COMP:
 851                                 /* for WUSB devices */
 852                                 if (process_this_if_tree &&
 853                                     state.st_build_ep_comp) {
 854                                         if (usba_process_ep_comp_descr(
 855                                             &state) != USB_SUCCESS) {
 856 
 857                                                 return (USB_FAILURE);
 858                                         }
 859                                 }
 860 
 861                                 break;
 862                         case USB_DESCR_TYPE_STRING:
 863                                 USB_DPRINTF_L2(DPRINT_MASK_ALL,
 864                                     usbai_reg_log_handle,
 865                                     "usb_get_dev_data: "
 866                                     "Found unexpected str descr at addr 0x%p",
 867                                     (void *)state.st_curr_raw_descr);
 868 
 869                                 break;  /* Shouldn't be any here.  Skip. */
 870 
 871                         default:
 872                                 /*
 873                                  * Treat all other descr as class/vendor
 874                                  * specific.  Skip if c/vs of a specific
 875                                  * interface are desired and this c/v is
 876                                  * associated with a different one.
 877                                  * Device level c/vs should always be
 878                                  * processed, e.g., the security descrs
 879                                  * for the Host Wire Adapter.
 880                                  */
 881                                 if ((state.st_last_processed_descr_type ==
 882                                     USB_DESCR_TYPE_CFG) ||
 883                                     (process_this_if_tree == B_TRUE)) {
 884                                         if (usba_process_cv_descr(&state) !=
 885                                             USB_SUCCESS) {
 886 
 887                                                 return (USB_FAILURE);
 888                                         }
 889                                 }
 890                         }
 891 
 892                         state.st_curr_raw_descr += state.st_curr_raw_descr_len;
 893                         cfg_len_so_far += state.st_curr_raw_descr_len;
 894 
 895                 } while (state.st_curr_raw_descr < last_byte);
 896         }
 897 
 898         /* Make tree sparse, and put elements in order. */
 899         usba_order_tree(&state);
 900 
 901         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 902             "usba_build_descr_tree done");
 903 
 904         return (USB_SUCCESS);
 905 }
 906 
 907 
 908 /*
 909  * usba_process_cfg_descr:
 910  *      Set up a configuration tree node based on a raw config descriptor.
 911  *
 912  * Arguments:
 913  *      state           - Pointer to this module's state structure.
 914  *
 915  * Returns:
 916  *      B_TRUE: the descr processed corresponds to a requested configuration.
 917  *      B_FALSE: the descr processed does not correspond to a requested config.
 918  */
 919 static void
 920 usba_process_cfg_descr(usba_reg_state_t *state)
 921 {
 922         usb_cfg_data_t *curr_cfg;
 923 
 924         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 925             "usba_process_cfg_descr starting");
 926 
 927         curr_cfg = state->st_curr_cfg =
 928             &state->st_dev_cfg[state->st_dev_n_cfg++];
 929 
 930         /* Parse and store config descriptor proper in the tree. */
 931         (void) usb_parse_data("2cs5c",
 932             state->st_curr_raw_descr, state->st_curr_raw_descr_len,
 933             &curr_cfg->cfg_descr,
 934             sizeof (usb_cfg_descr_t));
 935 
 936         state->st_total_cfg_length = curr_cfg->cfg_descr.wTotalLength;
 937 
 938         if (state->st_curr_cfg_str != NULL) {
 939                 curr_cfg->cfg_strsize = strlen(state->st_curr_cfg_str) + 1;
 940                 curr_cfg->cfg_str = kmem_zalloc(curr_cfg->cfg_strsize,
 941                     KM_SLEEP);
 942                 (void) strcpy(curr_cfg->cfg_str, state->st_curr_cfg_str);
 943         }
 944 
 945         curr_cfg->cfg_n_if = curr_cfg->cfg_descr.bNumInterfaces;
 946         curr_cfg->cfg_if = kmem_zalloc((curr_cfg->cfg_n_if *
 947             sizeof (usb_if_data_t)), KM_SLEEP);
 948 
 949         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 950             "usba_process_cfg_descr done");
 951 }
 952 
 953 
 954 /*
 955  * usba_process_if_descr:
 956  *      This processes a raw interface descriptor, and sets up an analogous
 957  *      interface node and child "alternate" nodes (each containing an
 958  *      interface descriptor) in the descriptor tree.
 959  *
 960  *      It groups all descriptors with the same bInterfaceNumber (alternates)
 961  *      into an array.  It makes entries in an interface array, each of which
 962  *      points to an array of alternates.
 963  *
 964  * Arguments:
 965  *      state           - Pointer to this module's state structure.
 966  *      requested_if    - Address into which the following is returned:
 967  *          B_TRUE      - the processed descr is of a requested interface.
 968  *          B_FALSE     - the processed descr if of a non-requested interface.
 969  *
 970  * Returns:
 971  *      USB_SUCCESS:    Descriptor is successfully parsed.
 972  *      USB_FAILURE:    Descriptor is inappropriately placed in config cloud.
 973  */
 974 static int
 975 usba_process_if_descr(usba_reg_state_t *state, boolean_t *requested_if)
 976 {
 977         char *string;
 978         usb_if_descr_t *new_if_descr;
 979         usba_device_t *usba_device = usba_get_usba_device(state->dip);
 980         int is_root_hub = (usba_device->usb_addr == ROOT_HUB_ADDR);
 981 
 982         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 983             "usba_process_if_descr starting");
 984 
 985         /* No config preceeds this interface. */
 986         if (state->st_curr_cfg == NULL) {
 987                 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 988                     "usba_process_if_descr found interface after no config.");
 989 
 990                 return (USB_FAILURE);
 991         }
 992 
 993         new_if_descr = kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP);
 994 
 995         /* Strictly speaking, unpacking is not necessary.  Could use bcopy. */
 996         (void) usb_parse_data("9c", state->st_curr_raw_descr,
 997             state->st_curr_raw_descr_len,
 998             new_if_descr, sizeof (usb_if_descr_t));
 999 
1000         /* Check the interface number in case of a malfunction device */
1001         if (new_if_descr->bInterfaceNumber >= state->st_curr_cfg->cfg_n_if) {
1002                 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1003                     "usba_process_if_descr: bInterfaceNumber=%d is not "
1004                     "a valid one", new_if_descr->bInterfaceNumber);
1005                 kmem_free(new_if_descr, sizeof (usb_if_descr_t));
1006 
1007                 *requested_if = B_FALSE;
1008 
1009                 return (USB_SUCCESS);
1010         }
1011         *requested_if = B_TRUE;
1012 
1013         /* Not a requested interface. */
1014         if ((state->st_if_to_build != new_if_descr->bInterfaceNumber) &&
1015             (state->st_if_to_build != USBA_ALL)) {
1016                 *requested_if = B_FALSE;
1017 
1018         } else {
1019                 usb_alt_if_data_t *alt_array;
1020                 uint_t          alt_index;
1021 
1022                 /* Point to proper interface node, based on num in descr. */
1023                 state->st_curr_if =
1024                     &state->st_curr_cfg->cfg_if[new_if_descr->bInterfaceNumber];
1025 
1026                 /* Make room for new alternate. */
1027                 alt_index = state->st_curr_if->if_n_alt;
1028                 alt_array = state->st_curr_if->if_alt;
1029                 usba_augment_array((void **)(&alt_array), alt_index,
1030                     sizeof (usb_alt_if_data_t));
1031 
1032                 /* Ptr to the current alt, may be used to attach a c/v to it. */
1033                 state->st_curr_alt = &alt_array[alt_index];
1034 
1035                 bcopy(new_if_descr, &(alt_array[alt_index++].altif_descr),
1036                     sizeof (usb_if_descr_t));
1037                 state->st_curr_if->if_alt = alt_array;
1038                 state->st_curr_if->if_n_alt = alt_index;
1039 
1040                 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
1041                 if (!is_root_hub) {
1042                         (void) usb_get_string_descr(state->dip, USB_LANG_ID,
1043                             state->st_curr_alt->altif_descr.iInterface,
1044                             string, USB_MAXSTRINGLEN);
1045                 }
1046                 if (string[0] == '\0') {
1047                         (void) strcpy(string, "<none>");
1048                 }
1049                 state->st_curr_alt->altif_strsize = strlen(string) + 1;
1050                 state->st_curr_alt->altif_str = kmem_zalloc(
1051                     state->st_curr_alt->altif_strsize, KM_SLEEP);
1052                 (void) strcpy(state->st_curr_alt->altif_str, string);
1053                 kmem_free(string, USB_MAXSTRINGLEN);
1054         }
1055 
1056         kmem_free(new_if_descr, sizeof (usb_if_descr_t));
1057 
1058         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1059             "usba_process_if_descr done");
1060 
1061         return (USB_SUCCESS);
1062 }
1063 
1064 
1065 /*
1066  * usba_process_ep_descr:
1067  *      This processes a raw endpoint descriptor, and sets up an analogous
1068  *      endpoint descriptor node in the descriptor tree.
1069  *
1070  * Arguments:
1071  *      state           - Pointer to this module's state structure.
1072  *
1073  * Returns:
1074  *      USB_SUCCESS:    Descriptor is successfully parsed.
1075  *      USB_FAILURE:    Descriptor is inappropriately placed in config cloud.
1076  */
1077 static int
1078 usba_process_ep_descr(usba_reg_state_t *state)
1079 {
1080         usb_alt_if_data_t *curr_alt = state->st_curr_alt;
1081 
1082         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1083             "usba_process_ep_descr starting");
1084 
1085         /* No interface preceeds this endpoint. */
1086         if (state->st_curr_alt == NULL) {
1087                 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1088                     "usba_process_ep_descr: no requested alt before endpt.");
1089 
1090                 return (USB_FAILURE);
1091         }
1092 
1093         usba_augment_array((void **)(&curr_alt->altif_ep),
1094             curr_alt->altif_n_ep, sizeof (usb_ep_data_t));
1095 
1096         /* Ptr to the current endpt, may be used to attach a c/v to it. */
1097         state->st_curr_ep = &curr_alt->altif_ep[curr_alt->altif_n_ep++];
1098 
1099         (void) usb_parse_data("4csc", state->st_curr_raw_descr,
1100             state->st_curr_raw_descr_len,
1101             &state->st_curr_ep->ep_descr, sizeof (usb_ep_descr_t));
1102 
1103         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1104             "usba_process_ep_descr done");
1105 
1106         return (USB_SUCCESS);
1107 }
1108 
1109 
1110 static int
1111 usba_process_ep_comp_descr(usba_reg_state_t *state)
1112 {
1113         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1114             "usba_process_ep_comp_descr starting");
1115 
1116         /* No endpoint descr preceeds this descr */
1117         if (state->st_curr_ep == NULL) {
1118                 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1119                     "usba_process_ep_comp_descr: no endpt before the descr");
1120 
1121                 return (USB_FAILURE);
1122         }
1123 
1124         (void) usb_parse_data("ccccsscc", state->st_curr_raw_descr,
1125             state->st_curr_raw_descr_len,
1126             &state->st_curr_ep->ep_comp_descr,
1127             sizeof (usb_ep_comp_descr_t));
1128         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1129             "usba_process_ep_comp_descr done");
1130 
1131         return (USB_SUCCESS);
1132 }
1133 
1134 /*
1135  * usba_process_cv_descr:
1136  *      This processes a raw endpoint descriptor, and sets up an analogous
1137  *      endpoint descriptor in the descriptor tree.  C/Vs are associated with
1138  *      other descriptors they follow in the raw data.
1139  *      last_processed_descr_type indicates the type of descr this c/v follows.
1140  *
1141  * Arguments:
1142  *      state           - Pointer to this module's state structure.
1143  *
1144  * Returns:
1145  *      USB_SUCCESS:    Descriptor is successfully parsed.
1146  *      USB_FAILURE:    Descriptor is inappropriately placed in config cloud.
1147  */
1148 static int
1149 usba_process_cv_descr(usba_reg_state_t *state)
1150 {
1151         usb_cvs_data_t  *curr_cv_descr;
1152         usb_cvs_data_t  **cvs_ptr = NULL;
1153         uint_t          *n_cvs_ptr;
1154 
1155         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1156             "usba_process_cv_descr starting.  Processing c/v for descr type %d",
1157             state->st_last_processed_descr_type);
1158 
1159         /*
1160          * Attach the c/v to a node based on the last descr type processed.
1161          * Save handles to appropriate c/v node array and count to update.
1162          */
1163         switch (state->st_last_processed_descr_type) {
1164         case USB_DESCR_TYPE_CFG:
1165                 n_cvs_ptr = &state->st_curr_cfg->cfg_n_cvs;
1166                 cvs_ptr = &state->st_curr_cfg->cfg_cvs;
1167                 break;
1168 
1169         case USB_DESCR_TYPE_IF:
1170                 n_cvs_ptr = &state->st_curr_alt->altif_n_cvs;
1171                 cvs_ptr = &state->st_curr_alt->altif_cvs;
1172                 break;
1173 
1174         case USB_DESCR_TYPE_EP:
1175                 n_cvs_ptr = &state->st_curr_ep->ep_n_cvs;
1176                 cvs_ptr = &state->st_curr_ep->ep_cvs;
1177                 break;
1178 
1179         default:
1180                 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle,
1181                     "usba_process_cv_descr: Type of last descriptor unknown. ");
1182 
1183                 return (USB_FAILURE);
1184         }
1185 
1186         usba_augment_array((void **)cvs_ptr, *n_cvs_ptr,
1187             sizeof (usb_cvs_data_t));
1188         curr_cv_descr = &(*cvs_ptr)[(*n_cvs_ptr)++];
1189 
1190         curr_cv_descr->cvs_buf =
1191             kmem_zalloc(state->st_curr_raw_descr_len, KM_SLEEP);
1192         curr_cv_descr->cvs_buf_len = state->st_curr_raw_descr_len;
1193         bcopy(state->st_curr_raw_descr, curr_cv_descr->cvs_buf,
1194             state->st_curr_raw_descr_len);
1195 
1196         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1197             "usba_process_cv_descr done");
1198 
1199         return (USB_SUCCESS);
1200 }
1201 
1202 
1203 /*
1204  * usba_set_parse_values:
1205  *      Based on parse level, set the configuration(s) and interface(s) to build
1206  *
1207  *      Returned configuration value can be USBA_ALL indicating to build all
1208  *      configurations.  Likewise for the returned interface value.
1209  *
1210  * Arguments:
1211  *      dip             - pointer to devinfo of the device
1212  *      usba_device     - pointer to usba_device structure of the device
1213  *      state           - Pointer to this module's state structure.
1214  *                        if no specific config specified, default to all config
1215  *                        if no specific interface specified, default to all.
1216  *                        if_to_build and config_to_build are modified.
1217  *                        dev_parse_level may be modified.
1218  *
1219  * Returns:
1220  *      USB_SUCCESS     - success
1221  *      USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
1222  */
1223 static int
1224 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
1225     usba_reg_state_t *state)
1226 {
1227         /* Default to *all* in case configuration# prop not set. */
1228         mutex_enter(&usba_device->usb_mutex);
1229         state->st_cfg_to_build = usba_device->usb_active_cfg_ndx;
1230         state->st_build_ep_comp = usba_device->usb_is_wireless;
1231         mutex_exit(&usba_device->usb_mutex);
1232         if (state->st_cfg_to_build == USBA_DEV_CONFIG_INDEX_UNDEFINED) {
1233                 state->st_cfg_to_build = USBA_ALL;
1234         }
1235         state->st_if_to_build = usb_get_if_number(dip);
1236 
1237         switch (state->st_dev_parse_level) {
1238         case USB_PARSE_LVL_ALL:         /* Parse all configurations */
1239                 state->st_cfg_to_build = USBA_ALL;
1240                 state->st_if_to_build = USBA_ALL;
1241                 break;
1242 
1243         case USB_PARSE_LVL_CFG:         /* Parse all interfaces of a */
1244                                         /* specific configuration. */
1245                 state->st_if_to_build = USBA_ALL;
1246                 break;
1247 
1248         case USB_PARSE_LVL_IF:          /* Parse configured interface only */
1249                 if (state->st_if_to_build < 0) {
1250                         state->st_if_to_build = USBA_ALL;
1251                 }
1252                 break;
1253 
1254         default:
1255 
1256                 return (USB_INVALID_ARGS);
1257         }
1258 
1259         /*
1260          * Set parse level to identify this tree properly, regardless of what
1261          * the caller thought the tree would have.
1262          */
1263         if ((state->st_if_to_build == USBA_ALL) &&
1264             (state->st_dev_parse_level == USB_PARSE_LVL_IF)) {
1265                 state->st_dev_parse_level = USB_PARSE_LVL_CFG;
1266         }
1267         if ((state->st_cfg_to_build == USBA_ALL) &&
1268             (state->st_dev_parse_level == USB_PARSE_LVL_CFG)) {
1269                 state->st_dev_parse_level = USB_PARSE_LVL_ALL;
1270         }
1271 
1272         return (USB_SUCCESS);
1273 }
1274 
1275 
1276 /*
1277  * usba_kmem_realloc:
1278  *      Resize dynamic memory.  Copy contents of old area to
1279  *      beginning of new area.
1280  *
1281  * Arguments:
1282  *      old_mem         - pointer to old memory area.
1283  *      old_size        - size of old memory area.  0 is OK.
1284  *      new_size        - size desired.
1285  *
1286  * Returns:
1287  *      pointer to new memory area.
1288  */
1289 static void*
1290 usba_kmem_realloc(void* old_mem, int old_size, int new_size)
1291 {
1292         void *new_mem = NULL;
1293 
1294         if (new_size > 0) {
1295                 new_mem = kmem_zalloc(new_size, KM_SLEEP);
1296                 if (old_size > 0) {
1297                         bcopy(old_mem, new_mem,
1298                             min(old_size, new_size));
1299                 }
1300         }
1301 
1302         if (old_size > 0) {
1303                 kmem_free(old_mem, old_size);
1304         }
1305 
1306         return (new_mem);
1307 }
1308 
1309 
1310 /*
1311  * usba_augment_array:
1312  *      Add a new element on the end of an array.
1313  *
1314  * Arguments:
1315  *      addr            - ptr to the array address.  Array addr will change.
1316  *      n_elements      - array element count.
1317  *      element_size    - size of an array element
1318  */
1319 static void
1320 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size)
1321 {
1322         *addr = usba_kmem_realloc(*addr, (n_elements * element_size),
1323             ((n_elements + 1) * element_size));
1324 }
1325 
1326 
1327 /*
1328  * usba_make_alts_sparse:
1329  *      Disburse alternate array elements such that they are at the proper array
1330  *      indices for which alt they represent.  It is assumed that all key values
1331  *      used for ordering the elements are positive.  Original array space may
1332  *      be freed and new space allocated.
1333  *
1334  * Arguments:
1335  *      array           - pointer to alternates array; may be modified
1336  *      n_elements      - number of elements in the array; may be modified
1337  */
1338 static void
1339 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements)
1340 {
1341         uint_t  n_orig_elements = *n_elements;
1342         uint8_t smallest_value;
1343         uint8_t largest_value;
1344         uint8_t curr_value;
1345         uint_t  in_order = 0;
1346         usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */
1347         usb_alt_if_data_t *repl_array;  /* Base ptr to sparse array */
1348         uint_t  n_repl_elements;        /* Number elements in the new array */
1349         uint_t  i;
1350 
1351         /* Check for a null array. */
1352         if ((array == NULL) || (n_orig_elements == 0)) {
1353 
1354                 return;
1355         }
1356 
1357         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1358             "make_sparse: array=0x%p, n_orig_elements=%d",
1359             (void *)array, n_orig_elements);
1360 
1361         curr_value = orig_addr[0].altif_descr.bAlternateSetting;
1362         smallest_value = largest_value = curr_value;
1363 
1364         /* Figure the low-high range of the array. */
1365         for (i = 1; i < n_orig_elements; i++) {
1366                 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1367                 if (curr_value < smallest_value) {
1368                         smallest_value = curr_value;
1369                 } else if (curr_value > largest_value) {
1370                         in_order++;
1371                         largest_value = curr_value;
1372                 }
1373         }
1374         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1375             "make_sparse: largest=%d, smallest=%d, "
1376             "order=%d",
1377             largest_value, smallest_value, in_order);
1378 
1379         n_repl_elements = largest_value + 1;
1380 
1381         /*
1382          * No holes to leave, array starts at zero, and everything is already
1383          * in order.  Just return original array.
1384          */
1385         if ((n_repl_elements == n_orig_elements) &&
1386             ((in_order + 1) == n_orig_elements)) {
1387                 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1388                     "No holes");
1389 
1390                 return;
1391         }
1392 
1393         /* Allocate zeroed space for the array. */
1394         repl_array = kmem_zalloc(
1395             (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP);
1396 
1397         /* Now fill in the array. */
1398         for (i = 0; i < n_orig_elements; i++) {
1399                 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1400 
1401                 /* Place in sparse array based on key. */
1402                 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1403                     "move %lu bytes (key %d) from 0x%p to 0x%p",
1404                     (unsigned long)sizeof (usb_alt_if_data_t), curr_value,
1405                     (void *)&orig_addr[i], (void *)&repl_array[curr_value]);
1406 
1407                 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value],
1408                     sizeof (usb_alt_if_data_t));
1409         }
1410 
1411         kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements);
1412         *array = repl_array;
1413         *n_elements = n_repl_elements;
1414 }
1415 
1416 
1417 /*
1418  * usba_order_tree:
1419  *      Take a tree as built by usba_build_descr_tree and make sure the key
1420  *      values of all elements match their indeces.  Proper order is implied.
1421  *
1422  * Arguments:
1423  *      state           - Pointer to this module's state structure.
1424  */
1425 static void
1426 usba_order_tree(usba_reg_state_t *state)
1427 {
1428         usb_cfg_data_t  *this_cfg;
1429         usb_if_data_t   *this_if;
1430         uint_t          n_cfgs = state->st_dev_n_cfg;
1431         uint_t          cfg;
1432         uint_t          which_if;
1433 
1434         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1435             "usba_order_tree:");
1436 
1437         for (cfg = 0; cfg < n_cfgs; cfg++) {
1438                 this_cfg = &state->st_dev_cfg[cfg];
1439 
1440                 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) {
1441                         this_if = this_cfg->cfg_if;
1442                         usba_make_alts_sparse(&this_if->if_alt,
1443                             &this_if->if_n_alt);
1444                 }
1445         }
1446 }
1447 
1448 
1449 /*
1450  * usb_free_descr_tree:
1451  *      Take down the configuration tree.  Called internally and can be called
1452  *      from a driver standalone to take the tree down while leaving the rest
1453  *      of the registration intact.
1454  *
1455  * Arguments:
1456  *      dip             - pointer to devinfo of the device
1457  *      dev_data        - pointer to registration data containing the tree.
1458  */
1459 void
1460 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1461 {
1462         usb_cfg_data_t *cfg_array;
1463         int n_cfgs;
1464         int cfg;
1465 
1466         if ((dip == NULL) || (dev_data == NULL)) {
1467 
1468                 return;
1469         }
1470         cfg_array = dev_data->dev_cfg;
1471         n_cfgs = dev_data->dev_n_cfg;
1472 
1473         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1474             "usb_free_descr_tree starting for %s%d",
1475             ddi_driver_name(dip), ddi_get_instance(dip));
1476 
1477         for (cfg = 0; cfg < n_cfgs; cfg++) {
1478                 if (cfg_array[cfg].cfg_if) {
1479                         usba_free_if_array(cfg_array[cfg].cfg_if,
1480                             cfg_array[cfg].cfg_n_if);
1481                 }
1482                 if (cfg_array[cfg].cfg_cvs) {
1483                         usba_free_cv_array(cfg_array[cfg].cfg_cvs,
1484                             cfg_array[cfg].cfg_n_cvs);
1485                 }
1486                 if (cfg_array[cfg].cfg_str) {
1487                         kmem_free(cfg_array[cfg].cfg_str,
1488                             cfg_array[cfg].cfg_strsize);
1489                 }
1490         }
1491 
1492         if (cfg_array) {
1493                 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs));
1494         }
1495 
1496         dev_data->dev_parse_level = USB_PARSE_LVL_NONE;
1497         dev_data->dev_n_cfg = 0;
1498         dev_data->dev_cfg = NULL;
1499         dev_data->dev_curr_cfg = NULL;
1500 
1501         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1502             "usb_free_descr_tree done");
1503 }
1504 
1505 
1506 /*
1507  * usba_free_if_array:
1508  *      Free a configuration's array of interface nodes and their subtrees of
1509  *      interface alternate, endpoint and c/v descriptors.
1510  *
1511  * Arguments:
1512  *      if_array        - pointer to array of interfaces to remove.
1513  *      n_ifs           - number of elements in the array to remove.
1514  */
1515 static void
1516 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs)
1517 {
1518         uint_t which_if;
1519         uint_t which_alt;
1520         uint_t n_alts;
1521         usb_alt_if_data_t *altif;
1522 
1523         for (which_if = 0; which_if < n_ifs; which_if++) {
1524                 n_alts = if_array[which_if].if_n_alt;
1525 
1526                 /* Every interface has at least one alternate. */
1527                 for (which_alt = 0; which_alt < n_alts; which_alt++) {
1528                         altif = &if_array[which_if].if_alt[which_alt];
1529                         usba_free_ep_array(altif->altif_ep, altif->altif_n_ep);
1530                         usba_free_cv_array(altif->altif_cvs,
1531                             altif->altif_n_cvs);
1532                         kmem_free(altif->altif_str, altif->altif_strsize);
1533                 }
1534 
1535                 kmem_free(if_array[which_if].if_alt,
1536                     (sizeof (usb_alt_if_data_t) * n_alts));
1537         }
1538 
1539         /* Free the interface array itself. */
1540         kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs));
1541 }
1542 
1543 
1544 /*
1545  * usba_free_ep_array:
1546  *      Free an array of endpoint nodes and their subtrees of c/v descriptors.
1547  *
1548  * Arguments:
1549  *      ep_array        - pointer to array of endpoints to remove.
1550  *      n_eps           - number of elements in the array to remove.
1551  */
1552 static void
1553 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps)
1554 {
1555         uint_t ep;
1556 
1557         for (ep = 0; ep < n_eps; ep++) {
1558                 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs);
1559         }
1560 
1561         kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps));
1562 }
1563 
1564 
1565 /*
1566  * usba_free_cv_array:
1567  *      Free an array of class/vendor (c/v) descriptor nodes.
1568  *
1569  * Arguments:
1570  *      cv_array        - pointer to array of c/v nodes to remove.
1571  *      n_cvs           - number of elements in the array to remove.
1572  */
1573 static void
1574 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs)
1575 {
1576         uint_t cv_node;
1577 
1578         /* Free data areas hanging off of each c/v descriptor. */
1579         for (cv_node = 0; cv_node < n_cvs; cv_node++) {
1580                 kmem_free(cv_array[cv_node].cvs_buf,
1581                     cv_array[cv_node].cvs_buf_len);
1582         }
1583 
1584         /* Free the array of cv descriptors. */
1585         kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs));
1586 }
1587 
1588 
1589 /*
1590  * usb_log_descr_tree:
1591  *      Log to the usba_debug_buf a descriptor tree as returned by
1592  *      usbai_register_client.
1593  *
1594  * Arguments:
1595  *      dev_data        - pointer to registration area containing the tree
1596  *      log_handle      - pointer to log handle to use for dumping.
1597  *      level           - print level, one of USB_LOG_L0 ... USB_LOG_L4
1598  *                        Please see usb_log(9F) for details.
1599  *      mask            - print mask.  Please see usb_log(9F) for details.
1600  *
1601  * Returns:
1602  *      USB_SUCCESS             - tree successfully dumped
1603  *      USB_INVALID_CONTEXT     - called from callback context
1604  *      USB_INVALID_ARGS        - bad arguments given
1605  */
1606 int
1607 usb_log_descr_tree(usb_client_dev_data_t *dev_data,
1608     usb_log_handle_t log_handle, uint_t level, uint_t mask)
1609 {
1610         return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask));
1611 }
1612 
1613 
1614 /*
1615  * usb_print_descr_tree:
1616  *      Print to the screen a descriptor tree as returned by
1617  *      usbai_register_client.
1618  *
1619  * Arguments:
1620  *      dip             - pointer to devinfo of the client
1621  *      dev_data        - pointer to registration area containing the tree
1622  *
1623  * Returns:
1624  *      USB_SUCCESS             - tree successfully dumped
1625  *      USB_INVALID_CONTEXT     - called from callback context
1626  *      USB_INVALID_ARGS        - bad arguments given
1627  */
1628 int
1629 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1630 {
1631         return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0));
1632 }
1633 
1634 
1635 /*
1636  * usba_dump_descr_tree:
1637  *      Dump a descriptor tree.
1638  *
1639  * Arguments:
1640  *      dip             - pointer to devinfo of the client.  Used when no
1641  *                        log_handle argument given.
1642  *      usb_reg         - pointer to registration area containing the tree
1643  *      log_handle      - pointer to log handle to use for dumping.  If NULL,
1644  *                        use internal log handle, which dumps to screen.
1645  *      level           - print level, one of USB_LOG_L0 ... USB_LOG_L4
1646  *                        Used only when log_handle provided.
1647  *      mask            - print mask, used when log_handle argument provided.
1648  *
1649  * Returns:
1650  *      USB_SUCCESS             - tree successfully dumped
1651  *      USB_INVALID_CONTEXT     - called from callback context
1652  *      USB_INVALID_ARGS        - bad arguments given
1653  */
1654 static int
1655 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg,
1656     usb_log_handle_t log_handle, uint_t level, uint_t mask)
1657 {
1658         usb_log_handle_t dump_handle;
1659         uint_t          dump_level;
1660         uint_t          dump_mask;
1661         int             which_config; /* Counters. */
1662         int             which_if;
1663         int             which_cv;
1664         usb_cfg_data_t  *config; /* ptr to current configuration tree node */
1665         usb_cfg_descr_t *config_descr; /* and its USB descriptor. */
1666         char            *string;
1667         char            *name_string = NULL;
1668         int             name_string_size;
1669 
1670         if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) {
1671 
1672                 return (USB_INVALID_ARGS);
1673         }
1674 
1675         /*
1676          * To keep calling this simple, kmem_zalloc with the sleep flag always.
1677          * This means no interrupt context is allowed.
1678          */
1679         if (servicing_interrupt()) {
1680 
1681                 return (USB_INVALID_CONTEXT);
1682         }
1683 
1684         string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
1685 
1686         if (log_handle != NULL) {
1687                 dump_level = level;
1688                 dump_mask = mask;
1689                 dump_handle = log_handle;
1690         } else {
1691                 dump_level = USB_LOG_L1;
1692                 dump_mask = DPRINT_MASK_ALL;
1693 
1694                 /* Build device name string. */
1695                 (void) snprintf(string, USB_MAXSTRINGLEN,
1696                     "Port%d", usb_get_addr(dip));
1697                 name_string_size = strlen(string) + 1;
1698                 name_string = kmem_zalloc(name_string_size, KM_SLEEP);
1699                 (void) strcpy(name_string, string);
1700 
1701                 /* Allocate a log handle specifying the name string. */
1702                 dump_handle = usb_alloc_log_hdl(NULL, name_string,
1703                     &dump_level, &dump_mask, NULL,
1704                     USB_FLAGS_SLEEP);
1705         }
1706 
1707         (void) usb_log(dump_handle, dump_level, dump_mask,
1708             "USB descriptor tree for %s %s",
1709             (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""),
1710             (usb_reg->dev_product != NULL ? usb_reg->dev_product : ""));
1711         if (usb_reg->dev_n_cfg == 0) {
1712                 (void) usb_log(dump_handle, dump_level, dump_mask,
1713                     "No descriptor tree present");
1714         } else {
1715                 (void) usb_log(dump_handle, dump_level, dump_mask,
1716                     "highest configuration found=%d", usb_reg->dev_n_cfg - 1);
1717         }
1718 
1719         for (which_config = 0; which_config < usb_reg->dev_n_cfg;
1720             which_config++) {
1721                 config = &usb_reg->dev_cfg[which_config];
1722                 config_descr = &config->cfg_descr;
1723                 if (config_descr->bLength == 0) {
1724 
1725                         continue;
1726                 }
1727                 if (dump_level == USB_LOG_L0) {
1728                         (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1729                 }
1730                 (void) usb_log(dump_handle, dump_level, dump_mask,
1731                     "Configuration #%d (Addr= 0x%p)", which_config,
1732                     (void *)config);
1733                 (void) usb_log(dump_handle, dump_level, dump_mask,
1734                     "String descr=%s", config->cfg_str);
1735                 (void) usb_log(dump_handle, dump_level, dump_mask,
1736                     "config descr: len=%d tp=%d totLen=%d numIf=%d "
1737                     "cfgVal=%d att=0x%x pwr=%d",
1738                     config_descr->bLength, config_descr->bDescriptorType,
1739                     config_descr->wTotalLength, config_descr->bNumInterfaces,
1740                     config_descr->bConfigurationValue,
1741                     config_descr->bmAttributes, config_descr->bMaxPower);
1742                 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) {
1743                         (void) usb_log(dump_handle, dump_level, dump_mask,
1744                             "usb_cfg_data_t shows max if=%d "
1745                             "and %d cv descr(s).",
1746                             config->cfg_n_if - 1, config->cfg_n_cvs);
1747                 }
1748 
1749                 for (which_if = 0; which_if < config->cfg_n_if;
1750                     which_if++) {
1751 
1752                         if (dump_level == USB_LOG_L0) {
1753                                 (void) usb_log(dump_handle, dump_level,
1754                                     dump_mask, " ");
1755                         }
1756                         (void) usb_log(dump_handle, dump_level, dump_mask,
1757                             "    interface #%d (0x%p)",
1758                             which_if, (void *)&config->cfg_if[which_if]);
1759                         usba_dump_if(&config->cfg_if[which_if],
1760                             dump_handle, dump_level, dump_mask, string);
1761                 }
1762 
1763                 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) {
1764                         (void) usb_log(dump_handle, dump_level, dump_mask,
1765                             "  config cv descriptor %d (Address=0x%p)",
1766                             which_cv, (void *)&config->cfg_cvs[which_cv]);
1767                         usba_dump_cv(&config->cfg_cvs[which_cv],
1768                             dump_handle, dump_level, dump_mask, string, 4);
1769                 }
1770         }
1771 
1772         (void) usb_log(dump_handle, dump_level, dump_mask,
1773             "Returning dev_curr_cfg:0x%p, dev_curr_if:%d",
1774             (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if);
1775 
1776         if (log_handle == NULL) {
1777                 usb_free_log_hdl(dump_handle);
1778         }
1779         if (name_string != NULL) {
1780                 kmem_free(name_string, name_string_size);
1781         }
1782         kmem_free(string, USB_MAXSTRINGLEN);
1783 
1784         return (USB_SUCCESS);
1785 }
1786 
1787 
1788 /*
1789  * usba_dump_if:
1790  *      Dump an interface node and its branches.
1791  *
1792  * Arguments:
1793  *      which_if        - interface node to dump
1794  *      dump_handle     - write data through this log handle
1795  *      dump_level      - level passed to usb_log
1796  *      dump_mask       - mask passed to usb_log
1797  *      string          - temporary area used for processing
1798  *
1799  */
1800 static void
1801 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle,
1802     uint_t dump_level, uint_t dump_mask, char *string)
1803 {
1804         int             which_alt;      /* Number of alt being dumped */
1805         usb_alt_if_data_t *alt;         /* Pointer to it. */
1806         usb_if_descr_t *if_descr;       /* Pointer to its USB descr. */
1807         int             which_ep;       /* Endpoint counter. */
1808         int             which_cv;       /* C/V descr counter. */
1809 
1810         for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) {
1811                 alt = &which_if->if_alt[which_alt];
1812                 if_descr = &alt->altif_descr;
1813 
1814                 if (if_descr->bLength == 0) {
1815 
1816                         continue;
1817                 }
1818                 if (dump_level == USB_LOG_L0) {
1819                         (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1820                 }
1821                 (void) usb_log(dump_handle, dump_level, dump_mask,
1822                     "\tAlt #%d (0x%p)", which_alt, (void *)alt);
1823                 (void) usb_log(dump_handle, dump_level, dump_mask,
1824                     "\tString descr=%s", alt->altif_str);
1825                 (void) usb_log(dump_handle, dump_level, dump_mask,
1826                     "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d "
1827                     "cls=%d sub=%d proto=%d",
1828                     if_descr->bLength,
1829                     if_descr->bDescriptorType, if_descr->bInterfaceNumber,
1830                     if_descr->bAlternateSetting, if_descr->bNumEndpoints,
1831                     if_descr->bInterfaceClass, if_descr->bInterfaceSubClass,
1832                     if_descr->bInterfaceProtocol);
1833 
1834                 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) {
1835                         (void) usb_log(dump_handle, dump_level, dump_mask,
1836                             "\tusb_alt_if_data_t shows max ep=%d "
1837                             "and %d cv descr(s).",
1838                             alt->altif_n_ep - 1, alt->altif_n_cvs);
1839                 }
1840 
1841                 for (which_ep = 0; which_ep < alt->altif_n_ep;
1842                     which_ep++) {
1843                         if (alt->altif_ep[which_ep].ep_descr.bLength == 0) {
1844 
1845                                 continue;
1846                         }
1847                         if (dump_level == USB_LOG_L0) {
1848                                 (void) usb_log(dump_handle, dump_level,
1849                                     dump_mask, " ");
1850                         }
1851                         usba_dump_ep(which_ep, &alt->altif_ep[which_ep],
1852                             dump_handle, dump_level, dump_mask, string);
1853                 }
1854 
1855                 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) {
1856                         if (dump_level == USB_LOG_L0) {
1857                                 (void) usb_log(dump_handle, dump_level,
1858                                     dump_mask, " ");
1859                         }
1860                         (void) usb_log(dump_handle, dump_level, dump_mask,
1861                             "\talt cv descriptor #%d (0x%p), size=%d",
1862                             which_cv, (void *)&alt->altif_cvs[which_cv],
1863                             alt->altif_cvs[which_cv].cvs_buf_len);
1864                         usba_dump_cv(&alt->altif_cvs[which_cv],
1865                             dump_handle, dump_level, dump_mask, string, 2);
1866                 }
1867         }
1868 }
1869 
1870 
1871 /*
1872  * usba_dump_ep:
1873  *      Dump an endpoint node and its branches.
1874  *
1875  * Arguments:
1876  *      which_ep        - index to display
1877  *      ep              - endpoint node to dump
1878  *      dump_handle     - write data through this log handle
1879  *      dump_level      - level passed to usb_log
1880  *      dump_mask       - mask passed to usb_log
1881  *      string          - temporary area used for processing
1882  *
1883  */
1884 static void
1885 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle,
1886                 uint_t dump_level, uint_t dump_mask, char *string)
1887 {
1888         int which_cv;
1889         usb_ep_descr_t *ep_descr = &ep->ep_descr;
1890 
1891         (void) usb_log(dump_handle, dump_level, dump_mask,
1892             "\t    endpoint[%d], epaddr=0x%x (0x%p)", which_ep,
1893             ep_descr->bEndpointAddress, (void *)ep);
1894         (void) usb_log(dump_handle, dump_level, dump_mask,
1895             "\t    len=%d type=%d attr=0x%x pktsize=%d interval=%d",
1896             ep_descr->bLength, ep_descr->bDescriptorType,
1897             ep_descr->bmAttributes, ep_descr->wMaxPacketSize,
1898             ep_descr->bInterval);
1899         if (ep->ep_n_cvs > 0) {
1900                 (void) usb_log(dump_handle, dump_level, dump_mask,
1901                     "\t    usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs);
1902         }
1903 
1904         for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) {
1905                 if (dump_level == USB_LOG_L0) {
1906                         (void) usb_log(dump_handle, dump_level,
1907                             dump_mask, " ");
1908                 }
1909                 (void) usb_log(dump_handle, dump_level, dump_mask,
1910                     "\t    endpoint cv descriptor %d (0x%p), size=%d",
1911                     which_cv, (void *)&ep->ep_cvs[which_cv],
1912                     ep->ep_cvs[which_cv].cvs_buf_len);
1913                 usba_dump_cv(&ep->ep_cvs[which_cv],
1914                     dump_handle, dump_level, dump_mask, string, 3);
1915         }
1916 }
1917 
1918 
1919 /*
1920  * usba_dump_cv:
1921  *      Dump a raw class or vendor specific descriptor.
1922  *
1923  * Arguments:
1924  *      cv_node         - pointer to the descriptor to dump
1925  *      dump_handle     - write data through this log handle
1926  *      dump_level      - level passed to usb_log
1927  *      dump_mask       - mask passed to usb_log
1928  *      string          - temporary area used for processing
1929  *      indent          - number of tabs to indent output
1930  *
1931  */
1932 static void
1933 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle,
1934     uint_t dump_level, uint_t dump_mask, char *string, int indent)
1935 {
1936         if (cv_node) {
1937                 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent,
1938                     dump_handle, dump_level, dump_mask, string,
1939                     USB_MAXSTRINGLEN);
1940         }
1941 }
1942 
1943 
1944 /*
1945  * usba_dump_bin:
1946  *      Generic byte dump function.
1947  *
1948  * Arguments:
1949  *      data            - pointer to the data to dump
1950  *      max_bytes       - amount of data to dump
1951  *      indent          - number of indentation levels
1952  *      dump_handle     - write data through this log handle
1953  *      dump_level      - level passed to usb_log
1954  *      dump_mask       - mask passed to usb_log
1955  *      buffer          - temporary area used for processing
1956  *      bufferlen       - size of the temporary string area
1957  *
1958  */
1959 static void
1960 usba_dump_bin(uint8_t *data, int max_bytes, int indent,
1961     usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask,
1962     char *buffer, int bufferlen)
1963 {
1964         int i;
1965         int bufoffset = 0;
1966         int nexthere;
1967 
1968         if ((indent * SPACES_PER_INDENT) >
1969             (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) {
1970                 (void) usb_log(dump_handle, dump_level, dump_mask,
1971                     "Offset to usb_dump_bin must be %d or less.  "
1972                     "Setting to 0.\n",
1973                     (bufferlen - (BINDUMP_BYTES_PER_LINE * 3)));
1974                 indent = 0;
1975         }
1976 
1977         /* Assume a tab is 2 four-space units. */
1978         for (i = 0; i < indent/2; i++) {
1979                 buffer[bufoffset] = '\t';
1980                 bufoffset++;
1981         }
1982 
1983         if (indent % 2) {
1984                 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR);
1985                 bufoffset += SPACES_PER_INDENT;
1986         }
1987 
1988         i = 0;                  /* Num dumped bytes put on this line. */
1989         nexthere = bufoffset;
1990         while (i < max_bytes) {
1991                 (void) sprintf(&buffer[nexthere], "%2x ", *data++);
1992                 nexthere += 3;
1993                 i++;
1994                 if (!(i % BINDUMP_BYTES_PER_LINE)) {
1995                         buffer[nexthere] = '\0';
1996                         (void) usb_log(dump_handle, dump_level, dump_mask,
1997                             buffer);
1998                         nexthere = bufoffset;
1999                 }
2000         }
2001 
2002         if (nexthere > bufoffset) {
2003                 buffer[nexthere] = '\0';
2004                 (void) usb_log(dump_handle, dump_level, dump_mask, buffer);
2005         }
2006 }