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