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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 * Copyright (c) 2017, Joyent, Inc.
30 * USBA: Solaris USB Architecture support
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
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.
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.
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.
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.
59 * Endpoint tree nodes contain a standard endpoint descriptor, plus a pointer to
60 * an array of c/v tree nodes.
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.
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.
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
77 * How the tree is built:
79 * usb_build_descr_tree() is responsible for the whole process.
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.
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
92 * The usba_reg_state_t structure maintains state of the tree-building process,
93 * helping coordinate all routines involved.
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>
102 #include <sys/usb/usba/usbai_register_impl.h>
105 * Header needed for use by this module only.
106 * However, function may be used in V0.8 drivers so needs to be global.
108 int usb_log_descr_tree(usb_client_dev_data_t
*, usb_log_handle_t
,
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;
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
*);
131 static void usba_order_tree(usba_reg_state_t
*);
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
);
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
,
143 static void usba_dump_cv(usb_cvs_data_t
*, usb_log_handle_t
, uint_t
, uint_t
,
145 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t
,
146 uint_t
, uint_t
, char *, int);
148 /* Framework initialization. */
150 usba_usbai_register_initialization()
152 usbai_reg_log_handle
= usb_alloc_log_hdl(NULL
, "usbreg",
153 &usbai_register_errlevel
,
154 &usbai_register_errmask
, NULL
,
157 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
158 "usba_usbai_register_initialization");
162 /* Framework destruction. */
164 usba_usbai_register_destroy()
166 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
167 "usba_usbai_register destroy");
169 usb_free_log_hdl(usbai_reg_log_handle
);
177 * dip - pointer to devinfo node of the client
178 * version - USBA registration version number
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
189 usb_client_attach(dev_info_t
*dip
, uint_t version
, usb_flags_t flags
)
192 usba_device_t
*usba_device
;
196 return (USB_INVALID_ARGS
);
199 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
200 "usb_client attach:");
202 usba_device
= usba_get_usba_device(dip
);
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.
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, "
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
);
219 return (USB_INVALID_VERSION
);
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
));
229 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "driver-major",
230 USBA_GET_MAJOR(version
));
231 if (rval
!= DDI_PROP_SUCCESS
) {
233 return (USB_FAILURE
);
235 rval
= ndi_prop_update_int(DDI_DEV_T_NONE
, dip
, "driver-minor",
236 USBA_GET_MINOR(version
));
237 if (rval
!= DDI_PROP_SUCCESS
) {
239 return (USB_FAILURE
);
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
;
248 mutex_exit(&usba_device
->usb_mutex
);
250 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
251 "usb_client attach: done");
253 return (USB_SUCCESS
);
259 * free dev_data is reg != NULL, not much else to do
262 * dip - pointer to devinfo node of the client
263 * reg - return registration data at this address
266 usb_client_detach(dev_info_t
*dip
, usb_client_dev_data_t
*reg
)
268 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
270 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
271 "usb_client_detach:");
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
);
278 usb_free_dev_data(dip
, reg
);
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
;
285 mutex_exit(&usba_device
->usb_mutex
);
288 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
289 "usb_client_detach done");
294 * usb_register_client (deprecated):
295 * The client registers with USBA during attach.
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
,
303 int rval
= usb_client_attach(dip
, version
, flags
);
305 if (rval
== USB_SUCCESS
) {
306 rval
= usb_get_dev_data(dip
, reg
, parse_level
, flags
);
308 if (rval
!= USB_SUCCESS
) {
309 usb_client_detach(dip
, NULL
);
318 * usb_unregister_client (deprecated):
319 * Undo the makings of usb_get_dev_data(). Free memory if allocated.
322 * dip - pointer to devinfo node of the client
323 * reg - pointer to registration data to be freed
326 usb_unregister_client(dev_info_t
*dip
, usb_client_dev_data_t
*reg
)
328 usb_client_detach(dip
, reg
);
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.
343 * This routine sets up directly-initialized fields, and calls
344 * usb_build_descr_tree() to parse the raw descriptors and initialize the
347 * Parse_level determines the extent to which the tree is built. It has
348 * the following values:
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.
365 * No tree is built for root hubs, regardless of parse_level.
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
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
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.
385 * The registration data is not shared. each client receives its own
390 usb_get_dev_data(dev_info_t
*dip
,
391 usb_client_dev_data_t
**reg
, usb_reg_parse_lvl_t parse_level
,
394 usb_client_dev_data_t
*usb_reg
= NULL
;
396 usba_device_t
*usba_device
;
397 int rval
= USB_SUCCESS
;
399 if ((dip
== NULL
) || (reg
== NULL
)) {
401 return (USB_INVALID_ARGS
);
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
));
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) {
414 return (USB_INVALID_VERSION
);
416 if (ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
417 "driver-minor", -1) == -1) {
419 return (USB_INVALID_VERSION
);
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
));
429 return (USB_FAILURE
);
432 usb_reg
->dev_iblock_cookie
= usba_hcdi_get_hcdi(
433 usba_device
->usb_root_hub_dip
)->hcdi_soft_iblock_cookie
;
435 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
436 "cookie = 0x%p", (void *)usb_reg
->dev_iblock_cookie
);
438 tmpbuf
= kmem_zalloc(USB_MAXSTRINGLEN
, KM_SLEEP
);
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
);
446 if (usba_device
->usb_product_str
!= NULL
) {
447 usb_reg
->dev_product
= kmem_zalloc(
448 strlen(usba_device
->usb_product_str
) + 1,
450 (void) strcpy(usb_reg
->dev_product
,
451 usba_device
->usb_product_str
);
454 if (usba_device
->usb_serialno_str
!= NULL
) {
455 usb_reg
->dev_serial
= kmem_zalloc(
456 strlen(usba_device
->usb_serialno_str
) + 1,
458 (void) strcpy(usb_reg
->dev_serial
,
459 usba_device
->usb_serialno_str
);
462 if ((usb_reg
->dev_parse_level
= parse_level
) == USB_PARSE_LVL_NONE
) {
465 } else if ((rval
= usba_build_descr_tree(dip
, usba_device
, usb_reg
)) !=
467 usb_unregister_client(dip
, usb_reg
);
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];
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
==
485 * Keep dev_curr_if at device's single interface only if that
486 * particular interface has been explicitly defined by the
489 usb_reg
->dev_curr_if
= usba_get_ifno(dip
);
491 (void) usb_log_descr_tree(usb_reg
, usbai_reg_log_handle
,
492 usbai_register_dump_errlevel
, (uint_t
)-1);
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.
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
].
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
);
513 kmem_free(tmpbuf
, USB_MAXSTRINGLEN
);
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
);
520 usba_device
->usb_client_flags
[usba_get_ifno(dip
)] |=
521 USBA_CLIENT_FLAG_DEV_DATA
;
523 entry
->cddl_dip
= dip
;
524 entry
->cddl_dev_data
= usb_reg
;
525 entry
->cddl_ifno
= usba_get_ifno(dip
);
528 usba_device
->usb_client_dev_data_list
.cddl_next
;
529 if (entry
->cddl_next
) {
530 entry
->cddl_next
->cddl_prev
= entry
;
532 entry
->cddl_prev
= &usba_device
->usb_client_dev_data_list
;
533 usba_device
->usb_client_dev_data_list
.cddl_next
= entry
;
535 mutex_exit(&usba_device
->usb_mutex
);
538 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
539 "usb_get_dev_data rval=%d", rval
);
547 * undoes what usb_get_dev_data does
550 * dip - pointer to devinfo node of the client
551 * reg - return registration data at this address
554 usb_free_dev_data(dev_info_t
*dip
, usb_client_dev_data_t
*reg
)
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
);
566 usba_device_t
*usba_device
= usba_get_usba_device(dip
);
567 usb_client_dev_data_list_t
*next
, *prev
, *entry
;
570 if (reg
->dev_serial
!= NULL
) {
571 kmem_free((char *)reg
->dev_serial
,
572 strlen((char *)reg
->dev_serial
) + 1);
575 if (reg
->dev_product
!= NULL
) {
576 kmem_free((char *)reg
->dev_product
,
577 strlen((char *)reg
->dev_product
) + 1);
580 if (reg
->dev_mfg
!= NULL
) {
581 kmem_free((char *)reg
->dev_mfg
,
582 strlen((char *)reg
->dev_mfg
) + 1);
585 /* Free config tree under reg->dev_cfg. */
586 if (reg
->dev_cfg
!= NULL
) {
587 usb_free_descr_tree(dip
, reg
);
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
;
594 /* free the entries in usb_client_data_list */
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
;
603 kmem_free(entry
, sizeof (*entry
));
606 * any other entries for this interface?
608 if (usba_get_ifno(dip
) == entry
->cddl_ifno
) {
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
,
621 usba_device
->usb_client_flags
[usba_get_ifno(dip
)]);
625 usb_client_flags
[usba_get_ifno(dip
)] &=
626 ~USBA_CLIENT_FLAG_DEV_DATA
;
628 mutex_exit(&usba_device
->usb_mutex
);
630 kmem_free(reg
, sizeof (usb_client_dev_data_t
));
633 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
634 "usb_free_dev_data done");
638 * usba_build_descr_tree:
639 * This builds the descriptor tree. See module header comment for tree
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.
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
656 usba_build_descr_tree(dev_info_t
*dip
, usba_device_t
*usba_device
,
657 usb_client_dev_data_t
*usb_reg
)
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. */
668 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
669 "usba_build_descr_tree starting");
671 bzero(&state
, sizeof (usba_reg_state_t
));
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.
679 state
.st_dev_parse_level
= usb_reg
->dev_parse_level
;
680 if (usba_set_parse_values(dip
, usba_device
, &state
) != USB_SUCCESS
) {
682 return (USB_INVALID_ARGS
);
684 usb_reg
->dev_parse_level
= state
.st_dev_parse_level
;
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
;
690 high_cfg_bound
= usba_device
->usb_n_cfgs
;
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
);
698 usb_reg
->dev_cfg
= state
.st_dev_cfg
= kmem_zalloc(
699 (usb_reg
->dev_n_cfg
* sizeof (usb_cfg_data_t
)),
702 * this_cfg_ndx loops through all configurations presented;
703 * state.st_dev_n_cfg limits the cfgs checked to the number desired.
705 state
.st_dev_n_cfg
= 0;
706 for (this_cfg_ndx
= low_cfg_bound
; this_cfg_ndx
< high_cfg_bound
;
709 state
.st_curr_raw_descr
=
710 usba_device
->usb_cfg_array
[this_cfg_ndx
];
711 ASSERT(state
.st_curr_raw_descr
!= NULL
);
713 /* Clear the following for config cloud sanity checking. */
715 state
.st_curr_cfg
= NULL
;
716 state
.st_curr_if
= NULL
;
717 state
.st_curr_alt
= NULL
;
718 state
.st_curr_ep
= NULL
;
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];
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
)) {
732 return (USB_FAILURE
);
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.
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
);
746 return (USB_FAILURE
);
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
);
755 switch (state
.st_curr_raw_descr_type
) {
756 case USB_DESCR_TYPE_CFG
:
758 process_this_if_tree
= B_FALSE
;
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
=
765 last_byte
= state
.st_curr_raw_descr
+
766 (state
.st_total_cfg_length
*
771 case USB_DESCR_TYPE_IF
:
773 * process_this_if_tree == TRUE means this
774 * interface, plus all eps and c/vs in it are
777 if (usba_process_if_descr(&state
,
778 &process_this_if_tree
) != USB_SUCCESS
) {
780 return (USB_FAILURE
);
782 state
.st_last_processed_descr_type
=
787 case USB_DESCR_TYPE_EP
:
789 * Skip if endpoints of a specific interface are
790 * desired and this endpoint is associated with
791 * a different interface.
793 if (process_this_if_tree
) {
794 if (usba_process_ep_descr(&state
) !=
797 return (USB_FAILURE
);
799 state
.st_last_processed_descr_type
=
805 case USB_DESCR_TYPE_SS_EP_COMP
:
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.
814 if (state
.st_last_processed_descr_type
==
816 if (usba_process_ss_ep_comp_descr(
817 &state
) != USB_SUCCESS
) {
819 return (USB_FAILURE
);
822 state
.st_last_processed_descr_type
=
823 USB_DESCR_TYPE_SS_EP_COMP
;
829 case USB_DESCR_TYPE_STRING
:
830 USB_DPRINTF_L2(DPRINT_MASK_ALL
,
831 usbai_reg_log_handle
,
833 "Found unexpected str descr at addr 0x%p",
834 (void *)state
.st_curr_raw_descr
);
836 break; /* Shouldn't be any here. Skip. */
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.
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
) !=
854 return (USB_FAILURE
);
859 state
.st_curr_raw_descr
+= state
.st_curr_raw_descr_len
;
860 cfg_len_so_far
+= state
.st_curr_raw_descr_len
;
862 } while (state
.st_curr_raw_descr
< last_byte
);
865 /* Make tree sparse, and put elements in order. */
866 usba_order_tree(&state
);
868 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
869 "usba_build_descr_tree done");
871 return (USB_SUCCESS
);
876 * usba_process_cfg_descr:
877 * Set up a configuration tree node based on a raw config descriptor.
880 * state - Pointer to this module's state structure.
883 * B_TRUE: the descr processed corresponds to a requested configuration.
884 * B_FALSE: the descr processed does not correspond to a requested config.
887 usba_process_cfg_descr(usba_reg_state_t
*state
)
889 usb_cfg_data_t
*curr_cfg
;
891 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
892 "usba_process_cfg_descr starting");
894 curr_cfg
= state
->st_curr_cfg
=
895 &state
->st_dev_cfg
[state
->st_dev_n_cfg
++];
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
));
903 state
->st_total_cfg_length
= curr_cfg
->cfg_descr
.wTotalLength
;
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
,
909 (void) strcpy(curr_cfg
->cfg_str
, state
->st_curr_cfg_str
);
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
);
916 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
917 "usba_process_cfg_descr done");
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.
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.
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.
938 * USB_SUCCESS: Descriptor is successfully parsed.
939 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
942 usba_process_if_descr(usba_reg_state_t
*state
, boolean_t
*requested_if
)
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
);
949 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
950 "usba_process_if_descr starting");
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.");
957 return (USB_FAILURE
);
960 new_if_descr
= kmem_zalloc(sizeof (usb_if_descr_t
), KM_SLEEP
);
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
));
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
));
974 *requested_if
= B_FALSE
;
976 return (USB_SUCCESS
);
978 *requested_if
= B_TRUE
;
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
;
986 usb_alt_if_data_t
*alt_array
;
989 /* Point to proper interface node, based on num in descr. */
991 &state
->st_curr_cfg
->cfg_if
[new_if_descr
->bInterfaceNumber
];
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
));
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
];
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
;
1007 string
= kmem_zalloc(USB_MAXSTRINGLEN
, KM_SLEEP
);
1009 (void) usb_get_string_descr(state
->dip
, USB_LANG_ID
,
1010 state
->st_curr_alt
->altif_descr
.iInterface
,
1011 string
, USB_MAXSTRINGLEN
);
1013 if (string
[0] == '\0') {
1014 (void) strcpy(string
, "<none>");
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
);
1023 kmem_free(new_if_descr
, sizeof (usb_if_descr_t
));
1025 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1026 "usba_process_if_descr done");
1028 return (USB_SUCCESS
);
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.
1038 * state - Pointer to this module's state structure.
1041 * USB_SUCCESS: Descriptor is successfully parsed.
1042 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1045 usba_process_ep_descr(usba_reg_state_t
*state
)
1047 usb_alt_if_data_t
*curr_alt
= state
->st_curr_alt
;
1049 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1050 "usba_process_ep_descr starting");
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.");
1057 return (USB_FAILURE
);
1060 usba_augment_array((void **)(&curr_alt
->altif_ep
),
1061 curr_alt
->altif_n_ep
, sizeof (usb_ep_data_t
));
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
++];
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
));
1070 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1071 "usba_process_ep_descr done");
1073 return (USB_SUCCESS
);
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.
1082 * state - Pointer to this module's state structure.
1085 * USB_SUCCESS: Descriptor is successfully parsed.
1086 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1089 usba_process_ss_ep_comp_descr(usba_reg_state_t
*state
)
1091 if (state
->st_curr_ep
== NULL
)
1092 return (USB_FAILURE
);
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
;
1100 return (USB_SUCCESS
);
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.
1112 * state - Pointer to this module's state structure.
1115 * USB_SUCCESS: Descriptor is successfully parsed.
1116 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1119 usba_process_cv_descr(usba_reg_state_t
*state
)
1121 usb_cvs_data_t
*curr_cv_descr
;
1122 usb_cvs_data_t
**cvs_ptr
= NULL
;
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
);
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.
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
;
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
;
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
;
1151 USB_DPRINTF_L2(DPRINT_MASK_ALL
, usbai_reg_log_handle
,
1152 "usba_process_cv_descr: Type of last descriptor unknown. ");
1154 return (USB_FAILURE
);
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
)++];
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
);
1167 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1168 "usba_process_cv_descr done");
1170 return (USB_SUCCESS
);
1175 * usba_set_parse_values:
1176 * Based on parse level, set the configuration(s) and interface(s) to build
1178 * Returned configuration value can be USBA_ALL indicating to build all
1179 * configurations. Likewise for the returned interface value.
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.
1191 * USB_SUCCESS - success
1192 * USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
1195 usba_set_parse_values(dev_info_t
*dip
, usba_device_t
*usba_device
,
1196 usba_reg_state_t
*state
)
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
;
1205 state
->st_if_to_build
= usb_get_if_number(dip
);
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
;
1213 case USB_PARSE_LVL_CFG
: /* Parse all interfaces of a */
1214 /* specific configuration. */
1215 state
->st_if_to_build
= USBA_ALL
;
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
;
1226 return (USB_INVALID_ARGS
);
1230 * Set parse level to identify this tree properly, regardless of what
1231 * the caller thought the tree would have.
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
;
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
;
1242 return (USB_SUCCESS
);
1247 * usba_kmem_realloc:
1248 * Resize dynamic memory. Copy contents of old area to
1249 * beginning of new area.
1252 * old_mem - pointer to old memory area.
1253 * old_size - size of old memory area. 0 is OK.
1254 * new_size - size desired.
1257 * pointer to new memory area.
1260 usba_kmem_realloc(void* old_mem
, int old_size
, int new_size
)
1262 void *new_mem
= NULL
;
1265 new_mem
= kmem_zalloc(new_size
, KM_SLEEP
);
1267 bcopy(old_mem
, new_mem
,
1268 min(old_size
, new_size
));
1273 kmem_free(old_mem
, old_size
);
1281 * usba_augment_array:
1282 * Add a new element on the end of an array.
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
1290 usba_augment_array(void **addr
, uint_t n_elements
, uint_t element_size
)
1292 *addr
= usba_kmem_realloc(*addr
, (n_elements
* element_size
),
1293 ((n_elements
+ 1) * element_size
));
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.
1305 * array - pointer to alternates array; may be modified
1306 * n_elements - number of elements in the array; may be modified
1309 usba_make_alts_sparse(usb_alt_if_data_t
**array
, uint_t
*n_elements
)
1311 uint_t n_orig_elements
= *n_elements
;
1312 uint8_t smallest_value
;
1313 uint8_t largest_value
;
1315 uint_t in_order
= 0;
1316 usb_alt_if_data_t
*orig_addr
= *array
; /* 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 */
1321 /* Check for a null array. */
1322 if ((array
== NULL
) || (n_orig_elements
== 0)) {
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
);
1331 curr_value
= orig_addr
[0].altif_descr
.bAlternateSetting
;
1332 smallest_value
= largest_value
= curr_value
;
1334 /* Figure the low-high range of the array. */
1335 for (i
= 1; i
< n_orig_elements
; i
++) {
1336 curr_value
= orig_addr
[i
].altif_descr
.bAlternateSetting
;
1337 if (curr_value
< smallest_value
) {
1338 smallest_value
= curr_value
;
1339 } else if (curr_value
> largest_value
) {
1341 largest_value
= curr_value
;
1344 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1345 "make_sparse: largest=%d, smallest=%d, "
1347 largest_value
, smallest_value
, in_order
);
1349 n_repl_elements
= largest_value
+ 1;
1352 * No holes to leave, array starts at zero, and everything is already
1353 * in order. Just return original array.
1355 if ((n_repl_elements
== n_orig_elements
) &&
1356 ((in_order
+ 1) == n_orig_elements
)) {
1357 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1363 /* Allocate zeroed space for the array. */
1364 repl_array
= kmem_zalloc(
1365 (n_repl_elements
* sizeof (usb_alt_if_data_t
)), KM_SLEEP
);
1367 /* Now fill in the array. */
1368 for (i
= 0; i
< n_orig_elements
; i
++) {
1369 curr_value
= orig_addr
[i
].altif_descr
.bAlternateSetting
;
1371 /* Place in sparse array based on key. */
1372 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1373 "move %lu bytes (key %d) from 0x%p to 0x%p",
1374 (unsigned long)sizeof (usb_alt_if_data_t
), curr_value
,
1375 (void *)&orig_addr
[i
], (void *)&repl_array
[curr_value
]);
1377 bcopy((char *)&orig_addr
[i
], (char *)&repl_array
[curr_value
],
1378 sizeof (usb_alt_if_data_t
));
1381 kmem_free(*array
, sizeof (usb_alt_if_data_t
) * n_orig_elements
);
1382 *array
= repl_array
;
1383 *n_elements
= n_repl_elements
;
1389 * Take a tree as built by usba_build_descr_tree and make sure the key
1390 * values of all elements match their indeces. Proper order is implied.
1393 * state - Pointer to this module's state structure.
1396 usba_order_tree(usba_reg_state_t
*state
)
1398 usb_cfg_data_t
*this_cfg
;
1399 usb_if_data_t
*this_if
;
1400 uint_t n_cfgs
= state
->st_dev_n_cfg
;
1404 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1405 "usba_order_tree:");
1407 for (cfg
= 0; cfg
< n_cfgs
; cfg
++) {
1408 this_cfg
= &state
->st_dev_cfg
[cfg
];
1410 for (which_if
= 0; which_if
< this_cfg
->cfg_n_if
; which_if
++) {
1411 this_if
= this_cfg
->cfg_if
;
1412 usba_make_alts_sparse(&this_if
->if_alt
,
1413 &this_if
->if_n_alt
);
1420 * usb_free_descr_tree:
1421 * Take down the configuration tree. Called internally and can be called
1422 * from a driver standalone to take the tree down while leaving the rest
1423 * of the registration intact.
1426 * dip - pointer to devinfo of the device
1427 * dev_data - pointer to registration data containing the tree.
1430 usb_free_descr_tree(dev_info_t
*dip
, usb_client_dev_data_t
*dev_data
)
1432 usb_cfg_data_t
*cfg_array
;
1436 if ((dip
== NULL
) || (dev_data
== NULL
)) {
1440 cfg_array
= dev_data
->dev_cfg
;
1441 n_cfgs
= dev_data
->dev_n_cfg
;
1443 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1444 "usb_free_descr_tree starting for %s%d",
1445 ddi_driver_name(dip
), ddi_get_instance(dip
));
1447 for (cfg
= 0; cfg
< n_cfgs
; cfg
++) {
1448 if (cfg_array
[cfg
].cfg_if
) {
1449 usba_free_if_array(cfg_array
[cfg
].cfg_if
,
1450 cfg_array
[cfg
].cfg_n_if
);
1452 if (cfg_array
[cfg
].cfg_cvs
) {
1453 usba_free_cv_array(cfg_array
[cfg
].cfg_cvs
,
1454 cfg_array
[cfg
].cfg_n_cvs
);
1456 if (cfg_array
[cfg
].cfg_str
) {
1457 kmem_free(cfg_array
[cfg
].cfg_str
,
1458 cfg_array
[cfg
].cfg_strsize
);
1463 kmem_free(cfg_array
, (sizeof (usb_cfg_data_t
) * n_cfgs
));
1466 dev_data
->dev_parse_level
= USB_PARSE_LVL_NONE
;
1467 dev_data
->dev_n_cfg
= 0;
1468 dev_data
->dev_cfg
= NULL
;
1469 dev_data
->dev_curr_cfg
= NULL
;
1471 USB_DPRINTF_L4(DPRINT_MASK_REGISTER
, usbai_reg_log_handle
,
1472 "usb_free_descr_tree done");
1477 * usba_free_if_array:
1478 * Free a configuration's array of interface nodes and their subtrees of
1479 * interface alternate, endpoint and c/v descriptors.
1482 * if_array - pointer to array of interfaces to remove.
1483 * n_ifs - number of elements in the array to remove.
1486 usba_free_if_array(usb_if_data_t
*if_array
, uint_t n_ifs
)
1491 usb_alt_if_data_t
*altif
;
1493 for (which_if
= 0; which_if
< n_ifs
; which_if
++) {
1494 n_alts
= if_array
[which_if
].if_n_alt
;
1496 /* Every interface has at least one alternate. */
1497 for (which_alt
= 0; which_alt
< n_alts
; which_alt
++) {
1498 altif
= &if_array
[which_if
].if_alt
[which_alt
];
1499 usba_free_ep_array(altif
->altif_ep
, altif
->altif_n_ep
);
1500 usba_free_cv_array(altif
->altif_cvs
,
1501 altif
->altif_n_cvs
);
1502 kmem_free(altif
->altif_str
, altif
->altif_strsize
);
1505 kmem_free(if_array
[which_if
].if_alt
,
1506 (sizeof (usb_alt_if_data_t
) * n_alts
));
1509 /* Free the interface array itself. */
1510 kmem_free(if_array
, (sizeof (usb_if_data_t
) * n_ifs
));
1515 * usba_free_ep_array:
1516 * Free an array of endpoint nodes and their subtrees of c/v descriptors.
1519 * ep_array - pointer to array of endpoints to remove.
1520 * n_eps - number of elements in the array to remove.
1523 usba_free_ep_array(usb_ep_data_t
*ep_array
, uint_t n_eps
)
1527 for (ep
= 0; ep
< n_eps
; ep
++) {
1528 usba_free_cv_array(ep_array
[ep
].ep_cvs
, ep_array
[ep
].ep_n_cvs
);
1531 kmem_free(ep_array
, (sizeof (usb_ep_data_t
) * n_eps
));
1536 * usba_free_cv_array:
1537 * Free an array of class/vendor (c/v) descriptor nodes.
1540 * cv_array - pointer to array of c/v nodes to remove.
1541 * n_cvs - number of elements in the array to remove.
1544 usba_free_cv_array(usb_cvs_data_t
*cv_array
, uint_t n_cvs
)
1548 /* Free data areas hanging off of each c/v descriptor. */
1549 for (cv_node
= 0; cv_node
< n_cvs
; cv_node
++) {
1550 kmem_free(cv_array
[cv_node
].cvs_buf
,
1551 cv_array
[cv_node
].cvs_buf_len
);
1554 /* Free the array of cv descriptors. */
1555 kmem_free(cv_array
, (sizeof (usb_cvs_data_t
) * n_cvs
));
1560 * usb_log_descr_tree:
1561 * Log to the usba_debug_buf a descriptor tree as returned by
1562 * usbai_register_client.
1565 * dev_data - pointer to registration area containing the tree
1566 * log_handle - pointer to log handle to use for dumping.
1567 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4
1568 * Please see usb_log(9F) for details.
1569 * mask - print mask. Please see usb_log(9F) for details.
1572 * USB_SUCCESS - tree successfully dumped
1573 * USB_INVALID_CONTEXT - called from callback context
1574 * USB_INVALID_ARGS - bad arguments given
1577 usb_log_descr_tree(usb_client_dev_data_t
*dev_data
,
1578 usb_log_handle_t log_handle
, uint_t level
, uint_t mask
)
1580 return (usba_dump_descr_tree(NULL
, dev_data
, log_handle
, level
, mask
));
1585 * usb_print_descr_tree:
1586 * Print to the screen a descriptor tree as returned by
1587 * usbai_register_client.
1590 * dip - pointer to devinfo of the client
1591 * dev_data - pointer to registration area containing the tree
1594 * USB_SUCCESS - tree successfully dumped
1595 * USB_INVALID_CONTEXT - called from callback context
1596 * USB_INVALID_ARGS - bad arguments given
1599 usb_print_descr_tree(dev_info_t
*dip
, usb_client_dev_data_t
*dev_data
)
1601 return (usba_dump_descr_tree(dip
, dev_data
, NULL
, 0, 0));
1606 * usba_dump_descr_tree:
1607 * Dump a descriptor tree.
1610 * dip - pointer to devinfo of the client. Used when no
1611 * log_handle argument given.
1612 * usb_reg - pointer to registration area containing the tree
1613 * log_handle - pointer to log handle to use for dumping. If NULL,
1614 * use internal log handle, which dumps to screen.
1615 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4
1616 * Used only when log_handle provided.
1617 * mask - print mask, used when log_handle argument provided.
1620 * USB_SUCCESS - tree successfully dumped
1621 * USB_INVALID_CONTEXT - called from callback context
1622 * USB_INVALID_ARGS - bad arguments given
1625 usba_dump_descr_tree(dev_info_t
*dip
, usb_client_dev_data_t
*usb_reg
,
1626 usb_log_handle_t log_handle
, uint_t level
, uint_t mask
)
1628 usb_log_handle_t dump_handle
;
1631 int which_config
; /* Counters. */
1634 usb_cfg_data_t
*config
; /* ptr to current configuration tree node */
1635 usb_cfg_descr_t
*config_descr
; /* and its USB descriptor. */
1637 char *name_string
= NULL
;
1638 int name_string_size
;
1640 if ((usb_reg
== NULL
) || ((log_handle
== NULL
) && (dip
== NULL
))) {
1642 return (USB_INVALID_ARGS
);
1646 * To keep calling this simple, kmem_zalloc with the sleep flag always.
1647 * This means no interrupt context is allowed.
1649 if (servicing_interrupt()) {
1651 return (USB_INVALID_CONTEXT
);
1654 string
= kmem_zalloc(USB_MAXSTRINGLEN
, KM_SLEEP
);
1656 if (log_handle
!= NULL
) {
1659 dump_handle
= log_handle
;
1661 dump_level
= USB_LOG_L1
;
1662 dump_mask
= DPRINT_MASK_ALL
;
1664 /* Build device name string. */
1665 (void) snprintf(string
, USB_MAXSTRINGLEN
,
1666 "Port%d", usb_get_addr(dip
));
1667 name_string_size
= strlen(string
) + 1;
1668 name_string
= kmem_zalloc(name_string_size
, KM_SLEEP
);
1669 (void) strcpy(name_string
, string
);
1671 /* Allocate a log handle specifying the name string. */
1672 dump_handle
= usb_alloc_log_hdl(NULL
, name_string
,
1673 &dump_level
, &dump_mask
, NULL
,
1677 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1678 "USB descriptor tree for %s %s",
1679 (usb_reg
->dev_mfg
!= NULL
? usb_reg
->dev_mfg
: ""),
1680 (usb_reg
->dev_product
!= NULL
? usb_reg
->dev_product
: ""));
1681 if (usb_reg
->dev_n_cfg
== 0) {
1682 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1683 "No descriptor tree present");
1685 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1686 "highest configuration found=%d", usb_reg
->dev_n_cfg
- 1);
1689 for (which_config
= 0; which_config
< usb_reg
->dev_n_cfg
;
1691 config
= &usb_reg
->dev_cfg
[which_config
];
1692 config_descr
= &config
->cfg_descr
;
1693 if (config_descr
->bLength
== 0) {
1697 if (dump_level
== USB_LOG_L0
) {
1698 (void) usb_log(dump_handle
, dump_level
, dump_mask
, " ");
1700 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1701 "Configuration #%d (Addr= 0x%p)", which_config
,
1703 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1704 "String descr=%s", config
->cfg_str
);
1705 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1706 "config descr: len=%d tp=%d totLen=%d numIf=%d "
1707 "cfgVal=%d att=0x%x pwr=%d",
1708 config_descr
->bLength
, config_descr
->bDescriptorType
,
1709 config_descr
->wTotalLength
, config_descr
->bNumInterfaces
,
1710 config_descr
->bConfigurationValue
,
1711 config_descr
->bmAttributes
, config_descr
->bMaxPower
);
1712 if ((config
->cfg_n_if
> 0) || (config
->cfg_n_cvs
> 0)) {
1713 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1714 "usb_cfg_data_t shows max if=%d "
1715 "and %d cv descr(s).",
1716 config
->cfg_n_if
- 1, config
->cfg_n_cvs
);
1719 for (which_if
= 0; which_if
< config
->cfg_n_if
;
1722 if (dump_level
== USB_LOG_L0
) {
1723 (void) usb_log(dump_handle
, dump_level
,
1726 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1727 " interface #%d (0x%p)",
1728 which_if
, (void *)&config
->cfg_if
[which_if
]);
1729 usba_dump_if(&config
->cfg_if
[which_if
],
1730 dump_handle
, dump_level
, dump_mask
, string
);
1733 for (which_cv
= 0; which_cv
< config
->cfg_n_cvs
; which_cv
++) {
1734 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1735 " config cv descriptor %d (Address=0x%p)",
1736 which_cv
, (void *)&config
->cfg_cvs
[which_cv
]);
1737 usba_dump_cv(&config
->cfg_cvs
[which_cv
],
1738 dump_handle
, dump_level
, dump_mask
, string
, 4);
1742 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1743 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d",
1744 (void *)usb_reg
->dev_curr_cfg
, usb_reg
->dev_curr_if
);
1746 if (log_handle
== NULL
) {
1747 usb_free_log_hdl(dump_handle
);
1749 if (name_string
!= NULL
) {
1750 kmem_free(name_string
, name_string_size
);
1752 kmem_free(string
, USB_MAXSTRINGLEN
);
1754 return (USB_SUCCESS
);
1760 * Dump an interface node and its branches.
1763 * which_if - interface node to dump
1764 * dump_handle - write data through this log handle
1765 * dump_level - level passed to usb_log
1766 * dump_mask - mask passed to usb_log
1767 * string - temporary area used for processing
1771 usba_dump_if(usb_if_data_t
*which_if
, usb_log_handle_t dump_handle
,
1772 uint_t dump_level
, uint_t dump_mask
, char *string
)
1774 int which_alt
; /* Number of alt being dumped */
1775 usb_alt_if_data_t
*alt
; /* Pointer to it. */
1776 usb_if_descr_t
*if_descr
; /* Pointer to its USB descr. */
1777 int which_ep
; /* Endpoint counter. */
1778 int which_cv
; /* C/V descr counter. */
1780 for (which_alt
= 0; which_alt
< which_if
->if_n_alt
; which_alt
++) {
1781 alt
= &which_if
->if_alt
[which_alt
];
1782 if_descr
= &alt
->altif_descr
;
1784 if (if_descr
->bLength
== 0) {
1788 if (dump_level
== USB_LOG_L0
) {
1789 (void) usb_log(dump_handle
, dump_level
, dump_mask
, " ");
1791 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1792 "\tAlt #%d (0x%p)", which_alt
, (void *)alt
);
1793 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1794 "\tString descr=%s", alt
->altif_str
);
1795 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1796 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d "
1797 "cls=%d sub=%d proto=%d",
1799 if_descr
->bDescriptorType
, if_descr
->bInterfaceNumber
,
1800 if_descr
->bAlternateSetting
, if_descr
->bNumEndpoints
,
1801 if_descr
->bInterfaceClass
, if_descr
->bInterfaceSubClass
,
1802 if_descr
->bInterfaceProtocol
);
1804 if ((alt
->altif_n_ep
> 0) || (alt
->altif_n_cvs
> 0)) {
1805 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1806 "\tusb_alt_if_data_t shows max ep=%d "
1807 "and %d cv descr(s).",
1808 alt
->altif_n_ep
- 1, alt
->altif_n_cvs
);
1811 for (which_ep
= 0; which_ep
< alt
->altif_n_ep
;
1813 if (alt
->altif_ep
[which_ep
].ep_descr
.bLength
== 0) {
1817 if (dump_level
== USB_LOG_L0
) {
1818 (void) usb_log(dump_handle
, dump_level
,
1821 usba_dump_ep(which_ep
, &alt
->altif_ep
[which_ep
],
1822 dump_handle
, dump_level
, dump_mask
, string
);
1825 for (which_cv
= 0; which_cv
< alt
->altif_n_cvs
; which_cv
++) {
1826 if (dump_level
== USB_LOG_L0
) {
1827 (void) usb_log(dump_handle
, dump_level
,
1830 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1831 "\talt cv descriptor #%d (0x%p), size=%d",
1832 which_cv
, (void *)&alt
->altif_cvs
[which_cv
],
1833 alt
->altif_cvs
[which_cv
].cvs_buf_len
);
1834 usba_dump_cv(&alt
->altif_cvs
[which_cv
],
1835 dump_handle
, dump_level
, dump_mask
, string
, 2);
1843 * Dump an endpoint node and its branches.
1846 * which_ep - index to display
1847 * ep - endpoint node to dump
1848 * dump_handle - write data through this log handle
1849 * dump_level - level passed to usb_log
1850 * dump_mask - mask passed to usb_log
1851 * string - temporary area used for processing
1855 usba_dump_ep(uint_t which_ep
, usb_ep_data_t
*ep
, usb_log_handle_t dump_handle
,
1856 uint_t dump_level
, uint_t dump_mask
, char *string
)
1859 usb_ep_descr_t
*ep_descr
= &ep
->ep_descr
;
1861 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1862 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep
,
1863 ep_descr
->bEndpointAddress
, (void *)ep
);
1864 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1865 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d",
1866 ep_descr
->bLength
, ep_descr
->bDescriptorType
,
1867 ep_descr
->bmAttributes
, ep_descr
->wMaxPacketSize
,
1868 ep_descr
->bInterval
);
1869 if (ep
->ep_n_cvs
> 0) {
1870 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1871 "\t usb_ep_data_t shows %d cv descr(s)", ep
->ep_n_cvs
);
1874 for (which_cv
= 0; which_cv
< ep
->ep_n_cvs
; which_cv
++) {
1875 if (dump_level
== USB_LOG_L0
) {
1876 (void) usb_log(dump_handle
, dump_level
,
1879 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1880 "\t endpoint cv descriptor %d (0x%p), size=%d",
1881 which_cv
, (void *)&ep
->ep_cvs
[which_cv
],
1882 ep
->ep_cvs
[which_cv
].cvs_buf_len
);
1883 usba_dump_cv(&ep
->ep_cvs
[which_cv
],
1884 dump_handle
, dump_level
, dump_mask
, string
, 3);
1891 * Dump a raw class or vendor specific descriptor.
1894 * cv_node - pointer to the descriptor to dump
1895 * dump_handle - write data through this log handle
1896 * dump_level - level passed to usb_log
1897 * dump_mask - mask passed to usb_log
1898 * string - temporary area used for processing
1899 * indent - number of tabs to indent output
1903 usba_dump_cv(usb_cvs_data_t
*cv_node
, usb_log_handle_t dump_handle
,
1904 uint_t dump_level
, uint_t dump_mask
, char *string
, int indent
)
1907 usba_dump_bin(cv_node
->cvs_buf
, cv_node
->cvs_buf_len
, indent
,
1908 dump_handle
, dump_level
, dump_mask
, string
,
1916 * Generic byte dump function.
1919 * data - pointer to the data to dump
1920 * max_bytes - amount of data to dump
1921 * indent - number of indentation levels
1922 * dump_handle - write data through this log handle
1923 * dump_level - level passed to usb_log
1924 * dump_mask - mask passed to usb_log
1925 * buffer - temporary area used for processing
1926 * bufferlen - size of the temporary string area
1930 usba_dump_bin(uint8_t *data
, int max_bytes
, int indent
,
1931 usb_log_handle_t dump_handle
, uint_t dump_level
, uint_t dump_mask
,
1932 char *buffer
, int bufferlen
)
1938 if ((indent
* SPACES_PER_INDENT
) >
1939 (bufferlen
- (BINDUMP_BYTES_PER_LINE
* 3))) {
1940 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1941 "Offset to usb_dump_bin must be %d or less. "
1943 (bufferlen
- (BINDUMP_BYTES_PER_LINE
* 3)));
1947 /* Assume a tab is 2 four-space units. */
1948 for (i
= 0; i
< indent
/2; i
++) {
1949 buffer
[bufoffset
] = '\t';
1954 (void) strcpy(&buffer
[bufoffset
], INDENT_SPACE_STR
);
1955 bufoffset
+= SPACES_PER_INDENT
;
1958 i
= 0; /* Num dumped bytes put on this line. */
1959 nexthere
= bufoffset
;
1960 while (i
< max_bytes
) {
1961 (void) sprintf(&buffer
[nexthere
], "%2x ", *data
++);
1964 if (!(i
% BINDUMP_BYTES_PER_LINE
)) {
1965 buffer
[nexthere
] = '\0';
1966 (void) usb_log(dump_handle
, dump_level
, dump_mask
,
1968 nexthere
= bufoffset
;
1972 if (nexthere
> bufoffset
) {
1973 buffer
[nexthere
] = '\0';
1974 (void) usb_log(dump_handle
, dump_level
, dump_mask
, buffer
);
1979 * usb_ep_xdescr_fill:
1981 * Fills in the extended endpoint descriptor based on data from the
1982 * configuration tree.
1985 * version - Should be USB_EP_XDESCR_CURRENT_VERSION
1986 * dip - devinfo pointer
1987 * ep_data - endpoint data pointer
1988 * ep_xdesc - An extended descriptor structure, filled upon
1989 * successful completion.
1992 * USB_SUCCESS - filling data succeeded
1993 * USB_INVALID_ARGS - invalid arguments
1996 usb_ep_xdescr_fill(uint_t version
, dev_info_t
*dip
, usb_ep_data_t
*ep_data
,
1997 usb_ep_xdescr_t
*ep_xdescr
)
1999 if (version
!= USB_EP_XDESCR_VERSION_ONE
) {
2001 return (USB_INVALID_ARGS
);
2004 if (dip
== NULL
|| ep_data
== NULL
|| ep_xdescr
== NULL
) {
2006 return (USB_INVALID_ARGS
);
2009 bzero(ep_xdescr
, sizeof (usb_ep_xdescr_t
));
2010 ep_xdescr
->uex_version
= version
;
2011 ep_xdescr
->uex_ep
= ep_data
->ep_descr
;
2012 if (ep_data
->ep_ss_valid
== B_TRUE
) {
2013 ep_xdescr
->uex_flags
|= USB_EP_XFLAGS_SS_COMP
;
2014 ep_xdescr
->uex_ep_ss
= ep_data
->ep_ss_comp
;
2017 return (USB_SUCCESS
);