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