1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2014 Garrett D'Amore <garrett@damore.org> 26 * Copyright 2019, Joyent, Inc. 27 */ 28 29 /* 30 * USBA: Solaris USB Architecture support 31 * 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 35 * dump it. 36 * 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. 41 * 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. 47 * 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. 51 * 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. 58 * 59 * Endpoint tree nodes contain a standard endpoint descriptor, plus a pointer to 60 * an array of c/v tree nodes. 61 * 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. 66 * 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. 71 * 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 76 * 77 * How the tree is built: 78 * 79 * usb_build_descr_tree() is responsible for the whole process. 80 * 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. 87 * 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 90 * alternate ID. 91 * 92 * The usba_reg_state_t structure maintains state of the tree-building process, 93 * helping coordinate all routines involved. 94 */ 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> 101 102 #include <sys/usb/usba/usbai_register_impl.h> 103 104 /* 105 * Header needed for use by this module only. 106 * However, function may be used in V0.8 drivers so needs to be global. 107 */ 108 int usb_log_descr_tree(usb_client_dev_data_t *, usb_log_handle_t, 109 uint_t, uint_t); 110 111 /* Debug stuff */ 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; 116 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 *); 130 131 static void usba_order_tree(usba_reg_state_t *); 132 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); 136 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, 142 uint_t, char *); 143 static void usba_dump_cv(usb_cvs_data_t *, usb_log_handle_t, uint_t, uint_t, 144 char *, int); 145 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t, 146 uint_t, uint_t, char *, int); 147 148 /* Framework initialization. */ 149 void 150 usba_usbai_register_initialization() 151 { 152 usbai_reg_log_handle = usb_alloc_log_hdl(NULL, "usbreg", 153 &usbai_register_errlevel, 154 &usbai_register_errmask, NULL, 155 0); 156 157 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 158 "usba_usbai_register_initialization"); 159 } 160 161 162 /* Framework destruction. */ 163 void 164 usba_usbai_register_destroy() 165 { 166 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 167 "usba_usbai_register destroy"); 168 169 usb_free_log_hdl(usbai_reg_log_handle); 170 } 171 172 173 /* 174 * usb_client_attach: 175 * 176 * Arguments: 177 * dip - pointer to devinfo node of the client 178 * version - USBA registration version number 179 * flags - None used 180 * 181 * Return Values: 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 186 */ 187 /*ARGSUSED*/ 188 int 189 usb_client_attach(dev_info_t *dip, uint_t version, usb_flags_t flags) 190 { 191 int rval; 192 usba_device_t *usba_device; 193 194 if (dip == NULL) { 195 196 return (USB_INVALID_ARGS); 197 } 198 199 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 200 "usb_client attach:"); 201 202 usba_device = usba_get_usba_device(dip); 203 204 /* 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. 207 */ 208 if ((version != 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, " 214 "expecting %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); 218 219 return (USB_INVALID_VERSION); 220 } 221 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)); 227 } 228 229 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-major", 230 USBA_GET_MAJOR(version)); 231 if (rval != DDI_PROP_SUCCESS) { 232 233 return (USB_FAILURE); 234 } 235 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-minor", 236 USBA_GET_MINOR(version)); 237 if (rval != DDI_PROP_SUCCESS) { 238 239 return (USB_FAILURE); 240 } 241 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; 247 } 248 mutex_exit(&usba_device->usb_mutex); 249 250 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 251 "usb_client attach: done"); 252 253 return (USB_SUCCESS); 254 } 255 256 257 /* 258 * usb_client_detach: 259 * free dev_data is reg != NULL, not much else to do 260 * 261 * Arguments: 262 * dip - pointer to devinfo node of the client 263 * reg - return registration data at this address 264 */ 265 void 266 usb_client_detach(dev_info_t *dip, usb_client_dev_data_t *reg) 267 { 268 usba_device_t *usba_device = usba_get_usba_device(dip); 269 270 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 271 "usb_client_detach:"); 272 273 if (dip) { 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); 277 278 usb_free_dev_data(dip, reg); 279 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; 284 } 285 mutex_exit(&usba_device->usb_mutex); 286 } 287 288 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 289 "usb_client_detach done"); 290 } 291 292 293 /* 294 * usb_register_client (deprecated): 295 * The client registers with USBA during attach. 296 */ 297 /*ARGSUSED*/ 298 int 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, 301 usb_flags_t flags) 302 { 303 int rval = usb_client_attach(dip, version, flags); 304 305 if (rval == USB_SUCCESS) { 306 rval = usb_get_dev_data(dip, reg, parse_level, flags); 307 308 if (rval != USB_SUCCESS) { 309 usb_client_detach(dip, NULL); 310 } 311 } 312 313 return (rval); 314 } 315 316 317 /* 318 * usb_unregister_client (deprecated): 319 * Undo the makings of usb_get_dev_data(). Free memory if allocated. 320 * 321 * Arguments: 322 * dip - pointer to devinfo node of the client 323 * reg - pointer to registration data to be freed 324 */ 325 void 326 usb_unregister_client(dev_info_t *dip, usb_client_dev_data_t *reg) 327 { 328 usb_client_detach(dip, reg); 329 } 330 331 332 /* 333 * usb_get_dev_data: 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. 342 * 343 * This routine sets up directly-initialized fields, and calls 344 * usb_build_descr_tree() to parse the raw descriptors and initialize the 345 * tree. 346 * 347 * Parse_level determines the extent to which the tree is built. It has 348 * the following values: 349 * 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. 364 * 365 * No tree is built for root hubs, regardless of parse_level. 366 * 367 * Arguments: 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 372 * flags - None used 373 * 374 * Return Values: 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 379 * 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. 384 * 385 * The registration data is not shared. each client receives its own 386 * copy. 387 */ 388 /*ARGSUSED*/ 389 int 390 usb_get_dev_data(dev_info_t *dip, 391 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level, 392 usb_flags_t flags) 393 { 394 usb_client_dev_data_t *usb_reg = NULL; 395 char *tmpbuf = NULL; 396 usba_device_t *usba_device; 397 int rval = USB_SUCCESS; 398 399 if ((dip == NULL) || (reg == NULL)) { 400 401 return (USB_INVALID_ARGS); 402 } 403 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)); 407 408 *reg = NULL; 409 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) { 413 414 return (USB_INVALID_VERSION); 415 } 416 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 417 "driver-minor", -1) == -1) { 418 419 return (USB_INVALID_VERSION); 420 } 421 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)); 428 429 return (USB_FAILURE); 430 } 431 432 usb_reg->dev_iblock_cookie = usba_hcdi_get_hcdi( 433 usba_device->usb_root_hub_dip)->hcdi_soft_iblock_cookie; 434 435 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 436 "cookie = 0x%p", (void *)usb_reg->dev_iblock_cookie); 437 438 tmpbuf = (char *)kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 439 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); 444 } 445 446 if (usba_device->usb_product_str != NULL) { 447 usb_reg->dev_product = kmem_zalloc( 448 strlen(usba_device->usb_product_str) + 1, 449 KM_SLEEP); 450 (void) strcpy(usb_reg->dev_product, 451 usba_device->usb_product_str); 452 } 453 454 if (usba_device->usb_serialno_str != NULL) { 455 usb_reg->dev_serial = kmem_zalloc( 456 strlen(usba_device->usb_serialno_str) + 1, 457 KM_SLEEP); 458 (void) strcpy(usb_reg->dev_serial, 459 usba_device->usb_serialno_str); 460 } 461 462 if ((usb_reg->dev_parse_level = parse_level) == USB_PARSE_LVL_NONE) { 463 rval = USB_SUCCESS; 464 465 } else if ((rval = usba_build_descr_tree(dip, usba_device, usb_reg)) != 466 USB_SUCCESS) { 467 usb_unregister_client(dip, usb_reg); 468 usb_reg = NULL; 469 } else { 470 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]; 474 } else { 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 == 481 USB_CFG_DESCR_SIZE); 482 } 483 484 /* 485 * Keep dev_curr_if at device's single interface only if that 486 * particular interface has been explicitly defined by the 487 * device. 488 */ 489 usb_reg->dev_curr_if = usba_get_ifno(dip); 490 #ifdef DEBUG 491 (void) usb_log_descr_tree(usb_reg, usbai_reg_log_handle, 492 usbai_register_dump_errlevel, (uint_t)-1); 493 #endif 494 /* 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. 498 */ 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]. 502 if_n_alt == 0)) { 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); 507 usb_reg = NULL; 508 rval = USB_FAILURE; 509 } 510 } 511 512 *reg = usb_reg; 513 kmem_free(tmpbuf, USB_MAXSTRINGLEN); 514 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); 519 520 usba_device->usb_client_flags[usba_get_ifno(dip)] |= 521 USBA_CLIENT_FLAG_DEV_DATA; 522 523 entry->cddl_dip = dip; 524 entry->cddl_dev_data = usb_reg; 525 entry->cddl_ifno = usba_get_ifno(dip); 526 527 entry->cddl_next = 528 usba_device->usb_client_dev_data_list.cddl_next; 529 if (entry->cddl_next) { 530 entry->cddl_next->cddl_prev = entry; 531 } 532 entry->cddl_prev = &usba_device->usb_client_dev_data_list; 533 usba_device->usb_client_dev_data_list.cddl_next = entry; 534 535 mutex_exit(&usba_device->usb_mutex); 536 } 537 538 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 539 "usb_get_dev_data rval=%d", rval); 540 541 return (rval); 542 } 543 544 545 /* 546 * usb_free_dev_data 547 * undoes what usb_get_dev_data does 548 * 549 * Arguments: 550 * dip - pointer to devinfo node of the client 551 * reg - return registration data at this address 552 */ 553 void 554 usb_free_dev_data(dev_info_t *dip, usb_client_dev_data_t *reg) 555 { 556 if (dip == NULL) { 557 558 return; 559 } 560 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); 564 565 if (reg != NULL) { 566 usba_device_t *usba_device = usba_get_usba_device(dip); 567 usb_client_dev_data_list_t *next, *prev, *entry; 568 int matches = 0; 569 570 if (reg->dev_serial != NULL) { 571 kmem_free((char *)reg->dev_serial, 572 strlen((char *)reg->dev_serial) + 1); 573 } 574 575 if (reg->dev_product != NULL) { 576 kmem_free((char *)reg->dev_product, 577 strlen((char *)reg->dev_product) + 1); 578 } 579 580 if (reg->dev_mfg != NULL) { 581 kmem_free((char *)reg->dev_mfg, 582 strlen((char *)reg->dev_mfg) + 1); 583 } 584 585 /* Free config tree under reg->dev_cfg. */ 586 if (reg->dev_cfg != NULL) { 587 usb_free_descr_tree(dip, reg); 588 } 589 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; 593 594 /* free the entries in usb_client_data_list */ 595 while (entry) { 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; 602 } 603 kmem_free(entry, sizeof (*entry)); 604 } else { 605 /* 606 * any other entries for this interface? 607 */ 608 if (usba_get_ifno(dip) == entry->cddl_ifno) { 609 matches++; 610 } 611 prev = entry; 612 } 613 entry = next; 614 } 615 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, 620 usba_get_ifno(dip), 621 usba_device->usb_client_flags[usba_get_ifno(dip)]); 622 623 if (matches == 0) { 624 usba_device-> 625 usb_client_flags[usba_get_ifno(dip)] &= 626 ~USBA_CLIENT_FLAG_DEV_DATA; 627 } 628 mutex_exit(&usba_device->usb_mutex); 629 630 kmem_free(reg, sizeof (usb_client_dev_data_t)); 631 } 632 633 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 634 "usb_free_dev_data done"); 635 } 636 637 /* 638 * usba_build_descr_tree: 639 * This builds the descriptor tree. See module header comment for tree 640 * description. 641 * 642 * Arguments: 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. 650 * Return values: 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 654 */ 655 static int 656 usba_build_descr_tree(dev_info_t *dip, usba_device_t *usba_device, 657 usb_client_dev_data_t *usb_reg) 658 { 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. */ 667 668 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 669 "usba_build_descr_tree starting"); 670 671 bzero(&state, sizeof (usba_reg_state_t)); 672 state.dip = dip; 673 674 /* 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. 678 */ 679 state.st_dev_parse_level = usb_reg->dev_parse_level; 680 if (usba_set_parse_values(dip, usba_device, &state) != USB_SUCCESS) { 681 682 return (USB_INVALID_ARGS); 683 } 684 usb_reg->dev_parse_level = state.st_dev_parse_level; 685 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; 689 low_cfg_bound = 0; 690 high_cfg_bound = usba_device->usb_n_cfgs; 691 } else { 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); 697 } 698 usb_reg->dev_cfg = state.st_dev_cfg = kmem_zalloc( 699 (usb_reg->dev_n_cfg * sizeof (usb_cfg_data_t)), 700 KM_SLEEP); 701 /* 702 * this_cfg_ndx loops through all configurations presented; 703 * state.st_dev_n_cfg limits the cfgs checked to the number desired. 704 */ 705 state.st_dev_n_cfg = 0; 706 for (this_cfg_ndx = low_cfg_bound; this_cfg_ndx < high_cfg_bound; 707 this_cfg_ndx++) { 708 709 state.st_curr_raw_descr = 710 usba_device->usb_cfg_array[this_cfg_ndx]; 711 ASSERT(state.st_curr_raw_descr != NULL); 712 713 /* Clear the following for config cloud sanity checking. */ 714 last_byte = NULL; 715 state.st_curr_cfg = NULL; 716 state.st_curr_if = NULL; 717 state.st_curr_alt = NULL; 718 state.st_curr_ep = NULL; 719 720 do { 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]; 726 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)) { 731 732 return (USB_FAILURE); 733 } 734 735 /* 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. 738 */ 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); 745 746 return (USB_FAILURE); 747 } 748 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); 754 755 switch (state.st_curr_raw_descr_type) { 756 case USB_DESCR_TYPE_CFG: 757 cfg_len_so_far = 0; 758 process_this_if_tree = B_FALSE; 759 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 = 764 USB_DESCR_TYPE_CFG; 765 last_byte = state.st_curr_raw_descr + 766 (state.st_total_cfg_length * 767 sizeof (uchar_t)); 768 769 break; 770 771 case USB_DESCR_TYPE_IF: 772 /* 773 * process_this_if_tree == TRUE means this 774 * interface, plus all eps and c/vs in it are 775 * to be processed. 776 */ 777 if (usba_process_if_descr(&state, 778 &process_this_if_tree) != USB_SUCCESS) { 779 780 return (USB_FAILURE); 781 } 782 state.st_last_processed_descr_type = 783 USB_DESCR_TYPE_IF; 784 785 break; 786 787 case USB_DESCR_TYPE_EP: 788 /* 789 * Skip if endpoints of a specific interface are 790 * desired and this endpoint is associated with 791 * a different interface. 792 */ 793 if (process_this_if_tree) { 794 if (usba_process_ep_descr(&state) != 795 USB_SUCCESS) { 796 797 return (USB_FAILURE); 798 } 799 state.st_last_processed_descr_type = 800 USB_DESCR_TYPE_EP; 801 } 802 803 break; 804 805 case USB_DESCR_TYPE_SS_EP_COMP: 806 807 /* 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. 813 */ 814 if (state.st_last_processed_descr_type == 815 USB_DESCR_TYPE_EP) { 816 if (usba_process_ss_ep_comp_descr( 817 &state) != USB_SUCCESS) { 818 819 return (USB_FAILURE); 820 } 821 822 state.st_last_processed_descr_type = 823 USB_DESCR_TYPE_SS_EP_COMP; 824 825 break; 826 } 827 break; 828 829 case USB_DESCR_TYPE_STRING: 830 USB_DPRINTF_L2(DPRINT_MASK_ALL, 831 usbai_reg_log_handle, 832 "usb_get_dev_data: " 833 "Found unexpected str descr at addr 0x%p", 834 (void *)state.st_curr_raw_descr); 835 836 break; /* Shouldn't be any here. Skip. */ 837 838 default: 839 /* 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. 847 */ 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) != 852 USB_SUCCESS) { 853 854 return (USB_FAILURE); 855 } 856 } 857 } 858 859 state.st_curr_raw_descr += state.st_curr_raw_descr_len; 860 cfg_len_so_far += state.st_curr_raw_descr_len; 861 862 } while (state.st_curr_raw_descr < last_byte); 863 } 864 865 /* Make tree sparse, and put elements in order. */ 866 usba_order_tree(&state); 867 868 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 869 "usba_build_descr_tree done"); 870 871 return (USB_SUCCESS); 872 } 873 874 875 /* 876 * usba_process_cfg_descr: 877 * Set up a configuration tree node based on a raw config descriptor. 878 * 879 * Arguments: 880 * state - Pointer to this module's state structure. 881 * 882 * Returns: 883 * B_TRUE: the descr processed corresponds to a requested configuration. 884 * B_FALSE: the descr processed does not correspond to a requested config. 885 */ 886 static void 887 usba_process_cfg_descr(usba_reg_state_t *state) 888 { 889 usb_cfg_data_t *curr_cfg; 890 891 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 892 "usba_process_cfg_descr starting"); 893 894 curr_cfg = state->st_curr_cfg = 895 &state->st_dev_cfg[state->st_dev_n_cfg++]; 896 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)); 902 903 state->st_total_cfg_length = curr_cfg->cfg_descr.wTotalLength; 904 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, 908 KM_SLEEP); 909 (void) strcpy(curr_cfg->cfg_str, state->st_curr_cfg_str); 910 } 911 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); 915 916 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 917 "usba_process_cfg_descr done"); 918 } 919 920 921 /* 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. 926 * 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. 930 * 931 * Arguments: 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. 936 * 937 * Returns: 938 * USB_SUCCESS: Descriptor is successfully parsed. 939 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 940 */ 941 static int 942 usba_process_if_descr(usba_reg_state_t *state, boolean_t *requested_if) 943 { 944 char *string; 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); 948 949 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 950 "usba_process_if_descr starting"); 951 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."); 956 957 return (USB_FAILURE); 958 } 959 960 new_if_descr = kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP); 961 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)); 966 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)); 973 974 *requested_if = B_FALSE; 975 976 return (USB_SUCCESS); 977 } 978 *requested_if = B_TRUE; 979 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; 984 985 } else { 986 usb_alt_if_data_t *alt_array; 987 uint_t alt_index; 988 989 /* Point to proper interface node, based on num in descr. */ 990 state->st_curr_if = 991 &state->st_curr_cfg->cfg_if[new_if_descr->bInterfaceNumber]; 992 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)); 998 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]; 1001 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; 1006 1007 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 1008 if (!is_root_hub) { 1009 (void) usb_get_string_descr(state->dip, USB_LANG_ID, 1010 state->st_curr_alt->altif_descr.iInterface, 1011 string, USB_MAXSTRINGLEN); 1012 } 1013 if (string[0] == '\0') { 1014 (void) strcpy(string, "<none>"); 1015 } 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); 1021 } 1022 1023 kmem_free(new_if_descr, sizeof (usb_if_descr_t)); 1024 1025 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1026 "usba_process_if_descr done"); 1027 1028 return (USB_SUCCESS); 1029 } 1030 1031 1032 /* 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. 1036 * 1037 * Arguments: 1038 * state - Pointer to this module's state structure. 1039 * 1040 * Returns: 1041 * USB_SUCCESS: Descriptor is successfully parsed. 1042 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 1043 */ 1044 static int 1045 usba_process_ep_descr(usba_reg_state_t *state) 1046 { 1047 usb_alt_if_data_t *curr_alt = state->st_curr_alt; 1048 1049 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1050 "usba_process_ep_descr starting"); 1051 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."); 1056 1057 return (USB_FAILURE); 1058 } 1059 1060 usba_augment_array((void **)(&curr_alt->altif_ep), 1061 curr_alt->altif_n_ep, sizeof (usb_ep_data_t)); 1062 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++]; 1065 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)); 1069 1070 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1071 "usba_process_ep_descr done"); 1072 1073 return (USB_SUCCESS); 1074 } 1075 1076 /* 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. 1080 * 1081 * Arguments: 1082 * state - Pointer to this module's state structure. 1083 * 1084 * Returns: 1085 * USB_SUCCESS: Descriptor is successfully parsed. 1086 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 1087 */ 1088 static int 1089 usba_process_ss_ep_comp_descr(usba_reg_state_t *state) 1090 { 1091 if (state->st_curr_ep == NULL) 1092 return (USB_FAILURE); 1093 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; 1099 1100 return (USB_SUCCESS); 1101 } 1102 1103 1104 /* 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. 1110 * 1111 * Arguments: 1112 * state - Pointer to this module's state structure. 1113 * 1114 * Returns: 1115 * USB_SUCCESS: Descriptor is successfully parsed. 1116 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 1117 */ 1118 static int 1119 usba_process_cv_descr(usba_reg_state_t *state) 1120 { 1121 usb_cvs_data_t *curr_cv_descr; 1122 usb_cvs_data_t **cvs_ptr = NULL; 1123 uint_t *n_cvs_ptr; 1124 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); 1128 1129 /* 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. 1132 */ 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; 1137 break; 1138 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; 1142 break; 1143 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; 1148 break; 1149 1150 default: 1151 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle, 1152 "usba_process_cv_descr: Type of last descriptor unknown. "); 1153 1154 return (USB_FAILURE); 1155 } 1156 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)++]; 1160 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); 1166 1167 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1168 "usba_process_cv_descr done"); 1169 1170 return (USB_SUCCESS); 1171 } 1172 1173 1174 /* 1175 * usba_set_parse_values: 1176 * Based on parse level, set the configuration(s) and interface(s) to build 1177 * 1178 * Returned configuration value can be USBA_ALL indicating to build all 1179 * configurations. Likewise for the returned interface value. 1180 * 1181 * Arguments: 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. 1189 * 1190 * Returns: 1191 * USB_SUCCESS - success 1192 * USB_INVALID_ARGS - state->st_dev_parse_level is invalid. 1193 */ 1194 static int 1195 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device, 1196 usba_reg_state_t *state) 1197 { 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; 1204 } 1205 state->st_if_to_build = usb_get_if_number(dip); 1206 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; 1211 break; 1212 1213 case USB_PARSE_LVL_CFG: /* Parse all interfaces of a */ 1214 /* specific configuration. */ 1215 state->st_if_to_build = USBA_ALL; 1216 break; 1217 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; 1221 } 1222 break; 1223 1224 default: 1225 1226 return (USB_INVALID_ARGS); 1227 } 1228 1229 /* 1230 * Set parse level to identify this tree properly, regardless of what 1231 * the caller thought the tree would have. 1232 */ 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; 1236 } 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; 1240 } 1241 1242 return (USB_SUCCESS); 1243 } 1244 1245 1246 /* 1247 * usba_kmem_realloc: 1248 * Resize dynamic memory. Copy contents of old area to 1249 * beginning of new area. 1250 * 1251 * Arguments: 1252 * old_mem - pointer to old memory area. 1253 * old_size - size of old memory area. 0 is OK. 1254 * new_size - size desired. 1255 * 1256 * Returns: 1257 * pointer to new memory area. 1258 */ 1259 static void* 1260 usba_kmem_realloc(void* old_mem, int old_size, int new_size) 1261 { 1262 void *new_mem = NULL; 1263 1264 if (new_size > 0) { 1265 new_mem = kmem_zalloc(new_size, KM_SLEEP); 1266 if (old_size > 0) { 1267 bcopy(old_mem, new_mem, 1268 min(old_size, new_size)); 1269 } 1270 } 1271 1272 if (old_size > 0) { 1273 kmem_free(old_mem, old_size); 1274 } 1275 1276 return (new_mem); 1277 } 1278 1279 1280 /* 1281 * usba_augment_array: 1282 * Add a new element on the end of an array. 1283 * 1284 * Arguments: 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 1288 */ 1289 static void 1290 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size) 1291 { 1292 *addr = usba_kmem_realloc(*addr, (n_elements * element_size), 1293 ((n_elements + 1) * element_size)); 1294 } 1295 1296 1297 /* 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. 1303 * 1304 * Arguments: 1305 * array - pointer to alternates array; may be modified 1306 * n_elements - number of elements in the array; may be modified 1307 */ 1308 static void 1309 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements) 1310 { 1311 uint_t n_orig_elements = *n_elements; 1312 uint8_t smallest_value; 1313 uint8_t largest_value; 1314 uint8_t curr_value; 1315 uint_t in_order = 0; 1316 usb_alt_if_data_t *orig_addr; /* 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 */ 1319 uint_t i; 1320 1321 /* Check for a null array. */ 1322 if ((array == NULL) || (n_orig_elements == 0)) { 1323 1324 return; 1325 } 1326 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); 1330 1331 orig_addr = *array; 1332 curr_value = orig_addr[0].altif_descr.bAlternateSetting; 1333 smallest_value = largest_value = curr_value; 1334 1335 /* Figure the low-high range of the array. */ 1336 for (i = 1; i < n_orig_elements; i++) { 1337 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1338 if (curr_value < smallest_value) { 1339 smallest_value = curr_value; 1340 } else if (curr_value > largest_value) { 1341 in_order++; 1342 largest_value = curr_value; 1343 } 1344 } 1345 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1346 "make_sparse: largest=%d, smallest=%d, " 1347 "order=%d", 1348 largest_value, smallest_value, in_order); 1349 1350 n_repl_elements = largest_value + 1; 1351 1352 /* 1353 * No holes to leave, array starts at zero, and everything is already 1354 * in order. Just return original array. 1355 */ 1356 if ((n_repl_elements == n_orig_elements) && 1357 ((in_order + 1) == n_orig_elements)) { 1358 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1359 "No holes"); 1360 1361 return; 1362 } 1363 1364 /* Allocate zeroed space for the array. */ 1365 repl_array = kmem_zalloc( 1366 (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP); 1367 1368 /* Now fill in the array. */ 1369 for (i = 0; i < n_orig_elements; i++) { 1370 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1371 1372 /* Place in sparse array based on key. */ 1373 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1374 "move %lu bytes (key %d) from 0x%p to 0x%p", 1375 (unsigned long)sizeof (usb_alt_if_data_t), curr_value, 1376 (void *)&orig_addr[i], (void *)&repl_array[curr_value]); 1377 1378 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value], 1379 sizeof (usb_alt_if_data_t)); 1380 } 1381 1382 kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements); 1383 *array = repl_array; 1384 *n_elements = n_repl_elements; 1385 } 1386 1387 1388 /* 1389 * usba_order_tree: 1390 * Take a tree as built by usba_build_descr_tree and make sure the key 1391 * values of all elements match their indeces. Proper order is implied. 1392 * 1393 * Arguments: 1394 * state - Pointer to this module's state structure. 1395 */ 1396 static void 1397 usba_order_tree(usba_reg_state_t *state) 1398 { 1399 usb_cfg_data_t *this_cfg; 1400 usb_if_data_t *this_if; 1401 uint_t n_cfgs = state->st_dev_n_cfg; 1402 uint_t cfg; 1403 uint_t which_if; 1404 1405 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1406 "usba_order_tree:"); 1407 1408 for (cfg = 0; cfg < n_cfgs; cfg++) { 1409 this_cfg = &state->st_dev_cfg[cfg]; 1410 1411 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) { 1412 this_if = this_cfg->cfg_if; 1413 usba_make_alts_sparse(&this_if->if_alt, 1414 &this_if->if_n_alt); 1415 } 1416 } 1417 } 1418 1419 1420 /* 1421 * usb_free_descr_tree: 1422 * Take down the configuration tree. Called internally and can be called 1423 * from a driver standalone to take the tree down while leaving the rest 1424 * of the registration intact. 1425 * 1426 * Arguments: 1427 * dip - pointer to devinfo of the device 1428 * dev_data - pointer to registration data containing the tree. 1429 */ 1430 void 1431 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1432 { 1433 usb_cfg_data_t *cfg_array; 1434 int n_cfgs; 1435 int cfg; 1436 1437 if ((dip == NULL) || (dev_data == NULL)) { 1438 1439 return; 1440 } 1441 cfg_array = dev_data->dev_cfg; 1442 n_cfgs = dev_data->dev_n_cfg; 1443 1444 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1445 "usb_free_descr_tree starting for %s%d", 1446 ddi_driver_name(dip), ddi_get_instance(dip)); 1447 1448 for (cfg = 0; cfg < n_cfgs; cfg++) { 1449 if (cfg_array[cfg].cfg_if) { 1450 usba_free_if_array(cfg_array[cfg].cfg_if, 1451 cfg_array[cfg].cfg_n_if); 1452 } 1453 if (cfg_array[cfg].cfg_cvs) { 1454 usba_free_cv_array(cfg_array[cfg].cfg_cvs, 1455 cfg_array[cfg].cfg_n_cvs); 1456 } 1457 if (cfg_array[cfg].cfg_str) { 1458 kmem_free(cfg_array[cfg].cfg_str, 1459 cfg_array[cfg].cfg_strsize); 1460 } 1461 } 1462 1463 if (cfg_array) { 1464 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs)); 1465 } 1466 1467 dev_data->dev_parse_level = USB_PARSE_LVL_NONE; 1468 dev_data->dev_n_cfg = 0; 1469 dev_data->dev_cfg = NULL; 1470 dev_data->dev_curr_cfg = NULL; 1471 1472 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1473 "usb_free_descr_tree done"); 1474 } 1475 1476 1477 /* 1478 * usba_free_if_array: 1479 * Free a configuration's array of interface nodes and their subtrees of 1480 * interface alternate, endpoint and c/v descriptors. 1481 * 1482 * Arguments: 1483 * if_array - pointer to array of interfaces to remove. 1484 * n_ifs - number of elements in the array to remove. 1485 */ 1486 static void 1487 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs) 1488 { 1489 uint_t which_if; 1490 uint_t which_alt; 1491 uint_t n_alts; 1492 usb_alt_if_data_t *altif; 1493 1494 for (which_if = 0; which_if < n_ifs; which_if++) { 1495 n_alts = if_array[which_if].if_n_alt; 1496 1497 /* Every interface has at least one alternate. */ 1498 for (which_alt = 0; which_alt < n_alts; which_alt++) { 1499 altif = &if_array[which_if].if_alt[which_alt]; 1500 usba_free_ep_array(altif->altif_ep, altif->altif_n_ep); 1501 usba_free_cv_array(altif->altif_cvs, 1502 altif->altif_n_cvs); 1503 kmem_free(altif->altif_str, altif->altif_strsize); 1504 } 1505 1506 kmem_free(if_array[which_if].if_alt, 1507 (sizeof (usb_alt_if_data_t) * n_alts)); 1508 } 1509 1510 /* Free the interface array itself. */ 1511 kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs)); 1512 } 1513 1514 1515 /* 1516 * usba_free_ep_array: 1517 * Free an array of endpoint nodes and their subtrees of c/v descriptors. 1518 * 1519 * Arguments: 1520 * ep_array - pointer to array of endpoints to remove. 1521 * n_eps - number of elements in the array to remove. 1522 */ 1523 static void 1524 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps) 1525 { 1526 uint_t ep; 1527 1528 for (ep = 0; ep < n_eps; ep++) { 1529 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs); 1530 } 1531 1532 kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps)); 1533 } 1534 1535 1536 /* 1537 * usba_free_cv_array: 1538 * Free an array of class/vendor (c/v) descriptor nodes. 1539 * 1540 * Arguments: 1541 * cv_array - pointer to array of c/v nodes to remove. 1542 * n_cvs - number of elements in the array to remove. 1543 */ 1544 static void 1545 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs) 1546 { 1547 uint_t cv_node; 1548 1549 /* Free data areas hanging off of each c/v descriptor. */ 1550 for (cv_node = 0; cv_node < n_cvs; cv_node++) { 1551 kmem_free(cv_array[cv_node].cvs_buf, 1552 cv_array[cv_node].cvs_buf_len); 1553 } 1554 1555 /* Free the array of cv descriptors. */ 1556 kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs)); 1557 } 1558 1559 1560 /* 1561 * usb_log_descr_tree: 1562 * Log to the usba_debug_buf a descriptor tree as returned by 1563 * usbai_register_client. 1564 * 1565 * Arguments: 1566 * dev_data - pointer to registration area containing the tree 1567 * log_handle - pointer to log handle to use for dumping. 1568 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1569 * Please see usb_log(9F) for details. 1570 * mask - print mask. Please see usb_log(9F) for details. 1571 * 1572 * Returns: 1573 * USB_SUCCESS - tree successfully dumped 1574 * USB_INVALID_CONTEXT - called from callback context 1575 * USB_INVALID_ARGS - bad arguments given 1576 */ 1577 int 1578 usb_log_descr_tree(usb_client_dev_data_t *dev_data, 1579 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1580 { 1581 return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask)); 1582 } 1583 1584 1585 /* 1586 * usb_print_descr_tree: 1587 * Print to the screen a descriptor tree as returned by 1588 * usbai_register_client. 1589 * 1590 * Arguments: 1591 * dip - pointer to devinfo of the client 1592 * dev_data - pointer to registration area containing the tree 1593 * 1594 * Returns: 1595 * USB_SUCCESS - tree successfully dumped 1596 * USB_INVALID_CONTEXT - called from callback context 1597 * USB_INVALID_ARGS - bad arguments given 1598 */ 1599 int 1600 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1601 { 1602 return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0)); 1603 } 1604 1605 1606 /* 1607 * usba_dump_descr_tree: 1608 * Dump a descriptor tree. 1609 * 1610 * Arguments: 1611 * dip - pointer to devinfo of the client. Used when no 1612 * log_handle argument given. 1613 * usb_reg - pointer to registration area containing the tree 1614 * log_handle - pointer to log handle to use for dumping. If NULL, 1615 * use internal log handle, which dumps to screen. 1616 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1617 * Used only when log_handle provided. 1618 * mask - print mask, used when log_handle argument provided. 1619 * 1620 * Returns: 1621 * USB_SUCCESS - tree successfully dumped 1622 * USB_INVALID_CONTEXT - called from callback context 1623 * USB_INVALID_ARGS - bad arguments given 1624 */ 1625 static int 1626 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg, 1627 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1628 { 1629 usb_log_handle_t dump_handle; 1630 uint_t dump_level; 1631 uint_t dump_mask; 1632 int which_config; /* Counters. */ 1633 int which_if; 1634 int which_cv; 1635 usb_cfg_data_t *config; /* ptr to current configuration tree node */ 1636 usb_cfg_descr_t *config_descr; /* and its USB descriptor. */ 1637 char *string; 1638 char *name_string = NULL; 1639 int name_string_size = 0; 1640 1641 if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) { 1642 1643 return (USB_INVALID_ARGS); 1644 } 1645 1646 /* 1647 * To keep calling this simple, kmem_zalloc with the sleep flag always. 1648 * This means no interrupt context is allowed. 1649 */ 1650 if (servicing_interrupt()) { 1651 1652 return (USB_INVALID_CONTEXT); 1653 } 1654 1655 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 1656 1657 if (log_handle != NULL) { 1658 dump_level = level; 1659 dump_mask = mask; 1660 dump_handle = log_handle; 1661 } else { 1662 dump_level = USB_LOG_L1; 1663 dump_mask = DPRINT_MASK_ALL; 1664 1665 /* Build device name string. */ 1666 (void) snprintf(string, USB_MAXSTRINGLEN, 1667 "Port%d", usb_get_addr(dip)); 1668 name_string_size = strlen(string) + 1; 1669 name_string = kmem_zalloc(name_string_size, KM_SLEEP); 1670 (void) strcpy(name_string, string); 1671 1672 /* Allocate a log handle specifying the name string. */ 1673 dump_handle = usb_alloc_log_hdl(NULL, name_string, 1674 &dump_level, &dump_mask, NULL, 1675 USB_FLAGS_SLEEP); 1676 } 1677 1678 (void) usb_log(dump_handle, dump_level, dump_mask, 1679 "USB descriptor tree for %s %s", 1680 (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""), 1681 (usb_reg->dev_product != NULL ? usb_reg->dev_product : "")); 1682 if (usb_reg->dev_n_cfg == 0) { 1683 (void) usb_log(dump_handle, dump_level, dump_mask, 1684 "No descriptor tree present"); 1685 } else { 1686 (void) usb_log(dump_handle, dump_level, dump_mask, 1687 "highest configuration found=%d", usb_reg->dev_n_cfg - 1); 1688 } 1689 1690 for (which_config = 0; which_config < usb_reg->dev_n_cfg; 1691 which_config++) { 1692 config = &usb_reg->dev_cfg[which_config]; 1693 config_descr = &config->cfg_descr; 1694 if (config_descr->bLength == 0) { 1695 1696 continue; 1697 } 1698 if (dump_level == USB_LOG_L0) { 1699 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1700 } 1701 (void) usb_log(dump_handle, dump_level, dump_mask, 1702 "Configuration #%d (Addr= 0x%p)", which_config, 1703 (void *)config); 1704 (void) usb_log(dump_handle, dump_level, dump_mask, 1705 "String descr=%s", config->cfg_str); 1706 (void) usb_log(dump_handle, dump_level, dump_mask, 1707 "config descr: len=%d tp=%d totLen=%d numIf=%d " 1708 "cfgVal=%d att=0x%x pwr=%d", 1709 config_descr->bLength, config_descr->bDescriptorType, 1710 config_descr->wTotalLength, config_descr->bNumInterfaces, 1711 config_descr->bConfigurationValue, 1712 config_descr->bmAttributes, config_descr->bMaxPower); 1713 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) { 1714 (void) usb_log(dump_handle, dump_level, dump_mask, 1715 "usb_cfg_data_t shows max if=%d " 1716 "and %d cv descr(s).", 1717 config->cfg_n_if - 1, config->cfg_n_cvs); 1718 } 1719 1720 for (which_if = 0; which_if < config->cfg_n_if; 1721 which_if++) { 1722 1723 if (dump_level == USB_LOG_L0) { 1724 (void) usb_log(dump_handle, dump_level, 1725 dump_mask, " "); 1726 } 1727 (void) usb_log(dump_handle, dump_level, dump_mask, 1728 " interface #%d (0x%p)", 1729 which_if, (void *)&config->cfg_if[which_if]); 1730 usba_dump_if(&config->cfg_if[which_if], 1731 dump_handle, dump_level, dump_mask, string); 1732 } 1733 1734 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) { 1735 (void) usb_log(dump_handle, dump_level, dump_mask, 1736 " config cv descriptor %d (Address=0x%p)", 1737 which_cv, (void *)&config->cfg_cvs[which_cv]); 1738 usba_dump_cv(&config->cfg_cvs[which_cv], 1739 dump_handle, dump_level, dump_mask, string, 4); 1740 } 1741 } 1742 1743 (void) usb_log(dump_handle, dump_level, dump_mask, 1744 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d", 1745 (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if); 1746 1747 if (log_handle == NULL) { 1748 usb_free_log_hdl(dump_handle); 1749 } 1750 if (name_string != NULL) { 1751 kmem_free(name_string, name_string_size); 1752 } 1753 kmem_free(string, USB_MAXSTRINGLEN); 1754 1755 return (USB_SUCCESS); 1756 } 1757 1758 1759 /* 1760 * usba_dump_if: 1761 * Dump an interface node and its branches. 1762 * 1763 * Arguments: 1764 * which_if - interface node to dump 1765 * dump_handle - write data through this log handle 1766 * dump_level - level passed to usb_log 1767 * dump_mask - mask passed to usb_log 1768 * string - temporary area used for processing 1769 * 1770 */ 1771 static void 1772 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle, 1773 uint_t dump_level, uint_t dump_mask, char *string) 1774 { 1775 int which_alt; /* Number of alt being dumped */ 1776 usb_alt_if_data_t *alt; /* Pointer to it. */ 1777 usb_if_descr_t *if_descr; /* Pointer to its USB descr. */ 1778 int which_ep; /* Endpoint counter. */ 1779 int which_cv; /* C/V descr counter. */ 1780 1781 for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) { 1782 alt = &which_if->if_alt[which_alt]; 1783 if_descr = &alt->altif_descr; 1784 1785 if (if_descr->bLength == 0) { 1786 1787 continue; 1788 } 1789 if (dump_level == USB_LOG_L0) { 1790 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1791 } 1792 (void) usb_log(dump_handle, dump_level, dump_mask, 1793 "\tAlt #%d (0x%p)", which_alt, (void *)alt); 1794 (void) usb_log(dump_handle, dump_level, dump_mask, 1795 "\tString descr=%s", alt->altif_str); 1796 (void) usb_log(dump_handle, dump_level, dump_mask, 1797 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d " 1798 "cls=%d sub=%d proto=%d", 1799 if_descr->bLength, 1800 if_descr->bDescriptorType, if_descr->bInterfaceNumber, 1801 if_descr->bAlternateSetting, if_descr->bNumEndpoints, 1802 if_descr->bInterfaceClass, if_descr->bInterfaceSubClass, 1803 if_descr->bInterfaceProtocol); 1804 1805 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) { 1806 (void) usb_log(dump_handle, dump_level, dump_mask, 1807 "\tusb_alt_if_data_t shows max ep=%d " 1808 "and %d cv descr(s).", 1809 alt->altif_n_ep - 1, alt->altif_n_cvs); 1810 } 1811 1812 for (which_ep = 0; which_ep < alt->altif_n_ep; 1813 which_ep++) { 1814 if (alt->altif_ep[which_ep].ep_descr.bLength == 0) { 1815 1816 continue; 1817 } 1818 if (dump_level == USB_LOG_L0) { 1819 (void) usb_log(dump_handle, dump_level, 1820 dump_mask, " "); 1821 } 1822 usba_dump_ep(which_ep, &alt->altif_ep[which_ep], 1823 dump_handle, dump_level, dump_mask, string); 1824 } 1825 1826 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) { 1827 if (dump_level == USB_LOG_L0) { 1828 (void) usb_log(dump_handle, dump_level, 1829 dump_mask, " "); 1830 } 1831 (void) usb_log(dump_handle, dump_level, dump_mask, 1832 "\talt cv descriptor #%d (0x%p), size=%d", 1833 which_cv, (void *)&alt->altif_cvs[which_cv], 1834 alt->altif_cvs[which_cv].cvs_buf_len); 1835 usba_dump_cv(&alt->altif_cvs[which_cv], 1836 dump_handle, dump_level, dump_mask, string, 2); 1837 } 1838 } 1839 } 1840 1841 1842 /* 1843 * usba_dump_ep: 1844 * Dump an endpoint node and its branches. 1845 * 1846 * Arguments: 1847 * which_ep - index to display 1848 * ep - endpoint node to dump 1849 * dump_handle - write data through this log handle 1850 * dump_level - level passed to usb_log 1851 * dump_mask - mask passed to usb_log 1852 * string - temporary area used for processing 1853 * 1854 */ 1855 static void 1856 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle, 1857 uint_t dump_level, uint_t dump_mask, char *string) 1858 { 1859 int which_cv; 1860 usb_ep_descr_t *ep_descr = &ep->ep_descr; 1861 1862 (void) usb_log(dump_handle, dump_level, dump_mask, 1863 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep, 1864 ep_descr->bEndpointAddress, (void *)ep); 1865 (void) usb_log(dump_handle, dump_level, dump_mask, 1866 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d", 1867 ep_descr->bLength, ep_descr->bDescriptorType, 1868 ep_descr->bmAttributes, ep_descr->wMaxPacketSize, 1869 ep_descr->bInterval); 1870 if (ep->ep_n_cvs > 0) { 1871 (void) usb_log(dump_handle, dump_level, dump_mask, 1872 "\t usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs); 1873 } 1874 1875 for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) { 1876 if (dump_level == USB_LOG_L0) { 1877 (void) usb_log(dump_handle, dump_level, 1878 dump_mask, " "); 1879 } 1880 (void) usb_log(dump_handle, dump_level, dump_mask, 1881 "\t endpoint cv descriptor %d (0x%p), size=%d", 1882 which_cv, (void *)&ep->ep_cvs[which_cv], 1883 ep->ep_cvs[which_cv].cvs_buf_len); 1884 usba_dump_cv(&ep->ep_cvs[which_cv], 1885 dump_handle, dump_level, dump_mask, string, 3); 1886 } 1887 } 1888 1889 1890 /* 1891 * usba_dump_cv: 1892 * Dump a raw class or vendor specific descriptor. 1893 * 1894 * Arguments: 1895 * cv_node - pointer to the descriptor to dump 1896 * dump_handle - write data through this log handle 1897 * dump_level - level passed to usb_log 1898 * dump_mask - mask passed to usb_log 1899 * string - temporary area used for processing 1900 * indent - number of tabs to indent output 1901 * 1902 */ 1903 static void 1904 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle, 1905 uint_t dump_level, uint_t dump_mask, char *string, int indent) 1906 { 1907 if (cv_node) { 1908 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent, 1909 dump_handle, dump_level, dump_mask, string, 1910 USB_MAXSTRINGLEN); 1911 } 1912 } 1913 1914 1915 /* 1916 * usba_dump_bin: 1917 * Generic byte dump function. 1918 * 1919 * Arguments: 1920 * data - pointer to the data to dump 1921 * max_bytes - amount of data to dump 1922 * indent - number of indentation levels 1923 * dump_handle - write data through this log handle 1924 * dump_level - level passed to usb_log 1925 * dump_mask - mask passed to usb_log 1926 * buffer - temporary area used for processing 1927 * bufferlen - size of the temporary string area 1928 * 1929 */ 1930 static void 1931 usba_dump_bin(uint8_t *data, int max_bytes, int indent, 1932 usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask, 1933 char *buffer, int bufferlen) 1934 { 1935 int i; 1936 int bufoffset = 0; 1937 int nexthere; 1938 1939 if ((indent * SPACES_PER_INDENT) > 1940 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) { 1941 (void) usb_log(dump_handle, dump_level, dump_mask, 1942 "Offset to usb_dump_bin must be %d or less. " 1943 "Setting to 0.\n", 1944 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))); 1945 indent = 0; 1946 } 1947 1948 /* Assume a tab is 2 four-space units. */ 1949 for (i = 0; i < indent/2; i++) { 1950 buffer[bufoffset] = '\t'; 1951 bufoffset++; 1952 } 1953 1954 if (indent % 2) { 1955 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR); 1956 bufoffset += SPACES_PER_INDENT; 1957 } 1958 1959 i = 0; /* Num dumped bytes put on this line. */ 1960 nexthere = bufoffset; 1961 while (i < max_bytes) { 1962 (void) sprintf(&buffer[nexthere], "%2x ", *data++); 1963 nexthere += 3; 1964 i++; 1965 if (!(i % BINDUMP_BYTES_PER_LINE)) { 1966 buffer[nexthere] = '\0'; 1967 (void) usb_log(dump_handle, dump_level, dump_mask, 1968 buffer); 1969 nexthere = bufoffset; 1970 } 1971 } 1972 1973 if (nexthere > bufoffset) { 1974 buffer[nexthere] = '\0'; 1975 (void) usb_log(dump_handle, dump_level, dump_mask, buffer); 1976 } 1977 } 1978 1979 /* 1980 * usb_ep_xdescr_fill: 1981 * 1982 * Fills in the extended endpoint descriptor based on data from the 1983 * configuration tree. 1984 * 1985 * Arguments: 1986 * version - Should be USB_EP_XDESCR_CURRENT_VERSION 1987 * dip - devinfo pointer 1988 * ep_data - endpoint data pointer 1989 * ep_xdesc - An extended descriptor structure, filled upon 1990 * successful completion. 1991 * 1992 * Return values: 1993 * USB_SUCCESS - filling data succeeded 1994 * USB_INVALID_ARGS - invalid arguments 1995 */ 1996 int 1997 usb_ep_xdescr_fill(uint_t version, dev_info_t *dip, usb_ep_data_t *ep_data, 1998 usb_ep_xdescr_t *ep_xdescr) 1999 { 2000 if (version != USB_EP_XDESCR_VERSION_ONE) { 2001 2002 return (USB_INVALID_ARGS); 2003 } 2004 2005 if (dip == NULL || ep_data == NULL || ep_xdescr == NULL) { 2006 2007 return (USB_INVALID_ARGS); 2008 } 2009 2010 bzero(ep_xdescr, sizeof (usb_ep_xdescr_t)); 2011 ep_xdescr->uex_version = version; 2012 ep_xdescr->uex_ep = ep_data->ep_descr; 2013 if (ep_data->ep_ss_valid == B_TRUE) { 2014 ep_xdescr->uex_flags |= USB_EP_XFLAGS_SS_COMP; 2015 ep_xdescr->uex_ep_ss = ep_data->ep_ss_comp; 2016 } 2017 2018 return (USB_SUCCESS); 2019 } 2020