xref: /illumos-gate/usr/src/uts/common/io/usb/usba/usbai_register.c (revision 495ee6847d0d3e288f47ba026d98a830e51cbc06)
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 (c) 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 }
2019