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