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