1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 */
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 */
107 int usb_log_descr_tree(usb_client_dev_data_t *, usb_log_handle_t,
108 uint_t, uint_t);
109
110 /* Debug stuff */
111 usb_log_handle_t usbai_reg_log_handle;
112 uint_t usbai_register_errlevel = USB_LOG_L2;
113 uint_t usbai_register_dump_errlevel = USB_LOG_L2;
114 uint_t usbai_register_errmask = (uint_t)-1;
115
116 /* Function prototypes */
117 static int usba_build_descr_tree(dev_info_t *, usba_device_t *,
118 usb_client_dev_data_t *);
119 static void usba_process_cfg_descr(usba_reg_state_t *);
120 static int usba_process_if_descr(usba_reg_state_t *, boolean_t *);
121 static int usba_process_ep_descr(usba_reg_state_t *);
122 static int usba_process_cv_descr(usba_reg_state_t *);
123 static int usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
124 usba_reg_state_t *state);
125 static void* usba_kmem_realloc(void *, int, int);
126 static void usba_augment_array(void **, uint_t, uint_t);
127 static void usba_make_alts_sparse(usb_alt_if_data_t **, uint_t *);
128
129 static void usba_order_tree(usba_reg_state_t *);
130
131 static void usba_free_if_array(usb_if_data_t *, uint_t);
132 static void usba_free_ep_array(usb_ep_data_t *, uint_t);
133 static void usba_free_cv_array(usb_cvs_data_t *, uint_t);
134
135 static int usba_dump_descr_tree(dev_info_t *, usb_client_dev_data_t *,
136 usb_log_handle_t, uint_t, uint_t);
137 static void usba_dump_if(usb_if_data_t *, usb_log_handle_t,
138 uint_t, uint_t, char *);
139 static void usba_dump_ep(uint_t, usb_ep_data_t *, usb_log_handle_t, uint_t,
140 uint_t, char *);
141 static void usba_dump_cv(usb_cvs_data_t *, usb_log_handle_t, uint_t, uint_t,
142 char *, int);
143 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t,
144 uint_t, uint_t, char *, int);
145
146 /* Framework initialization. */
147 void
usba_usbai_register_initialization()148 usba_usbai_register_initialization()
149 {
150 usbai_reg_log_handle = usb_alloc_log_hdl(NULL, "usbreg",
151 &usbai_register_errlevel,
152 &usbai_register_errmask, NULL,
153 0);
154
155 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
156 "usba_usbai_register_initialization");
157 }
158
159
160 /* Framework destruction. */
161 void
usba_usbai_register_destroy()162 usba_usbai_register_destroy()
163 {
164 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
165 "usba_usbai_register destroy");
166
167 usb_free_log_hdl(usbai_reg_log_handle);
168 }
169
170
171 /*
172 * usb_client_attach:
173 *
174 * Arguments:
175 * dip - pointer to devinfo node of the client
176 * version - USBA registration version number
177 * flags - None used
178 *
179 * Return Values:
180 * USB_SUCCESS - attach succeeded
181 * USB_INVALID_ARGS - received null dip
182 * USB_INVALID_VERSION - version argument is incorrect.
183 * USB_FAILURE - other internal failure
184 */
185 /*ARGSUSED*/
186 int
usb_client_attach(dev_info_t * dip,uint_t version,usb_flags_t flags)187 usb_client_attach(dev_info_t *dip, uint_t version, usb_flags_t flags)
188 {
189 int rval;
190 usba_device_t *usba_device;
191
192 if (dip == NULL) {
193
194 return (USB_INVALID_ARGS);
195 }
196
197 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
198 "usb_client attach:");
199
200 usba_device = usba_get_usba_device(dip);
201
202 /*
203 * Allow exact match for legacy (DDK 0.8/9) drivers, or same major
204 * VERSion and smaller or same minor version for non-legacy drivers.
205 */
206 if ((version !=
207 USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) &&
208 ((USBA_GET_MAJOR(version) != USBA_MAJOR_VER) ||
209 (USBA_GET_MINOR(version) > USBA_MINOR_VER))) {
210 USB_DPRINTF_L1(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
211 "Incorrect USB driver version for %s%d: found: %d.%d, "
212 "expecting %d.%d",
213 ddi_driver_name(dip), ddi_get_instance(dip),
214 USBA_GET_MAJOR(version), USBA_GET_MINOR(version),
215 USBA_MAJOR_VER, USBA_MINOR_VER);
216
217 return (USB_INVALID_VERSION);
218 }
219
220 if (version == USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) {
221 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
222 "Accepting legacy USB driver version %d.%d for %s%d",
223 USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER,
224 ddi_driver_name(dip), ddi_get_instance(dip));
225 }
226
227 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-major",
228 USBA_GET_MAJOR(version));
229 if (rval != DDI_PROP_SUCCESS) {
230
231 return (USB_FAILURE);
232 }
233 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-minor",
234 USBA_GET_MINOR(version));
235 if (rval != DDI_PROP_SUCCESS) {
236
237 return (USB_FAILURE);
238 }
239
240 mutex_enter(&usba_device->usb_mutex);
241 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
242 usba_device->usb_client_flags[usba_get_ifno(dip)] |=
243 USBA_CLIENT_FLAG_ATTACH;
244 usba_device->usb_client_attach_list->dip = dip;
245 }
246 mutex_exit(&usba_device->usb_mutex);
247
248 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
249 "usb_client attach: done");
250
251 return (USB_SUCCESS);
252 }
253
254
255 /*
256 * usb_client_detach:
257 * free dev_data is reg != NULL, not much else to do
258 *
259 * Arguments:
260 * dip - pointer to devinfo node of the client
261 * reg - return registration data at this address
262 */
263 void
usb_client_detach(dev_info_t * dip,usb_client_dev_data_t * reg)264 usb_client_detach(dev_info_t *dip, usb_client_dev_data_t *reg)
265 {
266 usba_device_t *usba_device = usba_get_usba_device(dip);
267
268 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
269 "usb_client_detach:");
270
271 if (dip) {
272 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
273 "Unregistering usb client %s%d: reg=0x%p",
274 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg);
275
276 usb_free_dev_data(dip, reg);
277
278 mutex_enter(&usba_device->usb_mutex);
279 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
280 usba_device->usb_client_flags[usba_get_ifno(dip)] &=
281 ~USBA_CLIENT_FLAG_ATTACH;
282 }
283 mutex_exit(&usba_device->usb_mutex);
284 }
285
286 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
287 "usb_client_detach done");
288 }
289
290
291 /*
292 * usb_register_client (deprecated):
293 * The client registers with USBA during attach.
294 */
295 /*ARGSUSED*/
296 int
usb_register_client(dev_info_t * dip,uint_t version,usb_client_dev_data_t ** reg,usb_reg_parse_lvl_t parse_level,usb_flags_t flags)297 usb_register_client(dev_info_t *dip, uint_t version,
298 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level,
299 usb_flags_t flags)
300 {
301 int rval = usb_client_attach(dip, version, flags);
302
303 if (rval == USB_SUCCESS) {
304 rval = usb_get_dev_data(dip, reg, parse_level, flags);
305
306 if (rval != USB_SUCCESS) {
307 usb_client_detach(dip, NULL);
308 }
309 }
310
311 return (rval);
312 }
313
314
315 /*
316 * usb_unregister_client (deprecated):
317 * Undo the makings of usb_get_dev_data(). Free memory if allocated.
318 *
319 * Arguments:
320 * dip - pointer to devinfo node of the client
321 * reg - pointer to registration data to be freed
322 */
323 void
usb_unregister_client(dev_info_t * dip,usb_client_dev_data_t * reg)324 usb_unregister_client(dev_info_t *dip, usb_client_dev_data_t *reg)
325 {
326 usb_client_detach(dip, reg);
327 }
328
329
330 /*
331 * usb_get_dev_data:
332 * On completion, the registration data has been initialized.
333 * Most data items are straightforward.
334 * Among the items returned in the data is the tree of
335 * parsed descriptors, in dev_cfg; the number of configurations parsed,
336 * in dev_n_cfg; a pointer to the current configuration in the tree,
337 * in dev_curr_cfg; the index of the first valid interface in the
338 * tree, in dev_curr_if, and a parse level that accurately reflects what
339 * is in the tree, in dev_parse_level.
340 *
341 * This routine sets up directly-initialized fields, and calls
342 * usb_build_descr_tree() to parse the raw descriptors and initialize the
343 * tree.
344 *
345 * Parse_level determines the extent to which the tree is built. It has
346 * the following values:
347 *
348 * USB_PARSE_LVL_NONE - Build no tree. dev_n_cfg will return 0, dev_cfg
349 * and dev_curr_cfg will return NULL.
350 * USB_PARSE_LVL_IF - Parse configured interface only, if configuration#
351 * and interface properties are set (as when different
352 * interfaces are viewed by the OS as different device
353 * instances). If an OS device instance is set up to
354 * represent an entire physical device, this works
355 * like USB_PARSE_LVL_ALL.
356 * USB_PARSE_LVL_CFG - Parse entire configuration of configured interface
357 * only. This is like USB_PARSE_LVL_IF except entire
358 * configuration is returned.
359 * USB_PARSE_LVL_ALL - Parse entire device (all configurations), even
360 * when driver is bound to a single interface of a
361 * single configuration.
362 *
363 * No tree is built for root hubs, regardless of parse_level.
364 *
365 * Arguments:
366 * dip - pointer to devinfo node of the client
367 * version - USBA registration version number
368 * reg - return registration data at this address
369 * parse_level - See above
370 * flags - None used
371 *
372 * Return Values:
373 * USB_SUCCESS - usb_get_dev_data succeeded
374 * USB_INVALID_ARGS - received null dip or reg argument
375 * USB_INVALID_CONTEXT - called from callback context
376 * USB_FAILURE - bad descriptor info or other internal failure
377 *
378 * Note: The non-standard USB descriptors are returned in RAW format.
379 * returns initialized registration data. Most data items are clear.
380 * Among the items returned is the tree of parsed descriptors in dev_cfg;
381 * and the number of configurations parsed in dev_n_cfg.
382 *
383 * The registration data is not shared. each client receives its own
384 * copy.
385 */
386 /*ARGSUSED*/
387 int
usb_get_dev_data(dev_info_t * dip,usb_client_dev_data_t ** reg,usb_reg_parse_lvl_t parse_level,usb_flags_t flags)388 usb_get_dev_data(dev_info_t *dip,
389 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level,
390 usb_flags_t flags)
391 {
392 usb_client_dev_data_t *usb_reg = NULL;
393 char *tmpbuf = NULL;
394 usba_device_t *usba_device;
395 int rval = USB_SUCCESS;
396
397 if ((dip == NULL) || (reg == NULL)) {
398
399 return (USB_INVALID_ARGS);
400 }
401
402 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
403 "usb_get_dev_data: %s%d",
404 ddi_driver_name(dip), ddi_get_instance(dip));
405
406 *reg = NULL;
407
408 /* did the client attach first? */
409 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
410 "driver-major", -1) == -1) {
411
412 return (USB_INVALID_VERSION);
413 }
414 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
415 "driver-minor", -1) == -1) {
416
417 return (USB_INVALID_VERSION);
418 }
419
420 usb_reg = kmem_zalloc(sizeof (usb_client_dev_data_t), KM_SLEEP);
421 usba_device = usba_get_usba_device(dip);
422 usb_reg->dev_descr = usba_device->usb_dev_descr;
423 usb_reg->dev_default_ph = usba_get_dflt_pipe_handle(dip);
424 if (usb_reg->dev_default_ph == NULL) {
425 kmem_free(usb_reg, sizeof (usb_client_dev_data_t));
426
427 return (USB_FAILURE);
428 }
429
430 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", (void *)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 */
551 void
usb_free_dev_data(dev_info_t * dip,usb_client_dev_data_t * reg)552 usb_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), (void *)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 (void *)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 * 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
usba_build_descr_tree(dev_info_t * dip,usba_device_t * usba_device,usb_client_dev_data_t * usb_reg)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 case USB_DESCR_TYPE_STRING:
803 USB_DPRINTF_L2(DPRINT_MASK_ALL,
804 usbai_reg_log_handle,
805 "usb_get_dev_data: "
806 "Found unexpected str descr at addr 0x%p",
807 (void *)state.st_curr_raw_descr);
808
809 break; /* Shouldn't be any here. Skip. */
810
811 default:
812 /*
813 * Treat all other descr as class/vendor
814 * specific. Skip if c/vs of a specific
815 * interface are desired and this c/v is
816 * associated with a different one.
817 * Device level c/vs should always be
818 * processed, e.g., the security descrs
819 * for the Host Wire Adapter.
820 */
821 if ((state.st_last_processed_descr_type ==
822 USB_DESCR_TYPE_CFG) ||
823 (process_this_if_tree == B_TRUE)) {
824 if (usba_process_cv_descr(&state) !=
825 USB_SUCCESS) {
826
827 return (USB_FAILURE);
828 }
829 }
830 }
831
832 state.st_curr_raw_descr += state.st_curr_raw_descr_len;
833 cfg_len_so_far += state.st_curr_raw_descr_len;
834
835 } while (state.st_curr_raw_descr < last_byte);
836 }
837
838 /* Make tree sparse, and put elements in order. */
839 usba_order_tree(&state);
840
841 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
842 "usba_build_descr_tree done");
843
844 return (USB_SUCCESS);
845 }
846
847
848 /*
849 * usba_process_cfg_descr:
850 * Set up a configuration tree node based on a raw config descriptor.
851 *
852 * Arguments:
853 * state - Pointer to this module's state structure.
854 *
855 * Returns:
856 * B_TRUE: the descr processed corresponds to a requested configuration.
857 * B_FALSE: the descr processed does not correspond to a requested config.
858 */
859 static void
usba_process_cfg_descr(usba_reg_state_t * state)860 usba_process_cfg_descr(usba_reg_state_t *state)
861 {
862 usb_cfg_data_t *curr_cfg;
863
864 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
865 "usba_process_cfg_descr starting");
866
867 curr_cfg = state->st_curr_cfg =
868 &state->st_dev_cfg[state->st_dev_n_cfg++];
869
870 /* Parse and store config descriptor proper in the tree. */
871 (void) usb_parse_data("2cs5c",
872 state->st_curr_raw_descr, state->st_curr_raw_descr_len,
873 &curr_cfg->cfg_descr,
874 sizeof (usb_cfg_descr_t));
875
876 state->st_total_cfg_length = curr_cfg->cfg_descr.wTotalLength;
877
878 if (state->st_curr_cfg_str != NULL) {
879 curr_cfg->cfg_strsize = strlen(state->st_curr_cfg_str) + 1;
880 curr_cfg->cfg_str = kmem_zalloc(curr_cfg->cfg_strsize,
881 KM_SLEEP);
882 (void) strcpy(curr_cfg->cfg_str, state->st_curr_cfg_str);
883 }
884
885 curr_cfg->cfg_n_if = curr_cfg->cfg_descr.bNumInterfaces;
886 curr_cfg->cfg_if = kmem_zalloc((curr_cfg->cfg_n_if *
887 sizeof (usb_if_data_t)), KM_SLEEP);
888
889 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
890 "usba_process_cfg_descr done");
891 }
892
893
894 /*
895 * usba_process_if_descr:
896 * This processes a raw interface descriptor, and sets up an analogous
897 * interface node and child "alternate" nodes (each containing an
898 * interface descriptor) in the descriptor tree.
899 *
900 * It groups all descriptors with the same bInterfaceNumber (alternates)
901 * into an array. It makes entries in an interface array, each of which
902 * points to an array of alternates.
903 *
904 * Arguments:
905 * state - Pointer to this module's state structure.
906 * requested_if - Address into which the following is returned:
907 * B_TRUE - the processed descr is of a requested interface.
908 * B_FALSE - the processed descr if of a non-requested interface.
909 *
910 * Returns:
911 * USB_SUCCESS: Descriptor is successfully parsed.
912 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
913 */
914 static int
usba_process_if_descr(usba_reg_state_t * state,boolean_t * requested_if)915 usba_process_if_descr(usba_reg_state_t *state, boolean_t *requested_if)
916 {
917 char *string;
918 usb_if_descr_t *new_if_descr;
919 usba_device_t *usba_device = usba_get_usba_device(state->dip);
920 int is_root_hub = (usba_device->usb_addr == ROOT_HUB_ADDR);
921
922 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
923 "usba_process_if_descr starting");
924
925 /* No config preceeds this interface. */
926 if (state->st_curr_cfg == NULL) {
927 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
928 "usba_process_if_descr found interface after no config.");
929
930 return (USB_FAILURE);
931 }
932
933 new_if_descr = kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP);
934
935 /* Strictly speaking, unpacking is not necessary. Could use bcopy. */
936 (void) usb_parse_data("9c", state->st_curr_raw_descr,
937 state->st_curr_raw_descr_len,
938 new_if_descr, sizeof (usb_if_descr_t));
939
940 /* Check the interface number in case of a malfunction device */
941 if (new_if_descr->bInterfaceNumber >= state->st_curr_cfg->cfg_n_if) {
942 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
943 "usba_process_if_descr: bInterfaceNumber=%d is not "
944 "a valid one", new_if_descr->bInterfaceNumber);
945 kmem_free(new_if_descr, sizeof (usb_if_descr_t));
946
947 *requested_if = B_FALSE;
948
949 return (USB_SUCCESS);
950 }
951 *requested_if = B_TRUE;
952
953 /* Not a requested interface. */
954 if ((state->st_if_to_build != new_if_descr->bInterfaceNumber) &&
955 (state->st_if_to_build != USBA_ALL)) {
956 *requested_if = B_FALSE;
957
958 } else {
959 usb_alt_if_data_t *alt_array;
960 uint_t alt_index;
961
962 /* Point to proper interface node, based on num in descr. */
963 state->st_curr_if =
964 &state->st_curr_cfg->cfg_if[new_if_descr->bInterfaceNumber];
965
966 /* Make room for new alternate. */
967 alt_index = state->st_curr_if->if_n_alt;
968 alt_array = state->st_curr_if->if_alt;
969 usba_augment_array((void **)(&alt_array), alt_index,
970 sizeof (usb_alt_if_data_t));
971
972 /* Ptr to the current alt, may be used to attach a c/v to it. */
973 state->st_curr_alt = &alt_array[alt_index];
974
975 bcopy(new_if_descr, &(alt_array[alt_index++].altif_descr),
976 sizeof (usb_if_descr_t));
977 state->st_curr_if->if_alt = alt_array;
978 state->st_curr_if->if_n_alt = alt_index;
979
980 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
981 if (!is_root_hub) {
982 (void) usb_get_string_descr(state->dip, USB_LANG_ID,
983 state->st_curr_alt->altif_descr.iInterface,
984 string, USB_MAXSTRINGLEN);
985 }
986 if (string[0] == '\0') {
987 (void) strcpy(string, "<none>");
988 }
989 state->st_curr_alt->altif_strsize = strlen(string) + 1;
990 state->st_curr_alt->altif_str = kmem_zalloc(
991 state->st_curr_alt->altif_strsize, KM_SLEEP);
992 (void) strcpy(state->st_curr_alt->altif_str, string);
993 kmem_free(string, USB_MAXSTRINGLEN);
994 }
995
996 kmem_free(new_if_descr, sizeof (usb_if_descr_t));
997
998 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
999 "usba_process_if_descr done");
1000
1001 return (USB_SUCCESS);
1002 }
1003
1004
1005 /*
1006 * usba_process_ep_descr:
1007 * This processes a raw endpoint descriptor, and sets up an analogous
1008 * endpoint descriptor node in the descriptor tree.
1009 *
1010 * Arguments:
1011 * state - Pointer to this module's state structure.
1012 *
1013 * Returns:
1014 * USB_SUCCESS: Descriptor is successfully parsed.
1015 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1016 */
1017 static int
usba_process_ep_descr(usba_reg_state_t * state)1018 usba_process_ep_descr(usba_reg_state_t *state)
1019 {
1020 usb_alt_if_data_t *curr_alt = state->st_curr_alt;
1021
1022 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1023 "usba_process_ep_descr starting");
1024
1025 /* No interface preceeds this endpoint. */
1026 if (state->st_curr_alt == NULL) {
1027 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1028 "usba_process_ep_descr: no requested alt before endpt.");
1029
1030 return (USB_FAILURE);
1031 }
1032
1033 usba_augment_array((void **)(&curr_alt->altif_ep),
1034 curr_alt->altif_n_ep, sizeof (usb_ep_data_t));
1035
1036 /* Ptr to the current endpt, may be used to attach a c/v to it. */
1037 state->st_curr_ep = &curr_alt->altif_ep[curr_alt->altif_n_ep++];
1038
1039 (void) usb_parse_data("4csc", state->st_curr_raw_descr,
1040 state->st_curr_raw_descr_len,
1041 &state->st_curr_ep->ep_descr, sizeof (usb_ep_descr_t));
1042
1043 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1044 "usba_process_ep_descr done");
1045
1046 return (USB_SUCCESS);
1047 }
1048
1049
1050 /*
1051 * usba_process_cv_descr:
1052 * This processes a raw endpoint descriptor, and sets up an analogous
1053 * endpoint descriptor in the descriptor tree. C/Vs are associated with
1054 * other descriptors they follow in the raw data.
1055 * last_processed_descr_type indicates the type of descr this c/v follows.
1056 *
1057 * Arguments:
1058 * state - Pointer to this module's state structure.
1059 *
1060 * Returns:
1061 * USB_SUCCESS: Descriptor is successfully parsed.
1062 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1063 */
1064 static int
usba_process_cv_descr(usba_reg_state_t * state)1065 usba_process_cv_descr(usba_reg_state_t *state)
1066 {
1067 usb_cvs_data_t *curr_cv_descr;
1068 usb_cvs_data_t **cvs_ptr = NULL;
1069 uint_t *n_cvs_ptr;
1070
1071 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1072 "usba_process_cv_descr starting. Processing c/v for descr type %d",
1073 state->st_last_processed_descr_type);
1074
1075 /*
1076 * Attach the c/v to a node based on the last descr type processed.
1077 * Save handles to appropriate c/v node array and count to update.
1078 */
1079 switch (state->st_last_processed_descr_type) {
1080 case USB_DESCR_TYPE_CFG:
1081 n_cvs_ptr = &state->st_curr_cfg->cfg_n_cvs;
1082 cvs_ptr = &state->st_curr_cfg->cfg_cvs;
1083 break;
1084
1085 case USB_DESCR_TYPE_IF:
1086 n_cvs_ptr = &state->st_curr_alt->altif_n_cvs;
1087 cvs_ptr = &state->st_curr_alt->altif_cvs;
1088 break;
1089
1090 case USB_DESCR_TYPE_EP:
1091 n_cvs_ptr = &state->st_curr_ep->ep_n_cvs;
1092 cvs_ptr = &state->st_curr_ep->ep_cvs;
1093 break;
1094
1095 default:
1096 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle,
1097 "usba_process_cv_descr: Type of last descriptor unknown. ");
1098
1099 return (USB_FAILURE);
1100 }
1101
1102 usba_augment_array((void **)cvs_ptr, *n_cvs_ptr,
1103 sizeof (usb_cvs_data_t));
1104 curr_cv_descr = &(*cvs_ptr)[(*n_cvs_ptr)++];
1105
1106 curr_cv_descr->cvs_buf =
1107 kmem_zalloc(state->st_curr_raw_descr_len, KM_SLEEP);
1108 curr_cv_descr->cvs_buf_len = state->st_curr_raw_descr_len;
1109 bcopy(state->st_curr_raw_descr, curr_cv_descr->cvs_buf,
1110 state->st_curr_raw_descr_len);
1111
1112 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1113 "usba_process_cv_descr done");
1114
1115 return (USB_SUCCESS);
1116 }
1117
1118
1119 /*
1120 * usba_set_parse_values:
1121 * Based on parse level, set the configuration(s) and interface(s) to build
1122 *
1123 * Returned configuration value can be USBA_ALL indicating to build all
1124 * configurations. Likewise for the returned interface value.
1125 *
1126 * Arguments:
1127 * dip - pointer to devinfo of the device
1128 * usba_device - pointer to usba_device structure of the device
1129 * state - Pointer to this module's state structure.
1130 * if no specific config specified, default to all config
1131 * if no specific interface specified, default to all.
1132 * if_to_build and config_to_build are modified.
1133 * dev_parse_level may be modified.
1134 *
1135 * Returns:
1136 * USB_SUCCESS - success
1137 * USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
1138 */
1139 static int
usba_set_parse_values(dev_info_t * dip,usba_device_t * usba_device,usba_reg_state_t * state)1140 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
1141 usba_reg_state_t *state)
1142 {
1143 /* Default to *all* in case configuration# prop not set. */
1144 mutex_enter(&usba_device->usb_mutex);
1145 state->st_cfg_to_build = usba_device->usb_active_cfg_ndx;
1146 mutex_exit(&usba_device->usb_mutex);
1147 if (state->st_cfg_to_build == USBA_DEV_CONFIG_INDEX_UNDEFINED) {
1148 state->st_cfg_to_build = USBA_ALL;
1149 }
1150 state->st_if_to_build = usb_get_if_number(dip);
1151
1152 switch (state->st_dev_parse_level) {
1153 case USB_PARSE_LVL_ALL: /* Parse all configurations */
1154 state->st_cfg_to_build = USBA_ALL;
1155 state->st_if_to_build = USBA_ALL;
1156 break;
1157
1158 case USB_PARSE_LVL_CFG: /* Parse all interfaces of a */
1159 /* specific configuration. */
1160 state->st_if_to_build = USBA_ALL;
1161 break;
1162
1163 case USB_PARSE_LVL_IF: /* Parse configured interface only */
1164 if (state->st_if_to_build < 0) {
1165 state->st_if_to_build = USBA_ALL;
1166 }
1167 break;
1168
1169 default:
1170
1171 return (USB_INVALID_ARGS);
1172 }
1173
1174 /*
1175 * Set parse level to identify this tree properly, regardless of what
1176 * the caller thought the tree would have.
1177 */
1178 if ((state->st_if_to_build == USBA_ALL) &&
1179 (state->st_dev_parse_level == USB_PARSE_LVL_IF)) {
1180 state->st_dev_parse_level = USB_PARSE_LVL_CFG;
1181 }
1182 if ((state->st_cfg_to_build == USBA_ALL) &&
1183 (state->st_dev_parse_level == USB_PARSE_LVL_CFG)) {
1184 state->st_dev_parse_level = USB_PARSE_LVL_ALL;
1185 }
1186
1187 return (USB_SUCCESS);
1188 }
1189
1190
1191 /*
1192 * usba_kmem_realloc:
1193 * Resize dynamic memory. Copy contents of old area to
1194 * beginning of new area.
1195 *
1196 * Arguments:
1197 * old_mem - pointer to old memory area.
1198 * old_size - size of old memory area. 0 is OK.
1199 * new_size - size desired.
1200 *
1201 * Returns:
1202 * pointer to new memory area.
1203 */
1204 static void*
usba_kmem_realloc(void * old_mem,int old_size,int new_size)1205 usba_kmem_realloc(void* old_mem, int old_size, int new_size)
1206 {
1207 void *new_mem = NULL;
1208
1209 if (new_size > 0) {
1210 new_mem = kmem_zalloc(new_size, KM_SLEEP);
1211 if (old_size > 0) {
1212 bcopy(old_mem, new_mem,
1213 min(old_size, new_size));
1214 }
1215 }
1216
1217 if (old_size > 0) {
1218 kmem_free(old_mem, old_size);
1219 }
1220
1221 return (new_mem);
1222 }
1223
1224
1225 /*
1226 * usba_augment_array:
1227 * Add a new element on the end of an array.
1228 *
1229 * Arguments:
1230 * addr - ptr to the array address. Array addr will change.
1231 * n_elements - array element count.
1232 * element_size - size of an array element
1233 */
1234 static void
usba_augment_array(void ** addr,uint_t n_elements,uint_t element_size)1235 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size)
1236 {
1237 *addr = usba_kmem_realloc(*addr, (n_elements * element_size),
1238 ((n_elements + 1) * element_size));
1239 }
1240
1241
1242 /*
1243 * usba_make_alts_sparse:
1244 * Disburse alternate array elements such that they are at the proper array
1245 * indices for which alt they represent. It is assumed that all key values
1246 * used for ordering the elements are positive. Original array space may
1247 * be freed and new space allocated.
1248 *
1249 * Arguments:
1250 * array - pointer to alternates array; may be modified
1251 * n_elements - number of elements in the array; may be modified
1252 */
1253 static void
usba_make_alts_sparse(usb_alt_if_data_t ** array,uint_t * n_elements)1254 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements)
1255 {
1256 uint_t n_orig_elements = *n_elements;
1257 uint8_t smallest_value;
1258 uint8_t largest_value;
1259 uint8_t curr_value;
1260 uint_t in_order = 0;
1261 usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */
1262 usb_alt_if_data_t *repl_array; /* Base ptr to sparse array */
1263 uint_t n_repl_elements; /* Number elements in the new array */
1264 uint_t i;
1265
1266 /* Check for a null array. */
1267 if ((array == NULL) || (n_orig_elements == 0)) {
1268
1269 return;
1270 }
1271
1272 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1273 "make_sparse: array=0x%p, n_orig_elements=%d",
1274 (void *)array, n_orig_elements);
1275
1276 curr_value = orig_addr[0].altif_descr.bAlternateSetting;
1277 smallest_value = largest_value = curr_value;
1278
1279 /* Figure the low-high range of the array. */
1280 for (i = 1; i < n_orig_elements; i++) {
1281 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1282 if (curr_value < smallest_value) {
1283 smallest_value = curr_value;
1284 } else if (curr_value > largest_value) {
1285 in_order++;
1286 largest_value = curr_value;
1287 }
1288 }
1289 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1290 "make_sparse: largest=%d, smallest=%d, "
1291 "order=%d",
1292 largest_value, smallest_value, in_order);
1293
1294 n_repl_elements = largest_value + 1;
1295
1296 /*
1297 * No holes to leave, array starts at zero, and everything is already
1298 * in order. Just return original array.
1299 */
1300 if ((n_repl_elements == n_orig_elements) &&
1301 ((in_order + 1) == n_orig_elements)) {
1302 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1303 "No holes");
1304
1305 return;
1306 }
1307
1308 /* Allocate zeroed space for the array. */
1309 repl_array = kmem_zalloc(
1310 (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP);
1311
1312 /* Now fill in the array. */
1313 for (i = 0; i < n_orig_elements; i++) {
1314 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1315
1316 /* Place in sparse array based on key. */
1317 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1318 "move %lu bytes (key %d) from 0x%p to 0x%p",
1319 (unsigned long)sizeof (usb_alt_if_data_t), curr_value,
1320 (void *)&orig_addr[i], (void *)&repl_array[curr_value]);
1321
1322 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value],
1323 sizeof (usb_alt_if_data_t));
1324 }
1325
1326 kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements);
1327 *array = repl_array;
1328 *n_elements = n_repl_elements;
1329 }
1330
1331
1332 /*
1333 * usba_order_tree:
1334 * Take a tree as built by usba_build_descr_tree and make sure the key
1335 * values of all elements match their indeces. Proper order is implied.
1336 *
1337 * Arguments:
1338 * state - Pointer to this module's state structure.
1339 */
1340 static void
usba_order_tree(usba_reg_state_t * state)1341 usba_order_tree(usba_reg_state_t *state)
1342 {
1343 usb_cfg_data_t *this_cfg;
1344 usb_if_data_t *this_if;
1345 uint_t n_cfgs = state->st_dev_n_cfg;
1346 uint_t cfg;
1347 uint_t which_if;
1348
1349 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1350 "usba_order_tree:");
1351
1352 for (cfg = 0; cfg < n_cfgs; cfg++) {
1353 this_cfg = &state->st_dev_cfg[cfg];
1354
1355 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) {
1356 this_if = this_cfg->cfg_if;
1357 usba_make_alts_sparse(&this_if->if_alt,
1358 &this_if->if_n_alt);
1359 }
1360 }
1361 }
1362
1363
1364 /*
1365 * usb_free_descr_tree:
1366 * Take down the configuration tree. Called internally and can be called
1367 * from a driver standalone to take the tree down while leaving the rest
1368 * of the registration intact.
1369 *
1370 * Arguments:
1371 * dip - pointer to devinfo of the device
1372 * dev_data - pointer to registration data containing the tree.
1373 */
1374 void
usb_free_descr_tree(dev_info_t * dip,usb_client_dev_data_t * dev_data)1375 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1376 {
1377 usb_cfg_data_t *cfg_array;
1378 int n_cfgs;
1379 int cfg;
1380
1381 if ((dip == NULL) || (dev_data == NULL)) {
1382
1383 return;
1384 }
1385 cfg_array = dev_data->dev_cfg;
1386 n_cfgs = dev_data->dev_n_cfg;
1387
1388 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1389 "usb_free_descr_tree starting for %s%d",
1390 ddi_driver_name(dip), ddi_get_instance(dip));
1391
1392 for (cfg = 0; cfg < n_cfgs; cfg++) {
1393 if (cfg_array[cfg].cfg_if) {
1394 usba_free_if_array(cfg_array[cfg].cfg_if,
1395 cfg_array[cfg].cfg_n_if);
1396 }
1397 if (cfg_array[cfg].cfg_cvs) {
1398 usba_free_cv_array(cfg_array[cfg].cfg_cvs,
1399 cfg_array[cfg].cfg_n_cvs);
1400 }
1401 if (cfg_array[cfg].cfg_str) {
1402 kmem_free(cfg_array[cfg].cfg_str,
1403 cfg_array[cfg].cfg_strsize);
1404 }
1405 }
1406
1407 if (cfg_array) {
1408 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs));
1409 }
1410
1411 dev_data->dev_parse_level = USB_PARSE_LVL_NONE;
1412 dev_data->dev_n_cfg = 0;
1413 dev_data->dev_cfg = NULL;
1414 dev_data->dev_curr_cfg = NULL;
1415
1416 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1417 "usb_free_descr_tree done");
1418 }
1419
1420
1421 /*
1422 * usba_free_if_array:
1423 * Free a configuration's array of interface nodes and their subtrees of
1424 * interface alternate, endpoint and c/v descriptors.
1425 *
1426 * Arguments:
1427 * if_array - pointer to array of interfaces to remove.
1428 * n_ifs - number of elements in the array to remove.
1429 */
1430 static void
usba_free_if_array(usb_if_data_t * if_array,uint_t n_ifs)1431 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs)
1432 {
1433 uint_t which_if;
1434 uint_t which_alt;
1435 uint_t n_alts;
1436 usb_alt_if_data_t *altif;
1437
1438 for (which_if = 0; which_if < n_ifs; which_if++) {
1439 n_alts = if_array[which_if].if_n_alt;
1440
1441 /* Every interface has at least one alternate. */
1442 for (which_alt = 0; which_alt < n_alts; which_alt++) {
1443 altif = &if_array[which_if].if_alt[which_alt];
1444 usba_free_ep_array(altif->altif_ep, altif->altif_n_ep);
1445 usba_free_cv_array(altif->altif_cvs,
1446 altif->altif_n_cvs);
1447 kmem_free(altif->altif_str, altif->altif_strsize);
1448 }
1449
1450 kmem_free(if_array[which_if].if_alt,
1451 (sizeof (usb_alt_if_data_t) * n_alts));
1452 }
1453
1454 /* Free the interface array itself. */
1455 kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs));
1456 }
1457
1458
1459 /*
1460 * usba_free_ep_array:
1461 * Free an array of endpoint nodes and their subtrees of c/v descriptors.
1462 *
1463 * Arguments:
1464 * ep_array - pointer to array of endpoints to remove.
1465 * n_eps - number of elements in the array to remove.
1466 */
1467 static void
usba_free_ep_array(usb_ep_data_t * ep_array,uint_t n_eps)1468 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps)
1469 {
1470 uint_t ep;
1471
1472 for (ep = 0; ep < n_eps; ep++) {
1473 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs);
1474 }
1475
1476 kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps));
1477 }
1478
1479
1480 /*
1481 * usba_free_cv_array:
1482 * Free an array of class/vendor (c/v) descriptor nodes.
1483 *
1484 * Arguments:
1485 * cv_array - pointer to array of c/v nodes to remove.
1486 * n_cvs - number of elements in the array to remove.
1487 */
1488 static void
usba_free_cv_array(usb_cvs_data_t * cv_array,uint_t n_cvs)1489 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs)
1490 {
1491 uint_t cv_node;
1492
1493 /* Free data areas hanging off of each c/v descriptor. */
1494 for (cv_node = 0; cv_node < n_cvs; cv_node++) {
1495 kmem_free(cv_array[cv_node].cvs_buf,
1496 cv_array[cv_node].cvs_buf_len);
1497 }
1498
1499 /* Free the array of cv descriptors. */
1500 kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs));
1501 }
1502
1503
1504 /*
1505 * usb_log_descr_tree:
1506 * Log to the usba_debug_buf a descriptor tree as returned by
1507 * usbai_register_client.
1508 *
1509 * Arguments:
1510 * dev_data - pointer to registration area containing the tree
1511 * log_handle - pointer to log handle to use for dumping.
1512 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4
1513 * Please see usb_log(9F) for details.
1514 * mask - print mask. Please see usb_log(9F) for details.
1515 *
1516 * Returns:
1517 * USB_SUCCESS - tree successfully dumped
1518 * USB_INVALID_CONTEXT - called from callback context
1519 * USB_INVALID_ARGS - bad arguments given
1520 */
1521 int
usb_log_descr_tree(usb_client_dev_data_t * dev_data,usb_log_handle_t log_handle,uint_t level,uint_t mask)1522 usb_log_descr_tree(usb_client_dev_data_t *dev_data,
1523 usb_log_handle_t log_handle, uint_t level, uint_t mask)
1524 {
1525 return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask));
1526 }
1527
1528
1529 /*
1530 * usb_print_descr_tree:
1531 * Print to the screen a descriptor tree as returned by
1532 * usbai_register_client.
1533 *
1534 * Arguments:
1535 * dip - pointer to devinfo of the client
1536 * dev_data - pointer to registration area containing the tree
1537 *
1538 * Returns:
1539 * USB_SUCCESS - tree successfully dumped
1540 * USB_INVALID_CONTEXT - called from callback context
1541 * USB_INVALID_ARGS - bad arguments given
1542 */
1543 int
usb_print_descr_tree(dev_info_t * dip,usb_client_dev_data_t * dev_data)1544 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1545 {
1546 return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0));
1547 }
1548
1549
1550 /*
1551 * usba_dump_descr_tree:
1552 * Dump a descriptor tree.
1553 *
1554 * Arguments:
1555 * dip - pointer to devinfo of the client. Used when no
1556 * log_handle argument given.
1557 * usb_reg - pointer to registration area containing the tree
1558 * log_handle - pointer to log handle to use for dumping. If NULL,
1559 * use internal log handle, which dumps to screen.
1560 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4
1561 * Used only when log_handle provided.
1562 * mask - print mask, used when log_handle argument provided.
1563 *
1564 * Returns:
1565 * USB_SUCCESS - tree successfully dumped
1566 * USB_INVALID_CONTEXT - called from callback context
1567 * USB_INVALID_ARGS - bad arguments given
1568 */
1569 static int
usba_dump_descr_tree(dev_info_t * dip,usb_client_dev_data_t * usb_reg,usb_log_handle_t log_handle,uint_t level,uint_t mask)1570 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg,
1571 usb_log_handle_t log_handle, uint_t level, uint_t mask)
1572 {
1573 usb_log_handle_t dump_handle;
1574 uint_t dump_level;
1575 uint_t dump_mask;
1576 int which_config; /* Counters. */
1577 int which_if;
1578 int which_cv;
1579 usb_cfg_data_t *config; /* ptr to current configuration tree node */
1580 usb_cfg_descr_t *config_descr; /* and its USB descriptor. */
1581 char *string;
1582 char *name_string = NULL;
1583 int name_string_size;
1584
1585 if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) {
1586
1587 return (USB_INVALID_ARGS);
1588 }
1589
1590 /*
1591 * To keep calling this simple, kmem_zalloc with the sleep flag always.
1592 * This means no interrupt context is allowed.
1593 */
1594 if (servicing_interrupt()) {
1595
1596 return (USB_INVALID_CONTEXT);
1597 }
1598
1599 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
1600
1601 if (log_handle != NULL) {
1602 dump_level = level;
1603 dump_mask = mask;
1604 dump_handle = log_handle;
1605 } else {
1606 dump_level = USB_LOG_L1;
1607 dump_mask = DPRINT_MASK_ALL;
1608
1609 /* Build device name string. */
1610 (void) snprintf(string, USB_MAXSTRINGLEN,
1611 "Port%d", usb_get_addr(dip));
1612 name_string_size = strlen(string) + 1;
1613 name_string = kmem_zalloc(name_string_size, KM_SLEEP);
1614 (void) strcpy(name_string, string);
1615
1616 /* Allocate a log handle specifying the name string. */
1617 dump_handle = usb_alloc_log_hdl(NULL, name_string,
1618 &dump_level, &dump_mask, NULL,
1619 USB_FLAGS_SLEEP);
1620 }
1621
1622 (void) usb_log(dump_handle, dump_level, dump_mask,
1623 "USB descriptor tree for %s %s",
1624 (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""),
1625 (usb_reg->dev_product != NULL ? usb_reg->dev_product : ""));
1626 if (usb_reg->dev_n_cfg == 0) {
1627 (void) usb_log(dump_handle, dump_level, dump_mask,
1628 "No descriptor tree present");
1629 } else {
1630 (void) usb_log(dump_handle, dump_level, dump_mask,
1631 "highest configuration found=%d", usb_reg->dev_n_cfg - 1);
1632 }
1633
1634 for (which_config = 0; which_config < usb_reg->dev_n_cfg;
1635 which_config++) {
1636 config = &usb_reg->dev_cfg[which_config];
1637 config_descr = &config->cfg_descr;
1638 if (config_descr->bLength == 0) {
1639
1640 continue;
1641 }
1642 if (dump_level == USB_LOG_L0) {
1643 (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1644 }
1645 (void) usb_log(dump_handle, dump_level, dump_mask,
1646 "Configuration #%d (Addr= 0x%p)", which_config,
1647 (void *)config);
1648 (void) usb_log(dump_handle, dump_level, dump_mask,
1649 "String descr=%s", config->cfg_str);
1650 (void) usb_log(dump_handle, dump_level, dump_mask,
1651 "config descr: len=%d tp=%d totLen=%d numIf=%d "
1652 "cfgVal=%d att=0x%x pwr=%d",
1653 config_descr->bLength, config_descr->bDescriptorType,
1654 config_descr->wTotalLength, config_descr->bNumInterfaces,
1655 config_descr->bConfigurationValue,
1656 config_descr->bmAttributes, config_descr->bMaxPower);
1657 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) {
1658 (void) usb_log(dump_handle, dump_level, dump_mask,
1659 "usb_cfg_data_t shows max if=%d "
1660 "and %d cv descr(s).",
1661 config->cfg_n_if - 1, config->cfg_n_cvs);
1662 }
1663
1664 for (which_if = 0; which_if < config->cfg_n_if;
1665 which_if++) {
1666
1667 if (dump_level == USB_LOG_L0) {
1668 (void) usb_log(dump_handle, dump_level,
1669 dump_mask, " ");
1670 }
1671 (void) usb_log(dump_handle, dump_level, dump_mask,
1672 " interface #%d (0x%p)",
1673 which_if, (void *)&config->cfg_if[which_if]);
1674 usba_dump_if(&config->cfg_if[which_if],
1675 dump_handle, dump_level, dump_mask, string);
1676 }
1677
1678 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) {
1679 (void) usb_log(dump_handle, dump_level, dump_mask,
1680 " config cv descriptor %d (Address=0x%p)",
1681 which_cv, (void *)&config->cfg_cvs[which_cv]);
1682 usba_dump_cv(&config->cfg_cvs[which_cv],
1683 dump_handle, dump_level, dump_mask, string, 4);
1684 }
1685 }
1686
1687 (void) usb_log(dump_handle, dump_level, dump_mask,
1688 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d",
1689 (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if);
1690
1691 if (log_handle == NULL) {
1692 usb_free_log_hdl(dump_handle);
1693 }
1694 if (name_string != NULL) {
1695 kmem_free(name_string, name_string_size);
1696 }
1697 kmem_free(string, USB_MAXSTRINGLEN);
1698
1699 return (USB_SUCCESS);
1700 }
1701
1702
1703 /*
1704 * usba_dump_if:
1705 * Dump an interface node and its branches.
1706 *
1707 * Arguments:
1708 * which_if - interface node to dump
1709 * dump_handle - write data through this log handle
1710 * dump_level - level passed to usb_log
1711 * dump_mask - mask passed to usb_log
1712 * string - temporary area used for processing
1713 *
1714 */
1715 static void
usba_dump_if(usb_if_data_t * which_if,usb_log_handle_t dump_handle,uint_t dump_level,uint_t dump_mask,char * string)1716 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle,
1717 uint_t dump_level, uint_t dump_mask, char *string)
1718 {
1719 int which_alt; /* Number of alt being dumped */
1720 usb_alt_if_data_t *alt; /* Pointer to it. */
1721 usb_if_descr_t *if_descr; /* Pointer to its USB descr. */
1722 int which_ep; /* Endpoint counter. */
1723 int which_cv; /* C/V descr counter. */
1724
1725 for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) {
1726 alt = &which_if->if_alt[which_alt];
1727 if_descr = &alt->altif_descr;
1728
1729 if (if_descr->bLength == 0) {
1730
1731 continue;
1732 }
1733 if (dump_level == USB_LOG_L0) {
1734 (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1735 }
1736 (void) usb_log(dump_handle, dump_level, dump_mask,
1737 "\tAlt #%d (0x%p)", which_alt, (void *)alt);
1738 (void) usb_log(dump_handle, dump_level, dump_mask,
1739 "\tString descr=%s", alt->altif_str);
1740 (void) usb_log(dump_handle, dump_level, dump_mask,
1741 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d "
1742 "cls=%d sub=%d proto=%d",
1743 if_descr->bLength,
1744 if_descr->bDescriptorType, if_descr->bInterfaceNumber,
1745 if_descr->bAlternateSetting, if_descr->bNumEndpoints,
1746 if_descr->bInterfaceClass, if_descr->bInterfaceSubClass,
1747 if_descr->bInterfaceProtocol);
1748
1749 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) {
1750 (void) usb_log(dump_handle, dump_level, dump_mask,
1751 "\tusb_alt_if_data_t shows max ep=%d "
1752 "and %d cv descr(s).",
1753 alt->altif_n_ep - 1, alt->altif_n_cvs);
1754 }
1755
1756 for (which_ep = 0; which_ep < alt->altif_n_ep;
1757 which_ep++) {
1758 if (alt->altif_ep[which_ep].ep_descr.bLength == 0) {
1759
1760 continue;
1761 }
1762 if (dump_level == USB_LOG_L0) {
1763 (void) usb_log(dump_handle, dump_level,
1764 dump_mask, " ");
1765 }
1766 usba_dump_ep(which_ep, &alt->altif_ep[which_ep],
1767 dump_handle, dump_level, dump_mask, string);
1768 }
1769
1770 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) {
1771 if (dump_level == USB_LOG_L0) {
1772 (void) usb_log(dump_handle, dump_level,
1773 dump_mask, " ");
1774 }
1775 (void) usb_log(dump_handle, dump_level, dump_mask,
1776 "\talt cv descriptor #%d (0x%p), size=%d",
1777 which_cv, (void *)&alt->altif_cvs[which_cv],
1778 alt->altif_cvs[which_cv].cvs_buf_len);
1779 usba_dump_cv(&alt->altif_cvs[which_cv],
1780 dump_handle, dump_level, dump_mask, string, 2);
1781 }
1782 }
1783 }
1784
1785
1786 /*
1787 * usba_dump_ep:
1788 * Dump an endpoint node and its branches.
1789 *
1790 * Arguments:
1791 * which_ep - index to display
1792 * ep - endpoint node to dump
1793 * dump_handle - write data through this log handle
1794 * dump_level - level passed to usb_log
1795 * dump_mask - mask passed to usb_log
1796 * string - temporary area used for processing
1797 *
1798 */
1799 static void
usba_dump_ep(uint_t which_ep,usb_ep_data_t * ep,usb_log_handle_t dump_handle,uint_t dump_level,uint_t dump_mask,char * string)1800 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle,
1801 uint_t dump_level, uint_t dump_mask, char *string)
1802 {
1803 int which_cv;
1804 usb_ep_descr_t *ep_descr = &ep->ep_descr;
1805
1806 (void) usb_log(dump_handle, dump_level, dump_mask,
1807 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep,
1808 ep_descr->bEndpointAddress, (void *)ep);
1809 (void) usb_log(dump_handle, dump_level, dump_mask,
1810 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d",
1811 ep_descr->bLength, ep_descr->bDescriptorType,
1812 ep_descr->bmAttributes, ep_descr->wMaxPacketSize,
1813 ep_descr->bInterval);
1814 if (ep->ep_n_cvs > 0) {
1815 (void) usb_log(dump_handle, dump_level, dump_mask,
1816 "\t usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs);
1817 }
1818
1819 for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) {
1820 if (dump_level == USB_LOG_L0) {
1821 (void) usb_log(dump_handle, dump_level,
1822 dump_mask, " ");
1823 }
1824 (void) usb_log(dump_handle, dump_level, dump_mask,
1825 "\t endpoint cv descriptor %d (0x%p), size=%d",
1826 which_cv, (void *)&ep->ep_cvs[which_cv],
1827 ep->ep_cvs[which_cv].cvs_buf_len);
1828 usba_dump_cv(&ep->ep_cvs[which_cv],
1829 dump_handle, dump_level, dump_mask, string, 3);
1830 }
1831 }
1832
1833
1834 /*
1835 * usba_dump_cv:
1836 * Dump a raw class or vendor specific descriptor.
1837 *
1838 * Arguments:
1839 * cv_node - pointer to the descriptor to dump
1840 * dump_handle - write data through this log handle
1841 * dump_level - level passed to usb_log
1842 * dump_mask - mask passed to usb_log
1843 * string - temporary area used for processing
1844 * indent - number of tabs to indent output
1845 *
1846 */
1847 static void
usba_dump_cv(usb_cvs_data_t * cv_node,usb_log_handle_t dump_handle,uint_t dump_level,uint_t dump_mask,char * string,int indent)1848 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle,
1849 uint_t dump_level, uint_t dump_mask, char *string, int indent)
1850 {
1851 if (cv_node) {
1852 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent,
1853 dump_handle, dump_level, dump_mask, string,
1854 USB_MAXSTRINGLEN);
1855 }
1856 }
1857
1858
1859 /*
1860 * usba_dump_bin:
1861 * Generic byte dump function.
1862 *
1863 * Arguments:
1864 * data - pointer to the data to dump
1865 * max_bytes - amount of data to dump
1866 * indent - number of indentation levels
1867 * dump_handle - write data through this log handle
1868 * dump_level - level passed to usb_log
1869 * dump_mask - mask passed to usb_log
1870 * buffer - temporary area used for processing
1871 * bufferlen - size of the temporary string area
1872 *
1873 */
1874 static void
usba_dump_bin(uint8_t * data,int max_bytes,int indent,usb_log_handle_t dump_handle,uint_t dump_level,uint_t dump_mask,char * buffer,int bufferlen)1875 usba_dump_bin(uint8_t *data, int max_bytes, int indent,
1876 usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask,
1877 char *buffer, int bufferlen)
1878 {
1879 int i;
1880 int bufoffset = 0;
1881 int nexthere;
1882
1883 if ((indent * SPACES_PER_INDENT) >
1884 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) {
1885 (void) usb_log(dump_handle, dump_level, dump_mask,
1886 "Offset to usb_dump_bin must be %d or less. "
1887 "Setting to 0.\n",
1888 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3)));
1889 indent = 0;
1890 }
1891
1892 /* Assume a tab is 2 four-space units. */
1893 for (i = 0; i < indent/2; i++) {
1894 buffer[bufoffset] = '\t';
1895 bufoffset++;
1896 }
1897
1898 if (indent % 2) {
1899 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR);
1900 bufoffset += SPACES_PER_INDENT;
1901 }
1902
1903 i = 0; /* Num dumped bytes put on this line. */
1904 nexthere = bufoffset;
1905 while (i < max_bytes) {
1906 (void) sprintf(&buffer[nexthere], "%2x ", *data++);
1907 nexthere += 3;
1908 i++;
1909 if (!(i % BINDUMP_BYTES_PER_LINE)) {
1910 buffer[nexthere] = '\0';
1911 (void) usb_log(dump_handle, dump_level, dump_mask,
1912 buffer);
1913 nexthere = bufoffset;
1914 }
1915 }
1916
1917 if (nexthere > bufoffset) {
1918 buffer[nexthere] = '\0';
1919 (void) usb_log(dump_handle, dump_level, dump_mask, buffer);
1920 }
1921 }
1922