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