Print this page
5832 EOF wireless usb (aka UWB)
Reviewed by: TBD
Reviewed by: TBD
Approved by: TBD


   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.


  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);


 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);


 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++;


 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
 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
 702 usba_build_descr_tree(dev_info_t *dip, usba_device_t *usba_device,
 703     usb_client_dev_data_t *usb_reg)


 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 ==


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
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
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;


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
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;




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  26  */
  27 
  28 /*
  29  * USBA: Solaris USB Architecture support
  30  *
  31  * This module builds a tree of parsed USB standard descriptors and unparsed
  32  * Class/Vendor specific (C/V) descriptors.  Routines are grouped into three
  33  * groups: those which build the tree, those which take it down, and those which
  34  * dump it.
  35  *
  36  * The tree built hangs off of the dev_cfg field of the usb_client_dev_data_t
  37  * structure returned by usb_get_dev_data().  The tree consists of different
  38  * kinds of tree nodes (usb_xxx_data_t) each containing a standard USB
  39  * descriptor (usb_xxx_descr_t) and pointers to arrays of other nodes.
  40  *
  41  * Arrays are dynamically sized, as the descriptors coming from the device may
  42  * lie, but the number of descriptors from the device is a more reliable
  43  * indicator of configuration.  This makes the code more robust.  After the raw
  44  * descriptor data has been parsed into a non-sparse tree, the tree is ordered
  45  * and made sparse with a bin-sort style algorithm.


  97 #include <sys/usb/usba/usba_private.h>
  98 #include <sys/usb/usba/hcdi_impl.h>
  99 #include <sys/usb/hubd/hub.h>
 100 
 101 #include <sys/usb/usba/usbai_register_impl.h>
 102 
 103 /*
 104  * Header needed for use by this module only.
 105  * However, function may be used in V0.8 drivers so needs to be global.
 106  */
 107 int usb_log_descr_tree(usb_client_dev_data_t *, usb_log_handle_t,
 108                                 uint_t, uint_t);
 109 
 110 /* Debug stuff */
 111 usb_log_handle_t        usbai_reg_log_handle;
 112 uint_t                  usbai_register_errlevel = USB_LOG_L2;
 113 uint_t                  usbai_register_dump_errlevel = USB_LOG_L2;
 114 uint_t                  usbai_register_errmask = (uint_t)-1;
 115 
 116 /* Function prototypes */

 117 static int usba_build_descr_tree(dev_info_t *, usba_device_t *,
 118                                 usb_client_dev_data_t *);
 119 static void usba_process_cfg_descr(usba_reg_state_t *);
 120 static int usba_process_if_descr(usba_reg_state_t *, boolean_t *);
 121 static int usba_process_ep_descr(usba_reg_state_t *);
 122 static int usba_process_cv_descr(usba_reg_state_t *);

 123 static int usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
 124     usba_reg_state_t *state);
 125 static void* usba_kmem_realloc(void *, int, int);
 126 static void usba_augment_array(void **, uint_t, uint_t);
 127 static void usba_make_alts_sparse(usb_alt_if_data_t **, uint_t *);
 128 
 129 static void usba_order_tree(usba_reg_state_t *);
 130 
 131 static void usba_free_if_array(usb_if_data_t *, uint_t);
 132 static void usba_free_ep_array(usb_ep_data_t *, uint_t);
 133 static void usba_free_cv_array(usb_cvs_data_t *, uint_t);
 134 
 135 static int usba_dump_descr_tree(dev_info_t *, usb_client_dev_data_t *,
 136                                 usb_log_handle_t, uint_t, uint_t);
 137 static void usba_dump_if(usb_if_data_t *, usb_log_handle_t,
 138                                 uint_t, uint_t, char *);
 139 static void usba_dump_ep(uint_t, usb_ep_data_t *, usb_log_handle_t, uint_t,
 140                                 uint_t, char *);
 141 static void usba_dump_cv(usb_cvs_data_t *, usb_log_handle_t, uint_t, uint_t,
 142                                 char *, int);


 410             "driver-major", -1) == -1) {
 411 
 412                 return (USB_INVALID_VERSION);
 413         }
 414         if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 415             "driver-minor", -1) == -1) {
 416 
 417                 return (USB_INVALID_VERSION);
 418         }
 419 
 420         usb_reg = kmem_zalloc(sizeof (usb_client_dev_data_t), KM_SLEEP);
 421         usba_device = usba_get_usba_device(dip);
 422         usb_reg->dev_descr = usba_device->usb_dev_descr;
 423         usb_reg->dev_default_ph = usba_get_dflt_pipe_handle(dip);
 424         if (usb_reg->dev_default_ph == NULL) {
 425                 kmem_free(usb_reg, sizeof (usb_client_dev_data_t));
 426 
 427                 return (USB_FAILURE);
 428         }
 429 










 430         usb_reg->dev_iblock_cookie = usba_hcdi_get_hcdi(
 431             usba_device->usb_root_hub_dip)->hcdi_soft_iblock_cookie;
 432 
 433         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 434             "cookie = 0x%p", (void *)usb_reg->dev_iblock_cookie);
 435 
 436         tmpbuf = (char *)kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
 437 
 438         if (usba_device->usb_mfg_str != NULL) {
 439                 usb_reg->dev_mfg = kmem_zalloc(
 440                     strlen(usba_device->usb_mfg_str) + 1, KM_SLEEP);
 441                 (void) strcpy(usb_reg->dev_mfg, usba_device->usb_mfg_str);
 442         }
 443 
 444         if (usba_device->usb_product_str != NULL) {
 445                 usb_reg->dev_product = kmem_zalloc(
 446                     strlen(usba_device->usb_product_str) + 1,
 447                     KM_SLEEP);
 448                 (void) strcpy(usb_reg->dev_product,
 449                     usba_device->usb_product_str);


 568                 if (reg->dev_serial != NULL) {
 569                         kmem_free((char *)reg->dev_serial,
 570                             strlen((char *)reg->dev_serial) + 1);
 571                 }
 572 
 573                 if (reg->dev_product != NULL) {
 574                         kmem_free((char *)reg->dev_product,
 575                             strlen((char *)reg->dev_product) + 1);
 576                 }
 577 
 578                 if (reg->dev_mfg != NULL) {
 579                         kmem_free((char *)reg->dev_mfg,
 580                             strlen((char *)reg->dev_mfg) + 1);
 581                 }
 582 
 583                 /* Free config tree under reg->dev_cfg. */
 584                 if (reg->dev_cfg != NULL) {
 585                         usb_free_descr_tree(dip, reg);
 586                 }
 587 




 588                 mutex_enter(&usba_device->usb_mutex);
 589                 prev = &usba_device->usb_client_dev_data_list;
 590                 entry = usba_device->usb_client_dev_data_list.cddl_next;
 591 
 592                 /* free the entries in usb_client_data_list */
 593                 while (entry) {
 594                         next = entry->cddl_next;
 595                         if ((dip == entry->cddl_dip) &&
 596                             (reg == entry->cddl_dev_data)) {
 597                                 prev->cddl_next = entry->cddl_next;
 598                                 if (entry->cddl_next) {
 599                                         entry->cddl_next->cddl_prev = prev;
 600                                 }
 601                                 kmem_free(entry, sizeof (*entry));
 602                         } else {
 603                                 /*
 604                                  * any other entries for this interface?
 605                                  */
 606                                 if (usba_get_ifno(dip) == entry->cddl_ifno) {
 607                                         matches++;


 616                     "usb_free_dev_data: next=0x%p flags[%d]=0x%x",
 617                     (void *)usba_device->usb_client_dev_data_list.cddl_next,
 618                     usba_get_ifno(dip),
 619                     usba_device->usb_client_flags[usba_get_ifno(dip)]);
 620 
 621                 if (matches == 0) {
 622                         usba_device->
 623                             usb_client_flags[usba_get_ifno(dip)] &=
 624                             ~USBA_CLIENT_FLAG_DEV_DATA;
 625                 }
 626                 mutex_exit(&usba_device->usb_mutex);
 627 
 628                 kmem_free(reg, sizeof (usb_client_dev_data_t));
 629         }
 630 
 631         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
 632             "usb_free_dev_data done");
 633 }
 634 
 635 /*


































 636  * usba_build_descr_tree:
 637  *      This builds the descriptor tree.  See module header comment for tree
 638  *      description.
 639  *
 640  * Arguments:
 641  *      dip             - devinfo pointer - cannot be NULL.
 642  *      usba_device     - pointer to usba_device structure.
 643  *      usb_reg         - pointer to area returned to client describing device.
 644  *                        number of configuration (dev_n_cfg) and array of
 645  *                        configurations (dev_cfg) are initialized here -
 646  *                        dev_parse_level used and may be modified to fit
 647  *                        current configuration.
 648  * Return values:
 649  *      USB_SUCCESS      - Tree build succeeded
 650  *      USB_INVALID_ARGS - dev_parse_level in usb_reg is invalid.
 651  *      USB_FAILURE      - Bad descriptor info or other internal failure
 652  */
 653 static int
 654 usba_build_descr_tree(dev_info_t *dip, usba_device_t *usba_device,
 655     usb_client_dev_data_t *usb_reg)


 782 
 783                                 break;
 784 
 785                         case USB_DESCR_TYPE_EP:
 786                                 /*
 787                                  * Skip if endpoints of a specific interface are
 788                                  * desired and this endpoint is associated with
 789                                  * a different interface.
 790                                  */
 791                                 if (process_this_if_tree) {
 792                                         if (usba_process_ep_descr(&state) !=
 793                                             USB_SUCCESS) {
 794 
 795                                                 return (USB_FAILURE);
 796                                         }
 797                                         state.st_last_processed_descr_type =
 798                                             USB_DESCR_TYPE_EP;
 799                                 }
 800 
 801                                 break;












 802                         case USB_DESCR_TYPE_STRING:
 803                                 USB_DPRINTF_L2(DPRINT_MASK_ALL,
 804                                     usbai_reg_log_handle,
 805                                     "usb_get_dev_data: "
 806                                     "Found unexpected str descr at addr 0x%p",
 807                                     (void *)state.st_curr_raw_descr);
 808 
 809                                 break;  /* Shouldn't be any here.  Skip. */
 810 
 811                         default:
 812                                 /*
 813                                  * Treat all other descr as class/vendor
 814                                  * specific.  Skip if c/vs of a specific
 815                                  * interface are desired and this c/v is
 816                                  * associated with a different one.
 817                                  * Device level c/vs should always be
 818                                  * processed, e.g., the security descrs
 819                                  * for the Host Wire Adapter.
 820                                  */
 821                                 if ((state.st_last_processed_descr_type ==


1030                 return (USB_FAILURE);
1031         }
1032 
1033         usba_augment_array((void **)(&curr_alt->altif_ep),
1034             curr_alt->altif_n_ep, sizeof (usb_ep_data_t));
1035 
1036         /* Ptr to the current endpt, may be used to attach a c/v to it. */
1037         state->st_curr_ep = &curr_alt->altif_ep[curr_alt->altif_n_ep++];
1038 
1039         (void) usb_parse_data("4csc", state->st_curr_raw_descr,
1040             state->st_curr_raw_descr_len,
1041             &state->st_curr_ep->ep_descr, sizeof (usb_ep_descr_t));
1042 
1043         USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1044             "usba_process_ep_descr done");
1045 
1046         return (USB_SUCCESS);
1047 }
1048 
1049 
























