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