/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
*/
/*
* USBA: Solaris USB Architecture support
*
* This module builds a tree of parsed USB standard descriptors and unparsed
* groups: those which build the tree, those which take it down, and those which
* dump it.
*
* The tree built hangs off of the dev_cfg field of the usb_client_dev_data_t
* structure returned by usb_get_dev_data(). The tree consists of different
* kinds of tree nodes (usb_xxx_data_t) each containing a standard USB
* descriptor (usb_xxx_descr_t) and pointers to arrays of other nodes.
*
* Arrays are dynamically sized, as the descriptors coming from the device may
* lie, but the number of descriptors from the device is a more reliable
* indicator of configuration. This makes the code more robust. After the raw
* descriptor data has been parsed into a non-sparse tree, the tree is ordered
* and made sparse with a bin-sort style algorithm.
*
* dev_cfg is an array of configuration tree nodes. Each contains space for one
* parsed standard USB configuration descriptor, a pointer to an array of c/v
* tree nodes and a pointer to an array of interface tree nodes.
*
* Each interface tree node represents a group of interface descriptors, called
* alternates, with the same interface number. Thus, each interface tree node
* has a pointer to an array of alternate-interface tree nodes each containing a
* standard USB interface descriptor. Alternate-interface tree nodes also
* contain a pointer to an array of c/v tree nodes and a pointer to an array of
* endpoint tree nodes.
*
* Endpoint tree nodes contain a standard endpoint descriptor, plus a pointer to
* an array of c/v tree nodes.
*
* Each array in the tree contains elements ranging from 0 to the largest key
* value of it's elements. Endpoints are a special case. The direction bit is
* right shifted over three unused bits before the index is determined, leaving
* a range of 0..31 instead of a sparsely-populated range of 0..255.
*
* The indices of tree elements coincide with their USB key values. For
* example, standard USB devices have no configuration 0; if they have one
* configuration it is #1. dev_cfg[0] is zeroed out; dev_cfg[1] is the root
* of configuration #1.
*
* The idea here is for a driver to be able to parse the tree to easily find a
* desired descriptor. For example, the interval of endpoint 2, alternate 3,
* interface 1, configuration 1 would be:
* dv->dev_cfg[1].cfg_if[1].if_alt[3].altif_ep[2].ep_descr.bInterval
*
* How the tree is built:
*
* usb_build_descr_tree() is responsible for the whole process.
*
* Next, usba_build_descr_tree() coordinates parsing this byte stream,
* descriptor by descriptor. usba_build_descr_tree() calls the appropriate
* usba_process_xx_descr() function to interpret and install each descriptor in
* the tree, based on the descriptor's type. When done with this phase, a
* non-sparse tree exists containing tree nodes with descriptors in the order
* they were found in the raw data.
*
* All levels of the tree, except alternates, remain non-sparse. Alternates are
* moved, possibly, within their array, so that descriptors are indexed by their
* alternate ID.
*
* The usba_reg_state_t structure maintains state of the tree-building process,
* helping coordinate all routines involved.
*/
#define USBA_FRAMEWORK
/*
* Header needed for use by this module only.
* However, function may be used in V0.8 drivers so needs to be global.
*/
/* Debug stuff */
/* Function prototypes */
static void usba_process_cfg_descr(usba_reg_state_t *);
static int usba_process_ep_descr(usba_reg_state_t *);
static int usba_process_cv_descr(usba_reg_state_t *);
static void* usba_kmem_realloc(void *, int, int);
static void usba_order_tree(usba_reg_state_t *);
uint_t, char *);
char *, int);
/* Framework initialization. */
void
{
0);
"usba_usbai_register_initialization");
}
/* Framework destruction. */
void
{
"usba_usbai_register destroy");
}
/*
* usb_client_attach:
*
* Arguments:
* dip - pointer to devinfo node of the client
* version - USBA registration version number
* flags - None used
*
* Return Values:
* USB_SUCCESS - attach succeeded
* USB_INVALID_ARGS - received null dip
* USB_INVALID_VERSION - version argument is incorrect.
* USB_FAILURE - other internal failure
*/
/*ARGSUSED*/
int
{
int rval;
return (USB_INVALID_ARGS);
}
"usb_client attach:");
/*
* Allow exact match for legacy (DDK 0.8/9) drivers, or same major
* VERSion and smaller or same minor version for non-legacy drivers.
*/
if ((version !=
"Incorrect USB driver version for %s%d: found: %d.%d, "
"expecting %d.%d",
return (USB_INVALID_VERSION);
}
"Accepting legacy USB driver version %d.%d for %s%d",
}
if (rval != DDI_PROP_SUCCESS) {
return (USB_FAILURE);
}
if (rval != DDI_PROP_SUCCESS) {
return (USB_FAILURE);
}
}
"usb_client attach: done");
return (USB_SUCCESS);
}
/*
* usb_client_detach:
* free dev_data is reg != NULL, not much else to do
*
* Arguments:
* dip - pointer to devinfo node of the client
* reg - return registration data at this address
*/
void
{
"usb_client_detach:");
if (dip) {
"Unregistering usb client %s%d: reg=0x%p",
}
}
"usb_client_detach done");
}
/*
* usb_register_client (deprecated):
* The client registers with USBA during attach.
*/
/*ARGSUSED*/
int
{
if (rval == USB_SUCCESS) {
if (rval != USB_SUCCESS) {
}
}
return (rval);
}
/*
* usb_unregister_client (deprecated):
* Undo the makings of usb_get_dev_data(). Free memory if allocated.
*
* Arguments:
* dip - pointer to devinfo node of the client
* reg - pointer to registration data to be freed
*/
void
{
}
/*
* usb_get_dev_data:
* On completion, the registration data has been initialized.
* Most data items are straightforward.
* Among the items returned in the data is the tree of
* parsed descriptors, in dev_cfg; the number of configurations parsed,
* in dev_n_cfg; a pointer to the current configuration in the tree,
* in dev_curr_cfg; the index of the first valid interface in the
* tree, in dev_curr_if, and a parse level that accurately reflects what
* is in the tree, in dev_parse_level.
*
* This routine sets up directly-initialized fields, and calls
* usb_build_descr_tree() to parse the raw descriptors and initialize the
* tree.
*
* Parse_level determines the extent to which the tree is built. It has
* the following values:
*
* USB_PARSE_LVL_NONE - Build no tree. dev_n_cfg will return 0, dev_cfg
* and dev_curr_cfg will return NULL.
* USB_PARSE_LVL_IF - Parse configured interface only, if configuration#
* and interface properties are set (as when different
* interfaces are viewed by the OS as different device
* instances). If an OS device instance is set up to
* represent an entire physical device, this works
* like USB_PARSE_LVL_ALL.
* USB_PARSE_LVL_CFG - Parse entire configuration of configured interface
* only. This is like USB_PARSE_LVL_IF except entire
* configuration is returned.
* USB_PARSE_LVL_ALL - Parse entire device (all configurations), even
* when driver is bound to a single interface of a
* single configuration.
*
* No tree is built for root hubs, regardless of parse_level.
*
* Arguments:
* dip - pointer to devinfo node of the client
* version - USBA registration version number
* reg - return registration data at this address
* parse_level - See above
* flags - None used
*
* Return Values:
* USB_SUCCESS - usb_get_dev_data succeeded
* USB_INVALID_ARGS - received null dip or reg argument
* USB_INVALID_CONTEXT - called from callback context
* USB_FAILURE - bad descriptor info or other internal failure
*
* Note: The non-standard USB descriptors are returned in RAW format.
* returns initialized registration data. Most data items are clear.
* Among the items returned is the tree of parsed descriptors in dev_cfg;
* and the number of configurations parsed in dev_n_cfg.
*
* The registration data is not shared. each client receives its own
* copy.
*/
/*ARGSUSED*/
int
{
return (USB_INVALID_ARGS);
}
"usb_get_dev_data: %s%d",
/* did the client attach first? */
"driver-major", -1) == -1) {
return (USB_INVALID_VERSION);
}
"driver-minor", -1) == -1) {
return (USB_INVALID_VERSION);
}
return (USB_FAILURE);
}
}
KM_SLEEP);
}
KM_SLEEP);
}
rval = USB_SUCCESS;
USB_SUCCESS) {
} else {
/* Current tree cfg is always zero if only one cfg in tree. */
} else {
}
/*
* Keep dev_curr_if at device's single interface only if that
* particular interface has been explicitly defined by the
* device.
*/
#ifdef DEBUG
#endif
/*
* Fail if interface and configuration of dev_curr_if and
* dev_curr_cfg don't exist or are invalid. (Shouldn't happen.)
* These indices must be reliable for tree traversal.
*/
if_n_alt == 0)) {
"usb_get_dev_data: dev_curr_cfg or "
"dev_curr_if have no descriptors");
rval = USB_FAILURE;
}
}
if (rval == USB_SUCCESS) {
}
}
"usb_get_dev_data rval=%d", rval);
return (rval);
}
/*
* usb_free_dev_data
* undoes what usb_get_dev_data does
*
* Arguments:
* dip - pointer to devinfo node of the client
* reg - return registration data at this address
*/
void
{
return;
}
"usb_free_dev_data %s%d: reg=0x%p",
int matches = 0;
}
}
}
/* Free config tree under reg->dev_cfg. */
}
/* free the entries in usb_client_data_list */
while (entry) {
}
} else {
/*
* any other entries for this interface?
*/
matches++;
}
}
}
"usb_free_dev_data: next=0x%p flags[%d]=0x%x",
if (matches == 0) {
}
}
"usb_free_dev_data done");
}
/*
* usba_build_descr_tree:
* This builds the descriptor tree. See module header comment for tree
* description.
*
* Arguments:
* dip - devinfo pointer - cannot be NULL.
* usba_device - pointer to usba_device structure.
* usb_reg - pointer to area returned to client describing device.
* number of configuration (dev_n_cfg) and array of
* configurations (dev_cfg) are initialized here -
* dev_parse_level used and may be modified to fit
* current configuration.
* Return values:
* USB_SUCCESS - Tree build succeeded
* USB_INVALID_ARGS - dev_parse_level in usb_reg is invalid.
* USB_FAILURE - Bad descriptor info or other internal failure
*/
static int
{
/* of this interface. */
"usba_build_descr_tree starting");
/*
* Set config(s) and interface(s) to parse based on parse level.
* Adjust parse_level according to which configs and interfaces are
* made available by the device.
*/
return (USB_INVALID_ARGS);
}
/* Preallocate configurations based on parse level. */
low_cfg_bound = 0;
} else {
}
KM_SLEEP);
/*
* this_cfg_ndx loops through all configurations presented;
* state.st_dev_n_cfg limits the cfgs checked to the number desired.
*/
state.st_dev_n_cfg = 0;
this_cfg_ndx++) {
/* Clear the following for config cloud sanity checking. */
do {
/* All descr have length and type at offset 0 and 1 */
/* First descr in cloud must be a config descr. */
return (USB_FAILURE);
}
/*
* Bomb if we don't find a new cfg descr when expected.
* cfg_len_so_far = total_cfg_length = 0 1st time thru.
*/
"usba_build_descr_tree: Configuration (%d) "
"larger than wTotalLength (%d).",
return (USB_FAILURE);
}
"usba_build_descr_tree: Process type %d descr "
(void *)state.st_curr_raw_descr);
switch (state.st_curr_raw_descr_type) {
case USB_DESCR_TYPE_CFG:
cfg_len_so_far = 0;
sizeof (uchar_t));
break;
case USB_DESCR_TYPE_IF:
/*
* process_this_if_tree == TRUE means this
* to be processed.
*/
if (usba_process_if_descr(&state,
&process_this_if_tree) != USB_SUCCESS) {
return (USB_FAILURE);
}
break;
case USB_DESCR_TYPE_EP:
/*
* Skip if endpoints of a specific interface are
* desired and this endpoint is associated with
* a different interface.
*/
if (process_this_if_tree) {
if (usba_process_ep_descr(&state) !=
USB_SUCCESS) {
return (USB_FAILURE);
}
}
break;
case USB_DESCR_TYPE_STRING:
"usb_get_dev_data: "
"Found unexpected str descr at addr 0x%p",
(void *)state.st_curr_raw_descr);
break; /* Shouldn't be any here. Skip. */
default:
/*
* interface are desired and this c/v is
* associated with a different one.
* processed, e.g., the security descrs
* for the Host Wire Adapter.
*/
if ((state.st_last_processed_descr_type ==
(process_this_if_tree == B_TRUE)) {
if (usba_process_cv_descr(&state) !=
USB_SUCCESS) {
return (USB_FAILURE);
}
}
}
}
/* Make tree sparse, and put elements in order. */
"usba_build_descr_tree done");
return (USB_SUCCESS);
}
/*
* usba_process_cfg_descr:
* Set up a configuration tree node based on a raw config descriptor.
*
* Arguments:
* state - Pointer to this module's state structure.
*
* Returns:
* B_TRUE: the descr processed corresponds to a requested configuration.
* B_FALSE: the descr processed does not correspond to a requested config.
*/
static void
{
"usba_process_cfg_descr starting");
/* Parse and store config descriptor proper in the tree. */
(void) usb_parse_data("2cs5c",
sizeof (usb_cfg_descr_t));
KM_SLEEP);
}
sizeof (usb_if_data_t)), KM_SLEEP);
"usba_process_cfg_descr done");
}
/*
* usba_process_if_descr:
* This processes a raw interface descriptor, and sets up an analogous
* interface node and child "alternate" nodes (each containing an
* interface descriptor) in the descriptor tree.
*
* It groups all descriptors with the same bInterfaceNumber (alternates)
* into an array. It makes entries in an interface array, each of which
* points to an array of alternates.
*
* Arguments:
* state - Pointer to this module's state structure.
* requested_if - Address into which the following is returned:
* B_TRUE - the processed descr is of a requested interface.
* B_FALSE - the processed descr if of a non-requested interface.
*
* Returns:
* USB_SUCCESS: Descriptor is successfully parsed.
* USB_FAILURE: Descriptor is inappropriately placed in config cloud.
*/
static int
{
char *string;
"usba_process_if_descr starting");
/* No config preceeds this interface. */
"usba_process_if_descr found interface after no config.");
return (USB_FAILURE);
}
/* Strictly speaking, unpacking is not necessary. Could use bcopy. */
new_if_descr, sizeof (usb_if_descr_t));
/* Check the interface number in case of a malfunction device */
"usba_process_if_descr: bInterfaceNumber=%d is not "
*requested_if = B_FALSE;
return (USB_SUCCESS);
}
*requested_if = B_TRUE;
/* Not a requested interface. */
*requested_if = B_FALSE;
} else {
/* Point to proper interface node, based on num in descr. */
state->st_curr_if =
/* Make room for new alternate. */
sizeof (usb_alt_if_data_t));
/* Ptr to the current alt, may be used to attach a c/v to it. */
sizeof (usb_if_descr_t));
if (!is_root_hub) {
}
if (string[0] == '\0') {
}
}
"usba_process_if_descr done");
return (USB_SUCCESS);
}
/*
* usba_process_ep_descr:
* This processes a raw endpoint descriptor, and sets up an analogous
* endpoint descriptor node in the descriptor tree.
*
* Arguments:
* state - Pointer to this module's state structure.
*
* Returns:
* USB_SUCCESS: Descriptor is successfully parsed.
* USB_FAILURE: Descriptor is inappropriately placed in config cloud.
*/
static int
{
"usba_process_ep_descr starting");
/* No interface preceeds this endpoint. */
"usba_process_ep_descr: no requested alt before endpt.");
return (USB_FAILURE);
}
/* Ptr to the current endpt, may be used to attach a c/v to it. */
"usba_process_ep_descr done");
return (USB_SUCCESS);
}
/*
* usba_process_cv_descr:
* This processes a raw endpoint descriptor, and sets up an analogous
* other descriptors they follow in the raw data.
* last_processed_descr_type indicates the type of descr this c/v follows.
*
* Arguments:
* state - Pointer to this module's state structure.
*
* Returns:
* USB_SUCCESS: Descriptor is successfully parsed.
* USB_FAILURE: Descriptor is inappropriately placed in config cloud.
*/
static int
{
"usba_process_cv_descr starting. Processing c/v for descr type %d",
/*
* Attach the c/v to a node based on the last descr type processed.
* Save handles to appropriate c/v node array and count to update.
*/
switch (state->st_last_processed_descr_type) {
case USB_DESCR_TYPE_CFG:
break;
case USB_DESCR_TYPE_IF:
break;
case USB_DESCR_TYPE_EP:
break;
default:
"usba_process_cv_descr: Type of last descriptor unknown. ");
return (USB_FAILURE);
}
sizeof (usb_cvs_data_t));
"usba_process_cv_descr done");
return (USB_SUCCESS);
}
/*
* usba_set_parse_values:
* Based on parse level, set the configuration(s) and interface(s) to build
*
* Returned configuration value can be USBA_ALL indicating to build all
* configurations. Likewise for the returned interface value.
*
* Arguments:
* dip - pointer to devinfo of the device
* usba_device - pointer to usba_device structure of the device
* state - Pointer to this module's state structure.
* if no specific config specified, default to all config
* if no specific interface specified, default to all.
* if_to_build and config_to_build are modified.
* dev_parse_level may be modified.
*
* Returns:
* USB_SUCCESS - success
* USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
*/
static int
{
/* Default to *all* in case configuration# prop not set. */
}
switch (state->st_dev_parse_level) {
case USB_PARSE_LVL_ALL: /* Parse all configurations */
break;
case USB_PARSE_LVL_CFG: /* Parse all interfaces of a */
/* specific configuration. */
break;
case USB_PARSE_LVL_IF: /* Parse configured interface only */
if (state->st_if_to_build < 0) {
}
break;
default:
return (USB_INVALID_ARGS);
}
/*
* Set parse level to identify this tree properly, regardless of what
* the caller thought the tree would have.
*/
}
}
return (USB_SUCCESS);
}
/*
* usba_kmem_realloc:
* Resize dynamic memory. Copy contents of old area to
* beginning of new area.
*
* Arguments:
* old_mem - pointer to old memory area.
* old_size - size of old memory area. 0 is OK.
* new_size - size desired.
*
* Returns:
* pointer to new memory area.
*/
static void*
{
if (new_size > 0) {
if (old_size > 0) {
}
}
if (old_size > 0) {
}
return (new_mem);
}
/*
* usba_augment_array:
* Add a new element on the end of an array.
*
* Arguments:
* addr - ptr to the array address. Array addr will change.
* n_elements - array element count.
* element_size - size of an array element
*/
static void
{
}
/*
* usba_make_alts_sparse:
* Disburse alternate array elements such that they are at the proper array
* indices for which alt they represent. It is assumed that all key values
* used for ordering the elements are positive. Original array space may
* be freed and new space allocated.
*
* Arguments:
* array - pointer to alternates array; may be modified
* n_elements - number of elements in the array; may be modified
*/
static void
{
uint_t i;
/* Check for a null array. */
return;
}
"make_sparse: array=0x%p, n_orig_elements=%d",
(void *)array, n_orig_elements);
/* Figure the low-high range of the array. */
for (i = 1; i < n_orig_elements; i++) {
if (curr_value < smallest_value) {
} else if (curr_value > largest_value) {
in_order++;
}
}
"make_sparse: largest=%d, smallest=%d, "
"order=%d",
/*
* No holes to leave, array starts at zero, and everything is already
* in order. Just return original array.
*/
if ((n_repl_elements == n_orig_elements) &&
"No holes");
return;
}
/* Allocate zeroed space for the array. */
/* Now fill in the array. */
for (i = 0; i < n_orig_elements; i++) {
/* Place in sparse array based on key. */
"move %lu bytes (key %d) from 0x%p to 0x%p",
(unsigned long)sizeof (usb_alt_if_data_t), curr_value,
sizeof (usb_alt_if_data_t));
}
*array = repl_array;
}
/*
* usba_order_tree:
* Take a tree as built by usba_build_descr_tree and make sure the key
* values of all elements match their indeces. Proper order is implied.
*
* Arguments:
* state - Pointer to this module's state structure.
*/
static void
{
"usba_order_tree:");
}
}
}
/*
* usb_free_descr_tree:
* Take down the configuration tree. Called internally and can be called
* from a driver standalone to take the tree down while leaving the rest
* of the registration intact.
*
* Arguments:
* dip - pointer to devinfo of the device
* dev_data - pointer to registration data containing the tree.
*/
void
{
int n_cfgs;
int cfg;
return;
}
"usb_free_descr_tree starting for %s%d",
}
}
}
}
if (cfg_array) {
}
"usb_free_descr_tree done");
}
/*
* usba_free_if_array:
* Free a configuration's array of interface nodes and their subtrees of
* interface alternate, endpoint and c/v descriptors.
*
* Arguments:
* if_array - pointer to array of interfaces to remove.
* n_ifs - number of elements in the array to remove.
*/
static void
{
/* Every interface has at least one alternate. */
altif->altif_n_cvs);
}
(sizeof (usb_alt_if_data_t) * n_alts));
}
/* Free the interface array itself. */
}
/*
* usba_free_ep_array:
* Free an array of endpoint nodes and their subtrees of c/v descriptors.
*
* Arguments:
* ep_array - pointer to array of endpoints to remove.
* n_eps - number of elements in the array to remove.
*/
static void
{
}
}
/*
* usba_free_cv_array:
*
* Arguments:
* cv_array - pointer to array of c/v nodes to remove.
* n_cvs - number of elements in the array to remove.
*/
static void
{
/* Free data areas hanging off of each c/v descriptor. */
}
/* Free the array of cv descriptors. */
}
/*
* usb_log_descr_tree:
* Log to the usba_debug_buf a descriptor tree as returned by
* usbai_register_client.
*
* Arguments:
* dev_data - pointer to registration area containing the tree
* log_handle - pointer to log handle to use for dumping.
* level - print level, one of USB_LOG_L0 ... USB_LOG_L4
* Please see usb_log(9F) for details.
* mask - print mask. Please see usb_log(9F) for details.
*
* Returns:
* USB_SUCCESS - tree successfully dumped
* USB_INVALID_CONTEXT - called from callback context
* USB_INVALID_ARGS - bad arguments given
*/
int
{
}
/*
* usb_print_descr_tree:
* Print to the screen a descriptor tree as returned by
* usbai_register_client.
*
* Arguments:
* dip - pointer to devinfo of the client
* dev_data - pointer to registration area containing the tree
*
* Returns:
* USB_SUCCESS - tree successfully dumped
* USB_INVALID_CONTEXT - called from callback context
* USB_INVALID_ARGS - bad arguments given
*/
int
{
}
/*
* usba_dump_descr_tree:
* Dump a descriptor tree.
*
* Arguments:
* dip - pointer to devinfo of the client. Used when no
* log_handle argument given.
* usb_reg - pointer to registration area containing the tree
* log_handle - pointer to log handle to use for dumping. If NULL,
* use internal log handle, which dumps to screen.
* level - print level, one of USB_LOG_L0 ... USB_LOG_L4
* Used only when log_handle provided.
* mask - print mask, used when log_handle argument provided.
*
* Returns:
* USB_SUCCESS - tree successfully dumped
* USB_INVALID_CONTEXT - called from callback context
* USB_INVALID_ARGS - bad arguments given
*/
static int
{
int which_if;
int which_cv;
char *string;
int name_string_size;
return (USB_INVALID_ARGS);
}
/*
* To keep calling this simple, kmem_zalloc with the sleep flag always.
* This means no interrupt context is allowed.
*/
if (servicing_interrupt()) {
return (USB_INVALID_CONTEXT);
}
if (log_handle != NULL) {
dump_level = level;
} else {
/* Build device name string. */
/* Allocate a log handle specifying the name string. */
}
"USB descriptor tree for %s %s",
"No descriptor tree present");
} else {
}
which_config++) {
if (config_descr->bLength == 0) {
continue;
}
if (dump_level == USB_LOG_L0) {
}
"Configuration #%d (Addr= 0x%p)", which_config,
(void *)config);
"config descr: len=%d tp=%d totLen=%d numIf=%d "
"cfgVal=%d att=0x%x pwr=%d",
"usb_cfg_data_t shows max if=%d "
"and %d cv descr(s).",
}
which_if++) {
if (dump_level == USB_LOG_L0) {
dump_mask, " ");
}
" interface #%d (0x%p)",
}
" config cv descriptor %d (Address=0x%p)",
}
}
"Returning dev_curr_cfg:0x%p, dev_curr_if:%d",
if (log_handle == NULL) {
}
if (name_string != NULL) {
}
return (USB_SUCCESS);
}
/*
* usba_dump_if:
* Dump an interface node and its branches.
*
* Arguments:
* which_if - interface node to dump
* dump_handle - write data through this log handle
* dump_level - level passed to usb_log
* dump_mask - mask passed to usb_log
* string - temporary area used for processing
*
*/
static void
{
continue;
}
if (dump_level == USB_LOG_L0) {
}
"\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d "
"cls=%d sub=%d proto=%d",
"\tusb_alt_if_data_t shows max ep=%d "
"and %d cv descr(s).",
}
which_ep++) {
continue;
}
if (dump_level == USB_LOG_L0) {
dump_mask, " ");
}
}
if (dump_level == USB_LOG_L0) {
dump_mask, " ");
}
"\talt cv descriptor #%d (0x%p), size=%d",
}
}
}
/*
* usba_dump_ep:
* Dump an endpoint node and its branches.
*
* Arguments:
* which_ep - index to display
* ep - endpoint node to dump
* dump_handle - write data through this log handle
* dump_level - level passed to usb_log
* dump_mask - mask passed to usb_log
* string - temporary area used for processing
*
*/
static void
{
int which_cv;
"\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep,
"\t len=%d type=%d attr=0x%x pktsize=%d interval=%d",
}
if (dump_level == USB_LOG_L0) {
dump_mask, " ");
}
"\t endpoint cv descriptor %d (0x%p), size=%d",
}
}
/*
* usba_dump_cv:
* Dump a raw class or vendor specific descriptor.
*
* Arguments:
* cv_node - pointer to the descriptor to dump
* dump_handle - write data through this log handle
* dump_level - level passed to usb_log
* dump_mask - mask passed to usb_log
* string - temporary area used for processing
* indent - number of tabs to indent output
*
*/
static void
{
if (cv_node) {
}
}
/*
* usba_dump_bin:
* Generic byte dump function.
*
* Arguments:
* data - pointer to the data to dump
* max_bytes - amount of data to dump
* indent - number of indentation levels
* dump_handle - write data through this log handle
* dump_level - level passed to usb_log
* dump_mask - mask passed to usb_log
* buffer - temporary area used for processing
* bufferlen - size of the temporary string area
*
*/
static void
{
int i;
int bufoffset = 0;
int nexthere;
if ((indent * SPACES_PER_INDENT) >
"Offset to usb_dump_bin must be %d or less. "
"Setting to 0.\n",
indent = 0;
}
/* Assume a tab is 2 four-space units. */
for (i = 0; i < indent/2; i++) {
bufoffset++;
}
if (indent % 2) {
}
i = 0; /* Num dumped bytes put on this line. */
while (i < max_bytes) {
nexthere += 3;
i++;
if (!(i % BINDUMP_BYTES_PER_LINE)) {
buffer);
}
}
}
}