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 2017 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         case USB_DESCR_TYPE_SS_EP_COMP:
1146                 n_cvs_ptr = &state->st_curr_ep->ep_n_cvs;
1147                 cvs_ptr = &state->st_curr_ep->ep_cvs;
1148                 break;
1149 
1150         default:
1151                 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle,
1152                     "usba_process_cv_descr: Type of last descriptor unknown. ");
1153 
1154                 return (USB_FAILURE);
1155         }
1156 
1157         usba_augment_array((void **)cvs_ptr, *n_cvs_ptr,
1158             sizeof (usb_cvs_data_t));
1159         curr_cv_descr = &(*cvs_ptr)[(*n_cvs_ptr)++];
1160 
1161         curr_cv_descr->cvs_buf =
1162             kmem_zalloc(state->st_curr_raw_descr_len, KM_SLEEP);
1163         curr_cv_descr->cvs_buf_len = state->st_curr_raw_descr_len;
1164         bcopy(state->st_curr_raw_descr, curr_cv_descr->cvs_buf,
1165             state->st_curr_raw_descr_len);
1166 
1167         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1168             "usba_process_cv_descr done");
1169 
1170         return (USB_SUCCESS);
1171 }
1172 
1173 
1174 /*
1175  * usba_set_parse_values:
1176  *      Based on parse level, set the configuration(s) and interface(s) to build
1177  *
1178  *      Returned configuration value can be USBA_ALL indicating to build all
1179  *      configurations.  Likewise for the returned interface value.
1180  *
1181  * Arguments:
1182  *      dip             - pointer to devinfo of the device
1183  *      usba_device     - pointer to usba_device structure of the device
1184  *      state           - Pointer to this module's state structure.
1185  *                        if no specific config specified, default to all config
1186  *                        if no specific interface specified, default to all.
1187  *                        if_to_build and config_to_build are modified.
1188  *                        dev_parse_level may be modified.
1189  *
1190  * Returns:
1191  *      USB_SUCCESS     - success
1192  *      USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
1193  */
1194 static int
1195 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
1196     usba_reg_state_t *state)
1197 {
1198         /* Default to *all* in case configuration# prop not set. */
1199         mutex_enter(&usba_device->usb_mutex);
1200         state->st_cfg_to_build = usba_device->usb_active_cfg_ndx;
1201         mutex_exit(&usba_device->usb_mutex);
1202         if (state->st_cfg_to_build == USBA_DEV_CONFIG_INDEX_UNDEFINED) {
1203                 state->st_cfg_to_build = USBA_ALL;
1204         }
1205         state->st_if_to_build = usb_get_if_number(dip);
1206 
1207         switch (state->st_dev_parse_level) {
1208         case USB_PARSE_LVL_ALL:         /* Parse all configurations */
1209                 state->st_cfg_to_build = USBA_ALL;
1210                 state->st_if_to_build = USBA_ALL;
1211                 break;
1212 
1213         case USB_PARSE_LVL_CFG:         /* Parse all interfaces of a */
1214                                         /* specific configuration. */
1215                 state->st_if_to_build = USBA_ALL;
1216                 break;
1217 
1218         case USB_PARSE_LVL_IF:          /* Parse configured interface only */
1219                 if (state->st_if_to_build < 0) {
1220                         state->st_if_to_build = USBA_ALL;
1221                 }
1222                 break;
1223 
1224         default:
1225 
1226                 return (USB_INVALID_ARGS);
1227         }
1228 
1229         /*
1230          * Set parse level to identify this tree properly, regardless of what
1231          * the caller thought the tree would have.
1232          */
1233         if ((state->st_if_to_build == USBA_ALL) &&
1234             (state->st_dev_parse_level == USB_PARSE_LVL_IF)) {
1235                 state->st_dev_parse_level = USB_PARSE_LVL_CFG;
1236         }
1237         if ((state->st_cfg_to_build == USBA_ALL) &&
1238             (state->st_dev_parse_level == USB_PARSE_LVL_CFG)) {
1239                 state->st_dev_parse_level = USB_PARSE_LVL_ALL;
1240         }
1241 
1242         return (USB_SUCCESS);
1243 }
1244 
1245 
1246 /*
1247  * usba_kmem_realloc:
1248  *      Resize dynamic memory.  Copy contents of old area to
1249  *      beginning of new area.
1250  *
1251  * Arguments:
1252  *      old_mem         - pointer to old memory area.
1253  *      old_size        - size of old memory area.  0 is OK.
1254  *      new_size        - size desired.
1255  *
1256  * Returns:
1257  *      pointer to new memory area.
1258  */
1259 static void*
1260 usba_kmem_realloc(void* old_mem, int old_size, int new_size)
1261 {
1262         void *new_mem = NULL;
1263 
1264         if (new_size > 0) {
1265                 new_mem = kmem_zalloc(new_size, KM_SLEEP);
1266                 if (old_size > 0) {
1267                         bcopy(old_mem, new_mem,
1268                             min(old_size, new_size));
1269                 }
1270         }
1271 
1272         if (old_size > 0) {
1273                 kmem_free(old_mem, old_size);
1274         }
1275 
1276         return (new_mem);
1277 }
1278 
1279 
1280 /*
1281  * usba_augment_array:
1282  *      Add a new element on the end of an array.
1283  *
1284  * Arguments:
1285  *      addr            - ptr to the array address.  Array addr will change.
1286  *      n_elements      - array element count.
1287  *      element_size    - size of an array element
1288  */
1289 static void
1290 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size)
1291 {
1292         *addr = usba_kmem_realloc(*addr, (n_elements * element_size),
1293             ((n_elements + 1) * element_size));
1294 }
1295 
1296 
1297 /*
1298  * usba_make_alts_sparse:
1299  *      Disburse alternate array elements such that they are at the proper array
1300  *      indices for which alt they represent.  It is assumed that all key values
1301  *      used for ordering the elements are positive.  Original array space may
1302  *      be freed and new space allocated.
1303  *
1304  * Arguments:
1305  *      array           - pointer to alternates array; may be modified
1306  *      n_elements      - number of elements in the array; may be modified
1307  */
1308 static void
1309 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements)
1310 {
1311         uint_t  n_orig_elements = *n_elements;
1312         uint8_t smallest_value;
1313         uint8_t largest_value;
1314         uint8_t curr_value;
1315         uint_t  in_order = 0;
1316         usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */
1317         usb_alt_if_data_t *repl_array;  /* Base ptr to sparse array */
1318         uint_t  n_repl_elements;        /* Number elements in the new array */
1319         uint_t  i;
1320 
1321         /* Check for a null array. */
1322         if ((array == NULL) || (n_orig_elements == 0)) {
1323 
1324                 return;
1325         }
1326 
1327         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1328             "make_sparse: array=0x%p, n_orig_elements=%d",
1329             (void *)array, n_orig_elements);
1330 
1331         curr_value = orig_addr[0].altif_descr.bAlternateSetting;
1332         smallest_value = largest_value = curr_value;
1333 
1334         /* Figure the low-high range of the array. */
1335         for (i = 1; i < n_orig_elements; i++) {
1336                 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1337                 if (curr_value < smallest_value) {
1338                         smallest_value = curr_value;
1339                 } else if (curr_value > largest_value) {
1340                         in_order++;
1341                         largest_value = curr_value;
1342                 }
1343         }
1344         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1345             "make_sparse: largest=%d, smallest=%d, "
1346             "order=%d",
1347             largest_value, smallest_value, in_order);
1348 
1349         n_repl_elements = largest_value + 1;
1350 
1351         /*
1352          * No holes to leave, array starts at zero, and everything is already
1353          * in order.  Just return original array.
1354          */
1355         if ((n_repl_elements == n_orig_elements) &&
1356             ((in_order + 1) == n_orig_elements)) {
1357                 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1358                     "No holes");
1359 
1360                 return;
1361         }
1362 
1363         /* Allocate zeroed space for the array. */
1364         repl_array = kmem_zalloc(
1365             (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP);
1366 
1367         /* Now fill in the array. */
1368         for (i = 0; i < n_orig_elements; i++) {
1369                 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1370 
1371                 /* Place in sparse array based on key. */
1372                 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1373                     "move %lu bytes (key %d) from 0x%p to 0x%p",
1374                     (unsigned long)sizeof (usb_alt_if_data_t), curr_value,
1375                     (void *)&orig_addr[i], (void *)&repl_array[curr_value]);
1376 
1377                 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value],
1378                     sizeof (usb_alt_if_data_t));
1379         }
1380 
1381         kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements);
1382         *array = repl_array;
1383         *n_elements = n_repl_elements;
1384 }
1385 
1386 
1387 /*
1388  * usba_order_tree:
1389  *      Take a tree as built by usba_build_descr_tree and make sure the key
1390  *      values of all elements match their indeces.  Proper order is implied.
1391  *
1392  * Arguments:
1393  *      state           - Pointer to this module's state structure.
1394  */
1395 static void
1396 usba_order_tree(usba_reg_state_t *state)
1397 {
1398         usb_cfg_data_t  *this_cfg;
1399         usb_if_data_t   *this_if;
1400         uint_t          n_cfgs = state->st_dev_n_cfg;
1401         uint_t          cfg;
1402         uint_t          which_if;
1403 
1404         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1405             "usba_order_tree:");
1406 
1407         for (cfg = 0; cfg < n_cfgs; cfg++) {
1408                 this_cfg = &state->st_dev_cfg[cfg];
1409 
1410                 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) {
1411                         this_if = this_cfg->cfg_if;
1412                         usba_make_alts_sparse(&this_if->if_alt,
1413                             &this_if->if_n_alt);
1414                 }
1415         }
1416 }
1417 
1418 
1419 /*
1420  * usb_free_descr_tree:
1421  *      Take down the configuration tree.  Called internally and can be called
1422  *      from a driver standalone to take the tree down while leaving the rest
1423  *      of the registration intact.
1424  *
1425  * Arguments:
1426  *      dip             - pointer to devinfo of the device
1427  *      dev_data        - pointer to registration data containing the tree.
1428  */
1429 void
1430 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1431 {
1432         usb_cfg_data_t *cfg_array;
1433         int n_cfgs;
1434         int cfg;
1435 
1436         if ((dip == NULL) || (dev_data == NULL)) {
1437 
1438                 return;
1439         }
1440         cfg_array = dev_data->dev_cfg;
1441         n_cfgs = dev_data->dev_n_cfg;
1442 
1443         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1444             "usb_free_descr_tree starting for %s%d",
1445             ddi_driver_name(dip), ddi_get_instance(dip));
1446 
1447         for (cfg = 0; cfg < n_cfgs; cfg++) {
1448                 if (cfg_array[cfg].cfg_if) {
1449                         usba_free_if_array(cfg_array[cfg].cfg_if,
1450                             cfg_array[cfg].cfg_n_if);
1451                 }
1452                 if (cfg_array[cfg].cfg_cvs) {
1453                         usba_free_cv_array(cfg_array[cfg].cfg_cvs,
1454                             cfg_array[cfg].cfg_n_cvs);
1455                 }
1456                 if (cfg_array[cfg].cfg_str) {
1457                         kmem_free(cfg_array[cfg].cfg_str,
1458                             cfg_array[cfg].cfg_strsize);
1459                 }
1460         }
1461 
1462         if (cfg_array) {
1463                 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs));
1464         }
1465 
1466         dev_data->dev_parse_level = USB_PARSE_LVL_NONE;
1467         dev_data->dev_n_cfg = 0;
1468         dev_data->dev_cfg = NULL;
1469         dev_data->dev_curr_cfg = NULL;
1470 
1471         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1472             "usb_free_descr_tree done");
1473 }
1474 
1475 
1476 /*
1477  * usba_free_if_array:
1478  *      Free a configuration's array of interface nodes and their subtrees of
1479  *      interface alternate, endpoint and c/v descriptors.
1480  *
1481  * Arguments:
1482  *      if_array        - pointer to array of interfaces to remove.
1483  *      n_ifs           - number of elements in the array to remove.
1484  */
1485 static void
1486 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs)
1487 {
1488         uint_t which_if;
1489         uint_t which_alt;
1490         uint_t n_alts;
1491         usb_alt_if_data_t *altif;
1492 
1493         for (which_if = 0; which_if < n_ifs; which_if++) {
1494                 n_alts = if_array[which_if].if_n_alt;
1495 
1496                 /* Every interface has at least one alternate. */
1497                 for (which_alt = 0; which_alt < n_alts; which_alt++) {
1498                         altif = &if_array[which_if].if_alt[which_alt];
1499                         usba_free_ep_array(altif->altif_ep, altif->altif_n_ep);
1500                         usba_free_cv_array(altif->altif_cvs,
1501                             altif->altif_n_cvs);
1502                         kmem_free(altif->altif_str, altif->altif_strsize);
1503                 }
1504 
1505                 kmem_free(if_array[which_if].if_alt,
1506                     (sizeof (usb_alt_if_data_t) * n_alts));
1507         }
1508 
1509         /* Free the interface array itself. */
1510         kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs));
1511 }
1512 
1513 
1514 /*
1515  * usba_free_ep_array:
1516  *      Free an array of endpoint nodes and their subtrees of c/v descriptors.
1517  *
1518  * Arguments:
1519  *      ep_array        - pointer to array of endpoints to remove.
1520  *      n_eps           - number of elements in the array to remove.
1521  */
1522 static void
1523 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps)
1524 {
1525         uint_t ep;
1526 
1527         for (ep = 0; ep < n_eps; ep++) {
1528                 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs);
1529         }
1530 
1531         kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps));
1532 }
1533 
1534 
1535 /*
1536  * usba_free_cv_array:
1537  *      Free an array of class/vendor (c/v) descriptor nodes.
1538  *
1539  * Arguments:
1540  *      cv_array        - pointer to array of c/v nodes to remove.
1541  *      n_cvs           - number of elements in the array to remove.
1542  */
1543 static void
1544 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs)
1545 {
1546         uint_t cv_node;
1547 
1548         /* Free data areas hanging off of each c/v descriptor. */
1549         for (cv_node = 0; cv_node < n_cvs; cv_node++) {
1550                 kmem_free(cv_array[cv_node].cvs_buf,
1551                     cv_array[cv_node].cvs_buf_len);
1552         }
1553 
1554         /* Free the array of cv descriptors. */
1555         kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs));
1556 }
1557 
1558 
1559 /*
1560  * usb_log_descr_tree:
1561  *      Log to the usba_debug_buf a descriptor tree as returned by
1562  *      usbai_register_client.
1563  *
1564  * Arguments:
1565  *      dev_data        - pointer to registration area containing the tree
1566  *      log_handle      - pointer to log handle to use for dumping.
1567  *      level           - print level, one of USB_LOG_L0 ... USB_LOG_L4
1568  *                        Please see usb_log(9F) for details.
1569  *      mask            - print mask.  Please see usb_log(9F) for details.
1570  *
1571  * Returns:
1572  *      USB_SUCCESS             - tree successfully dumped
1573  *      USB_INVALID_CONTEXT     - called from callback context
1574  *      USB_INVALID_ARGS        - bad arguments given
1575  */
1576 int
1577 usb_log_descr_tree(usb_client_dev_data_t *dev_data,
1578     usb_log_handle_t log_handle, uint_t level, uint_t mask)
1579 {
1580         return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask));
1581 }
1582 
1583 
1584 /*
1585  * usb_print_descr_tree:
1586  *      Print to the screen a descriptor tree as returned by
1587  *      usbai_register_client.
1588  *
1589  * Arguments:
1590  *      dip             - pointer to devinfo of the client
1591  *      dev_data        - pointer to registration area containing the tree
1592  *
1593  * Returns:
1594  *      USB_SUCCESS             - tree successfully dumped
1595  *      USB_INVALID_CONTEXT     - called from callback context
1596  *      USB_INVALID_ARGS        - bad arguments given
1597  */
1598 int
1599 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1600 {
1601         return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0));
1602 }
1603 
1604 
1605 /*
1606  * usba_dump_descr_tree:
1607  *      Dump a descriptor tree.
1608  *
1609  * Arguments:
1610  *      dip             - pointer to devinfo of the client.  Used when no
1611  *                        log_handle argument given.
1612  *      usb_reg         - pointer to registration area containing the tree
1613  *      log_handle      - pointer to log handle to use for dumping.  If NULL,
1614  *                        use internal log handle, which dumps to screen.
1615  *      level           - print level, one of USB_LOG_L0 ... USB_LOG_L4
1616  *                        Used only when log_handle provided.
1617  *      mask            - print mask, used when log_handle argument provided.
1618  *
1619  * Returns:
1620  *      USB_SUCCESS             - tree successfully dumped
1621  *      USB_INVALID_CONTEXT     - called from callback context
1622  *      USB_INVALID_ARGS        - bad arguments given
1623  */
1624 static int
1625 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg,
1626     usb_log_handle_t log_handle, uint_t level, uint_t mask)
1627 {
1628         usb_log_handle_t dump_handle;
1629         uint_t          dump_level;
1630         uint_t          dump_mask;
1631         int             which_config; /* Counters. */
1632         int             which_if;
1633         int             which_cv;
1634         usb_cfg_data_t  *config; /* ptr to current configuration tree node */
1635         usb_cfg_descr_t *config_descr; /* and its USB descriptor. */
1636         char            *string;
1637         char            *name_string = NULL;
1638         int             name_string_size;
1639 
1640         if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) {
1641 
1642                 return (USB_INVALID_ARGS);
1643         }
1644 
1645         /*
1646          * To keep calling this simple, kmem_zalloc with the sleep flag always.
1647          * This means no interrupt context is allowed.
1648          */
1649         if (servicing_interrupt()) {
1650 
1651                 return (USB_INVALID_CONTEXT);
1652         }
1653 
1654         string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
1655 
1656         if (log_handle != NULL) {
1657                 dump_level = level;
1658                 dump_mask = mask;
1659                 dump_handle = log_handle;
1660         } else {
1661                 dump_level = USB_LOG_L1;
1662                 dump_mask = DPRINT_MASK_ALL;
1663 
1664                 /* Build device name string. */
1665                 (void) snprintf(string, USB_MAXSTRINGLEN,
1666                     "Port%d", usb_get_addr(dip));
1667                 name_string_size = strlen(string) + 1;
1668                 name_string = kmem_zalloc(name_string_size, KM_SLEEP);
1669                 (void) strcpy(name_string, string);
1670 
1671                 /* Allocate a log handle specifying the name string. */
1672                 dump_handle = usb_alloc_log_hdl(NULL, name_string,
1673                     &dump_level, &dump_mask, NULL,
1674                     USB_FLAGS_SLEEP);
1675         }
1676 
1677         (void) usb_log(dump_handle, dump_level, dump_mask,
1678             "USB descriptor tree for %s %s",
1679             (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""),
1680             (usb_reg->dev_product != NULL ? usb_reg->dev_product : ""));
1681         if (usb_reg->dev_n_cfg == 0) {
1682                 (void) usb_log(dump_handle, dump_level, dump_mask,
1683                     "No descriptor tree present");
1684         } else {
1685                 (void) usb_log(dump_handle, dump_level, dump_mask,
1686                     "highest configuration found=%d", usb_reg->dev_n_cfg - 1);
1687         }
1688 
1689         for (which_config = 0; which_config < usb_reg->dev_n_cfg;
1690             which_config++) {
1691                 config = &usb_reg->dev_cfg[which_config];
1692                 config_descr = &config->cfg_descr;
1693                 if (config_descr->bLength == 0) {
1694 
1695                         continue;
1696                 }
1697                 if (dump_level == USB_LOG_L0) {
1698                         (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1699                 }
1700                 (void) usb_log(dump_handle, dump_level, dump_mask,
1701                     "Configuration #%d (Addr= 0x%p)", which_config,
1702                     (void *)config);
1703                 (void) usb_log(dump_handle, dump_level, dump_mask,
1704                     "String descr=%s", config->cfg_str);
1705                 (void) usb_log(dump_handle, dump_level, dump_mask,
1706                     "config descr: len=%d tp=%d totLen=%d numIf=%d "
1707                     "cfgVal=%d att=0x%x pwr=%d",
1708                     config_descr->bLength, config_descr->bDescriptorType,
1709                     config_descr->wTotalLength, config_descr->bNumInterfaces,
1710                     config_descr->bConfigurationValue,
1711                     config_descr->bmAttributes, config_descr->bMaxPower);
1712                 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) {
1713                         (void) usb_log(dump_handle, dump_level, dump_mask,
1714                             "usb_cfg_data_t shows max if=%d "
1715                             "and %d cv descr(s).",
1716                             config->cfg_n_if - 1, config->cfg_n_cvs);
1717                 }
1718 
1719                 for (which_if = 0; which_if < config->cfg_n_if;
1720                     which_if++) {
1721 
1722                         if (dump_level == USB_LOG_L0) {
1723                                 (void) usb_log(dump_handle, dump_level,
1724                                     dump_mask, " ");
1725                         }
1726                         (void) usb_log(dump_handle, dump_level, dump_mask,
1727                             "    interface #%d (0x%p)",
1728                             which_if, (void *)&config->cfg_if[which_if]);
1729                         usba_dump_if(&config->cfg_if[which_if],
1730                             dump_handle, dump_level, dump_mask, string);
1731                 }
1732 
1733                 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) {
1734                         (void) usb_log(dump_handle, dump_level, dump_mask,
1735                             "  config cv descriptor %d (Address=0x%p)",
1736                             which_cv, (void *)&config->cfg_cvs[which_cv]);
1737                         usba_dump_cv(&config->cfg_cvs[which_cv],
1738                             dump_handle, dump_level, dump_mask, string, 4);
1739                 }
1740         }
1741 
1742         (void) usb_log(dump_handle, dump_level, dump_mask,
1743             "Returning dev_curr_cfg:0x%p, dev_curr_if:%d",
1744             (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if);
1745 
1746         if (log_handle == NULL) {
1747                 usb_free_log_hdl(dump_handle);
1748         }
1749         if (name_string != NULL) {
1750                 kmem_free(name_string, name_string_size);
1751         }
1752         kmem_free(string, USB_MAXSTRINGLEN);
1753 
1754         return (USB_SUCCESS);
1755 }
1756 
1757 
1758 /*
1759  * usba_dump_if:
1760  *      Dump an interface node and its branches.
1761  *
1762  * Arguments:
1763  *      which_if        - interface node to dump
1764  *      dump_handle     - write data through this log handle
1765  *      dump_level      - level passed to usb_log
1766  *      dump_mask       - mask passed to usb_log
1767  *      string          - temporary area used for processing
1768  *
1769  */
1770 static void
1771 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle,
1772     uint_t dump_level, uint_t dump_mask, char *string)
1773 {
1774         int             which_alt;      /* Number of alt being dumped */
1775         usb_alt_if_data_t *alt;         /* Pointer to it. */
1776         usb_if_descr_t *if_descr;       /* Pointer to its USB descr. */
1777         int             which_ep;       /* Endpoint counter. */
1778         int             which_cv;       /* C/V descr counter. */
1779 
1780         for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) {
1781                 alt = &which_if->if_alt[which_alt];
1782                 if_descr = &alt->altif_descr;
1783 
1784                 if (if_descr->bLength == 0) {
1785 
1786                         continue;
1787                 }
1788                 if (dump_level == USB_LOG_L0) {
1789                         (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1790                 }
1791                 (void) usb_log(dump_handle, dump_level, dump_mask,
1792                     "\tAlt #%d (0x%p)", which_alt, (void *)alt);
1793                 (void) usb_log(dump_handle, dump_level, dump_mask,
1794                     "\tString descr=%s", alt->altif_str);
1795                 (void) usb_log(dump_handle, dump_level, dump_mask,
1796                     "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d "
1797                     "cls=%d sub=%d proto=%d",
1798                     if_descr->bLength,
1799                     if_descr->bDescriptorType, if_descr->bInterfaceNumber,
1800                     if_descr->bAlternateSetting, if_descr->bNumEndpoints,
1801                     if_descr->bInterfaceClass, if_descr->bInterfaceSubClass,
1802                     if_descr->bInterfaceProtocol);
1803 
1804                 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) {
1805                         (void) usb_log(dump_handle, dump_level, dump_mask,
1806                             "\tusb_alt_if_data_t shows max ep=%d "
1807                             "and %d cv descr(s).",
1808                             alt->altif_n_ep - 1, alt->altif_n_cvs);
1809                 }
1810 
1811                 for (which_ep = 0; which_ep < alt->altif_n_ep;
1812                     which_ep++) {
1813                         if (alt->altif_ep[which_ep].ep_descr.bLength == 0) {
1814 
1815                                 continue;
1816                         }
1817                         if (dump_level == USB_LOG_L0) {
1818                                 (void) usb_log(dump_handle, dump_level,
1819                                     dump_mask, " ");
1820                         }
1821                         usba_dump_ep(which_ep, &alt->altif_ep[which_ep],
1822                             dump_handle, dump_level, dump_mask, string);
1823                 }
1824 
1825                 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) {
1826                         if (dump_level == USB_LOG_L0) {
1827                                 (void) usb_log(dump_handle, dump_level,
1828                                     dump_mask, " ");
1829                         }
1830                         (void) usb_log(dump_handle, dump_level, dump_mask,
1831                             "\talt cv descriptor #%d (0x%p), size=%d",
1832                             which_cv, (void *)&alt->altif_cvs[which_cv],
1833                             alt->altif_cvs[which_cv].cvs_buf_len);
1834                         usba_dump_cv(&alt->altif_cvs[which_cv],
1835                             dump_handle, dump_level, dump_mask, string, 2);
1836                 }
1837         }
1838 }
1839 
1840 
1841 /*
1842  * usba_dump_ep:
1843  *      Dump an endpoint node and its branches.
1844  *
1845  * Arguments:
1846  *      which_ep        - index to display
1847  *      ep              - endpoint node to dump
1848  *      dump_handle     - write data through this log handle
1849  *      dump_level      - level passed to usb_log
1850  *      dump_mask       - mask passed to usb_log
1851  *      string          - temporary area used for processing
1852  *
1853  */
1854 static void
1855 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle,
1856     uint_t dump_level, uint_t dump_mask, char *string)
1857 {
1858         int which_cv;
1859         usb_ep_descr_t *ep_descr = &ep->ep_descr;
1860 
1861         (void) usb_log(dump_handle, dump_level, dump_mask,
1862             "\t    endpoint[%d], epaddr=0x%x (0x%p)", which_ep,
1863             ep_descr->bEndpointAddress, (void *)ep);
1864         (void) usb_log(dump_handle, dump_level, dump_mask,
1865             "\t    len=%d type=%d attr=0x%x pktsize=%d interval=%d",
1866             ep_descr->bLength, ep_descr->bDescriptorType,
1867             ep_descr->bmAttributes, ep_descr->wMaxPacketSize,
1868             ep_descr->bInterval);
1869         if (ep->ep_n_cvs > 0) {
1870                 (void) usb_log(dump_handle, dump_level, dump_mask,
1871                     "\t    usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs);
1872         }
1873 
1874         for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) {
1875                 if (dump_level == USB_LOG_L0) {
1876                         (void) usb_log(dump_handle, dump_level,
1877                             dump_mask, " ");
1878                 }
1879                 (void) usb_log(dump_handle, dump_level, dump_mask,
1880                     "\t    endpoint cv descriptor %d (0x%p), size=%d",
1881                     which_cv, (void *)&ep->ep_cvs[which_cv],
1882                     ep->ep_cvs[which_cv].cvs_buf_len);
1883                 usba_dump_cv(&ep->ep_cvs[which_cv],
1884                     dump_handle, dump_level, dump_mask, string, 3);
1885         }
1886 }
1887 
1888 
1889 /*
1890  * usba_dump_cv:
1891  *      Dump a raw class or vendor specific descriptor.
1892  *
1893  * Arguments:
1894  *      cv_node         - pointer to the descriptor to dump
1895  *      dump_handle     - write data through this log handle
1896  *      dump_level      - level passed to usb_log
1897  *      dump_mask       - mask passed to usb_log
1898  *      string          - temporary area used for processing
1899  *      indent          - number of tabs to indent output
1900  *
1901  */
1902 static void
1903 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle,
1904     uint_t dump_level, uint_t dump_mask, char *string, int indent)
1905 {
1906         if (cv_node) {
1907                 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent,
1908                     dump_handle, dump_level, dump_mask, string,
1909                     USB_MAXSTRINGLEN);
1910         }
1911 }
1912 
1913 
1914 /*
1915  * usba_dump_bin:
1916  *      Generic byte dump function.
1917  *
1918  * Arguments:
1919  *      data            - pointer to the data to dump
1920  *      max_bytes       - amount of data to dump
1921  *      indent          - number of indentation levels
1922  *      dump_handle     - write data through this log handle
1923  *      dump_level      - level passed to usb_log
1924  *      dump_mask       - mask passed to usb_log
1925  *      buffer          - temporary area used for processing
1926  *      bufferlen       - size of the temporary string area
1927  *
1928  */
1929 static void
1930 usba_dump_bin(uint8_t *data, int max_bytes, int indent,
1931     usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask,
1932     char *buffer, int bufferlen)
1933 {
1934         int i;
1935         int bufoffset = 0;
1936         int nexthere;
1937 
1938         if ((indent * SPACES_PER_INDENT) >
1939             (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) {
1940                 (void) usb_log(dump_handle, dump_level, dump_mask,
1941                     "Offset to usb_dump_bin must be %d or less.  "
1942                     "Setting to 0.\n",
1943                     (bufferlen - (BINDUMP_BYTES_PER_LINE * 3)));
1944                 indent = 0;
1945         }
1946 
1947         /* Assume a tab is 2 four-space units. */
1948         for (i = 0; i < indent/2; i++) {
1949                 buffer[bufoffset] = '\t';
1950                 bufoffset++;
1951         }
1952 
1953         if (indent % 2) {
1954                 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR);
1955                 bufoffset += SPACES_PER_INDENT;
1956         }
1957 
1958         i = 0;                  /* Num dumped bytes put on this line. */
1959         nexthere = bufoffset;
1960         while (i < max_bytes) {
1961                 (void) sprintf(&buffer[nexthere], "%2x ", *data++);
1962                 nexthere += 3;
1963                 i++;
1964                 if (!(i % BINDUMP_BYTES_PER_LINE)) {
1965                         buffer[nexthere] = '\0';
1966                         (void) usb_log(dump_handle, dump_level, dump_mask,
1967                             buffer);
1968                         nexthere = bufoffset;
1969                 }
1970         }
1971 
1972         if (nexthere > bufoffset) {
1973                 buffer[nexthere] = '\0';
1974                 (void) usb_log(dump_handle, dump_level, dump_mask, buffer);
1975         }
1976 }
1977 
1978 /*
1979  * usb_ep_xdescr_fill:
1980  *
1981  * Fills in the extended endpoint descriptor based on data from the
1982  * configuration tree.
1983  *
1984  * Arguments:
1985  *      version         - Should be USB_EP_XDESCR_CURRENT_VERSION
1986  *      dip             - devinfo pointer
1987  *      ep_data         - endpoint data pointer
1988  *      ep_xdesc        - An extended descriptor structure, filled upon
1989  *                        successful completion.
1990  *
1991  * Return values:
1992  *      USB_SUCCESS      - filling data succeeded
1993  *      USB_INVALID_ARGS - invalid arguments
1994  */
1995 int
1996 usb_ep_xdescr_fill(uint_t version, dev_info_t *dip, usb_ep_data_t *ep_data,
1997     usb_ep_xdescr_t *ep_xdescr)
1998 {
1999         if (version != USB_EP_XDESCR_VERSION_ONE) {
2000 
2001                 return (USB_INVALID_ARGS);
2002         }
2003 
2004         if (dip == NULL || ep_data == NULL || ep_xdescr == NULL) {
2005 
2006                 return (USB_INVALID_ARGS);
2007         }
2008 
2009         bzero(ep_xdescr, sizeof (usb_ep_xdescr_t));
2010         ep_xdescr->uex_version = version;
2011         ep_xdescr->uex_ep = ep_data->ep_descr;
2012         if (ep_data->ep_ss_valid == B_TRUE) {
2013                 ep_xdescr->uex_flags |= USB_EP_XFLAGS_SS_COMP;
2014                 ep_xdescr->uex_ep_ss = ep_data->ep_ss_comp;
2015         }
2016 
2017         return (USB_SUCCESS);
2018 }