1050 /*
1051  * usba_process_cv_descr:
1052  *      This processes a raw endpoint descriptor, and sets up an analogous
1053  *      endpoint descriptor in the descriptor tree.  C/Vs are associated with
1054  *      other descriptors they follow in the raw data.
1055  *      last_processed_descr_type indicates the type of descr this c/v follows.
1056  *
1057  * Arguments:
1058  *      state           - Pointer to this module's state structure.
1059  *
1060  * Returns:
1061  *      USB_SUCCESS:    Descriptor is successfully parsed.
1062  *      USB_FAILURE:    Descriptor is inappropriately placed in config cloud.
1063  */
1064 static int
1065 usba_process_cv_descr(usba_reg_state_t *state)
1066 {
1067         usb_cvs_data_t  *curr_cv_descr;
1068         usb_cvs_data_t  **cvs_ptr = NULL;
1069         uint_t          *n_cvs_ptr;


1126  * Arguments:
1127  *      dip             - pointer to devinfo of the device
1128  *      usba_device     - pointer to usba_device structure of the device
1129  *      state           - Pointer to this module's state structure.
1130  *                        if no specific config specified, default to all config
1131  *                        if no specific interface specified, default to all.
1132  *                        if_to_build and config_to_build are modified.
1133  *                        dev_parse_level may be modified.
1134  *
1135  * Returns:
1136  *      USB_SUCCESS     - success
1137  *      USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
1138  */
1139 static int
1140 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
1141     usba_reg_state_t *state)
1142 {
1143         /* Default to *all* in case configuration# prop not set. */
1144         mutex_enter(&usba_device->usb_mutex);
1145         state->st_cfg_to_build = usba_device->usb_active_cfg_ndx;

1146         mutex_exit(&usba_device->usb_mutex);
1147         if (state->st_cfg_to_build == USBA_DEV_CONFIG_INDEX_UNDEFINED) {
1148                 state->st_cfg_to_build = USBA_ALL;
1149         }
1150         state->st_if_to_build = usb_get_if_number(dip);
1151 
1152         switch (state->st_dev_parse_level) {
1153         case USB_PARSE_LVL_ALL:         /* Parse all configurations */
1154                 state->st_cfg_to_build = USBA_ALL;
1155                 state->st_if_to_build = USBA_ALL;
1156                 break;
1157 
1158         case USB_PARSE_LVL_CFG:         /* Parse all interfaces of a */
1159                                         /* specific configuration. */
1160                 state->st_if_to_build = USBA_ALL;
1161                 break;
1162 
1163         case USB_PARSE_LVL_IF:          /* Parse configured interface only */
1164                 if (state->st_if_to_build < 0) {
1165                         state->st_if_to_build = USBA_ALL;