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