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 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. 44 * 45 * dev_cfg is an array of configuration tree nodes. Each contains space for one 46 * parsed standard USB configuration descriptor, a pointer to an array of c/v 47 * tree nodes and a pointer to an array of interface tree nodes. 48 * 49 * Each interface tree node represents a group of interface descriptors, called 50 * alternates, with the same interface number. Thus, each interface tree node 51 * has a pointer to an array of alternate-interface tree nodes each containing a 52 * standard USB interface descriptor. Alternate-interface tree nodes also 53 * contain a pointer to an array of c/v tree nodes and a pointer to an array of 54 * endpoint tree nodes. 55 * 56 * Endpoint tree nodes contain a standard endpoint descriptor, plus a pointer to 57 * an array of c/v tree nodes. 58 * 59 * Each array in the tree contains elements ranging from 0 to the largest key 60 * value of it's elements. Endpoints are a special case. The direction bit is 61 * right shifted over three unused bits before the index is determined, leaving 62 * a range of 0..31 instead of a sparsely-populated range of 0..255. 63 * 64 * The indices of tree elements coincide with their USB key values. For 65 * example, standard USB devices have no configuration 0; if they have one 66 * configuration it is #1. dev_cfg[0] is zeroed out; dev_cfg[1] is the root 67 * of configuration #1. 68 * 69 * The idea here is for a driver to be able to parse the tree to easily find a 70 * desired descriptor. For example, the interval of endpoint 2, alternate 3, 71 * interface 1, configuration 1 would be: 72 * dv->dev_cfg[1].cfg_if[1].if_alt[3].altif_ep[2].ep_descr.bInterval 73 * 74 * How the tree is built: 75 * 76 * usb_build_descr_tree() is responsible for the whole process. 77 * 78 * Next, usba_build_descr_tree() coordinates parsing this byte stream, 79 * descriptor by descriptor. usba_build_descr_tree() calls the appropriate 80 * usba_process_xx_descr() function to interpret and install each descriptor in 81 * the tree, based on the descriptor's type. When done with this phase, a 82 * non-sparse tree exists containing tree nodes with descriptors in the order 83 * they were found in the raw data. 84 * 85 * All levels of the tree, except alternates, remain non-sparse. Alternates are 86 * moved, possibly, within their array, so that descriptors are indexed by their 87 * alternate ID. 88 * 89 * The usba_reg_state_t structure maintains state of the tree-building process, 90 * helping coordinate all routines involved. 91 */ 92 #define USBA_FRAMEWORK 93 #include <sys/usb/usba.h> 94 #include <sys/usb/usba/usba_impl.h> 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); 143 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t, 144 uint_t, uint_t, char *, int); 145 146 /* Framework initialization. */ 147 void 148 usba_usbai_register_initialization() 149 { 150 usbai_reg_log_handle = usb_alloc_log_hdl(NULL, "usbreg", 151 &usbai_register_errlevel, 152 &usbai_register_errmask, NULL, 153 0); 154 155 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 156 "usba_usbai_register_initialization"); 157 } 158 159 160 /* Framework destruction. */ 161 void 162 usba_usbai_register_destroy() 163 { 164 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 165 "usba_usbai_register destroy"); 166 167 usb_free_log_hdl(usbai_reg_log_handle); 168 } 169 170 171 /* 172 * usb_client_attach: 173 * 174 * Arguments: 175 * dip - pointer to devinfo node of the client 176 * version - USBA registration version number 177 * flags - None used 178 * 179 * Return Values: 180 * USB_SUCCESS - attach succeeded 181 * USB_INVALID_ARGS - received null dip 182 * USB_INVALID_VERSION - version argument is incorrect. 183 * USB_FAILURE - other internal failure 184 */ 185 /*ARGSUSED*/ 186 int 187 usb_client_attach(dev_info_t *dip, uint_t version, usb_flags_t flags) 188 { 189 int rval; 190 usba_device_t *usba_device; 191 192 if (dip == NULL) { 193 194 return (USB_INVALID_ARGS); 195 } 196 197 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 198 "usb_client attach:"); 199 200 usba_device = usba_get_usba_device(dip); 201 202 /* 203 * Allow exact match for legacy (DDK 0.8/9) drivers, or same major 204 * VERSion and smaller or same minor version for non-legacy drivers. 205 */ 206 if ((version != 207 USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) && 208 ((USBA_GET_MAJOR(version) != USBA_MAJOR_VER) || 209 (USBA_GET_MINOR(version) > USBA_MINOR_VER))) { 210 USB_DPRINTF_L1(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 211 "Incorrect USB driver version for %s%d: found: %d.%d, " 212 "expecting %d.%d", 213 ddi_driver_name(dip), ddi_get_instance(dip), 214 USBA_GET_MAJOR(version), USBA_GET_MINOR(version), 215 USBA_MAJOR_VER, USBA_MINOR_VER); 216 217 return (USB_INVALID_VERSION); 218 } 219 220 if (version == USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) { 221 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 222 "Accepting legacy USB driver version %d.%d for %s%d", 223 USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER, 224 ddi_driver_name(dip), ddi_get_instance(dip)); 225 } 226 227 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-major", 228 USBA_GET_MAJOR(version)); 229 if (rval != DDI_PROP_SUCCESS) { 230 231 return (USB_FAILURE); 232 } 233 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-minor", 234 USBA_GET_MINOR(version)); 235 if (rval != DDI_PROP_SUCCESS) { 236 237 return (USB_FAILURE); 238 } 239 240 mutex_enter(&usba_device->usb_mutex); 241 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) { 242 usba_device->usb_client_flags[usba_get_ifno(dip)] |= 243 USBA_CLIENT_FLAG_ATTACH; 244 usba_device->usb_client_attach_list->dip = dip; 245 } 246 mutex_exit(&usba_device->usb_mutex); 247 248 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 249 "usb_client attach: done"); 250 251 return (USB_SUCCESS); 252 } 253 254 255 /* 256 * usb_client_detach: 257 * free dev_data is reg != NULL, not much else to do 258 * 259 * Arguments: 260 * dip - pointer to devinfo node of the client 261 * reg - return registration data at this address 262 */ 263 void 264 usb_client_detach(dev_info_t *dip, usb_client_dev_data_t *reg) 265 { 266 usba_device_t *usba_device = usba_get_usba_device(dip); 267 268 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 269 "usb_client_detach:"); 270 271 if (dip) { 272 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 273 "Unregistering usb client %s%d: reg=0x%p", 274 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg); 275 276 usb_free_dev_data(dip, reg); 277 278 mutex_enter(&usba_device->usb_mutex); 279 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) { 280 usba_device->usb_client_flags[usba_get_ifno(dip)] &= 281 ~USBA_CLIENT_FLAG_ATTACH; 282 } 283 mutex_exit(&usba_device->usb_mutex); 284 } 285 286 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 287 "usb_client_detach done"); 288 } 289 290 291 /* 292 * usb_register_client (deprecated): 293 * The client registers with USBA during attach. 294 */ 295 /*ARGSUSED*/ 296 int 297 usb_register_client(dev_info_t *dip, uint_t version, 298 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level, 299 usb_flags_t flags) 300 { 301 int rval = usb_client_attach(dip, version, flags); 302 303 if (rval == USB_SUCCESS) { 304 rval = usb_get_dev_data(dip, reg, parse_level, flags); 305 306 if (rval != USB_SUCCESS) { 307 usb_client_detach(dip, NULL); 308 } 309 } 310 311 return (rval); 312 } 313 314 315 /* 316 * usb_unregister_client (deprecated): 317 * Undo the makings of usb_get_dev_data(). Free memory if allocated. 318 * 319 * Arguments: 320 * dip - pointer to devinfo node of the client 321 * reg - pointer to registration data to be freed 322 */ 323 void 324 usb_unregister_client(dev_info_t *dip, usb_client_dev_data_t *reg) 325 { 326 usb_client_detach(dip, reg); 327 } 328 329 330 /* 331 * usb_get_dev_data: 332 * On completion, the registration data has been initialized. 333 * Most data items are straightforward. 334 * Among the items returned in the data is the tree of 335 * parsed descriptors, in dev_cfg; the number of configurations parsed, 336 * in dev_n_cfg; a pointer to the current configuration in the tree, 337 * in dev_curr_cfg; the index of the first valid interface in the 338 * tree, in dev_curr_if, and a parse level that accurately reflects what 339 * is in the tree, in dev_parse_level. 340 * 341 * This routine sets up directly-initialized fields, and calls 342 * usb_build_descr_tree() to parse the raw descriptors and initialize the 343 * tree. 344 * 345 * Parse_level determines the extent to which the tree is built. It has 346 * the following values: 347 * 348 * USB_PARSE_LVL_NONE - Build no tree. dev_n_cfg will return 0, dev_cfg 349 * and dev_curr_cfg will return NULL. 350 * USB_PARSE_LVL_IF - Parse configured interface only, if configuration# 351 * and interface properties are set (as when different 352 * interfaces are viewed by the OS as different device 353 * instances). If an OS device instance is set up to 354 * represent an entire physical device, this works 355 * like USB_PARSE_LVL_ALL. 356 * USB_PARSE_LVL_CFG - Parse entire configuration of configured interface 357 * only. This is like USB_PARSE_LVL_IF except entire 358 * configuration is returned. 359 * USB_PARSE_LVL_ALL - Parse entire device (all configurations), even 360 * when driver is bound to a single interface of a 361 * single configuration. 362 * 363 * No tree is built for root hubs, regardless of parse_level. 364 * 365 * Arguments: 366 * dip - pointer to devinfo node of the client 367 * version - USBA registration version number 368 * reg - return registration data at this address 369 * parse_level - See above 370 * flags - None used 371 * 372 * Return Values: 373 * USB_SUCCESS - usb_get_dev_data succeeded 374 * USB_INVALID_ARGS - received null dip or reg argument 375 * USB_INVALID_CONTEXT - called from callback context 376 * USB_FAILURE - bad descriptor info or other internal failure 377 * 378 * Note: The non-standard USB descriptors are returned in RAW format. 379 * returns initialized registration data. Most data items are clear. 380 * Among the items returned is the tree of parsed descriptors in dev_cfg; 381 * and the number of configurations parsed in dev_n_cfg. 382 * 383 * The registration data is not shared. each client receives its own 384 * copy. 385 */ 386 /*ARGSUSED*/ 387 int 388 usb_get_dev_data(dev_info_t *dip, 389 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level, 390 usb_flags_t flags) 391 { 392 usb_client_dev_data_t *usb_reg = NULL; 393 char *tmpbuf = NULL; 394 usba_device_t *usba_device; 395 int rval = USB_SUCCESS; 396 397 if ((dip == NULL) || (reg == NULL)) { 398 399 return (USB_INVALID_ARGS); 400 } 401 402 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 403 "usb_get_dev_data: %s%d", 404 ddi_driver_name(dip), ddi_get_instance(dip)); 405 406 *reg = NULL; 407 408 /* did the client attach first? */ 409 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 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); 460 } 461 462 if (usba_device->usb_serialno_str != NULL) { 463 usb_reg->dev_serial = kmem_zalloc( 464 strlen(usba_device->usb_serialno_str) + 1, 465 KM_SLEEP); 466 (void) strcpy(usb_reg->dev_serial, 467 usba_device->usb_serialno_str); 468 } 469 470 if ((usb_reg->dev_parse_level = parse_level) == USB_PARSE_LVL_NONE) { 471 rval = USB_SUCCESS; 472 473 } else if ((rval = usba_build_descr_tree(dip, usba_device, usb_reg)) != 474 USB_SUCCESS) { 475 usb_unregister_client(dip, usb_reg); 476 usb_reg = NULL; 477 } else { 478 479 /* Current tree cfg is always zero if only one cfg in tree. */ 480 if (usb_reg->dev_n_cfg == 1) { 481 usb_reg->dev_curr_cfg = &usb_reg->dev_cfg[0]; 482 } else { 483 mutex_enter(&usba_device->usb_mutex); 484 usb_reg->dev_curr_cfg = 485 &usb_reg->dev_cfg[usba_device->usb_active_cfg_ndx]; 486 mutex_exit(&usba_device->usb_mutex); 487 ASSERT(usb_reg->dev_curr_cfg != NULL); 488 ASSERT(usb_reg->dev_curr_cfg->cfg_descr.bLength == 489 USB_CFG_DESCR_SIZE); 490 } 491 492 /* 493 * Keep dev_curr_if at device's single interface only if that 494 * particular interface has been explicitly defined by the 495 * device. 496 */ 497 usb_reg->dev_curr_if = usba_get_ifno(dip); 498 #ifdef DEBUG 499 (void) usb_log_descr_tree(usb_reg, usbai_reg_log_handle, 500 usbai_register_dump_errlevel, (uint_t)-1); 501 #endif 502 /* 503 * Fail if interface and configuration of dev_curr_if and 504 * dev_curr_cfg don't exist or are invalid. (Shouldn't happen.) 505 * These indices must be reliable for tree traversal. 506 */ 507 if ((usb_reg->dev_curr_cfg->cfg_n_if <= usb_reg->dev_curr_if) || 508 (usb_reg->dev_curr_cfg->cfg_descr.bLength == 0) || 509 (usb_reg->dev_curr_cfg->cfg_if[usb_reg->dev_curr_if]. 510 if_n_alt == 0)) { 511 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle, 512 "usb_get_dev_data: dev_curr_cfg or " 513 "dev_curr_if have no descriptors"); 514 usb_unregister_client(dip, usb_reg); 515 usb_reg = NULL; 516 rval = USB_FAILURE; 517 } 518 } 519 520 *reg = usb_reg; 521 kmem_free(tmpbuf, USB_MAXSTRINGLEN); 522 523 if (rval == USB_SUCCESS) { 524 usb_client_dev_data_list_t *entry = kmem_zalloc( 525 sizeof (*entry), KM_SLEEP); 526 mutex_enter(&usba_device->usb_mutex); 527 528 usba_device->usb_client_flags[usba_get_ifno(dip)] |= 529 USBA_CLIENT_FLAG_DEV_DATA; 530 531 entry->cddl_dip = dip; 532 entry->cddl_dev_data = usb_reg; 533 entry->cddl_ifno = usba_get_ifno(dip); 534 535 entry->cddl_next = 536 usba_device->usb_client_dev_data_list.cddl_next; 537 if (entry->cddl_next) { 538 entry->cddl_next->cddl_prev = entry; 539 } 540 entry->cddl_prev = &usba_device->usb_client_dev_data_list; 541 usba_device->usb_client_dev_data_list.cddl_next = entry; 542 543 mutex_exit(&usba_device->usb_mutex); 544 } 545 546 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 547 "usb_get_dev_data rval=%d", rval); 548 549 return (rval); 550 } 551 552 553 /* 554 * usb_free_dev_data 555 * undoes what usb_get_dev_data does 556 * 557 * Arguments: 558 * dip - pointer to devinfo node of the client 559 * reg - return registration data at this address 560 */ 561 void 562 usb_free_dev_data(dev_info_t *dip, usb_client_dev_data_t *reg) 563 { 564 if (dip == NULL) { 565 566 return; 567 } 568 569 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 570 "usb_free_dev_data %s%d: reg=0x%p", 571 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg); 572 573 if (reg != NULL) { 574 usba_device_t *usba_device = usba_get_usba_device(dip); 575 usb_client_dev_data_list_t *next, *prev, *entry; 576 int matches = 0; 577 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++; 622 } 623 prev = entry; 624 } 625 entry = next; 626 } 627 628 USB_DPRINTF_L3(DPRINT_MASK_REGISTER, 629 usbai_reg_log_handle, 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) 704 { 705 usba_reg_state_t state; /* State of tree construction */ 706 int cfg_len_so_far = 0; /* Bytes found, this config. */ 707 uint8_t *last_byte; /* Ptr to the end of the cfg cloud. */ 708 uint_t this_cfg_ndx; /* Configuration counter. */ 709 uint_t high_cfg_bound; /* High config index + 1. */ 710 uint_t low_cfg_bound; /* Low config index. */ 711 boolean_t process_this_if_tree = B_FALSE; /* Save alts, eps, */ 712 /* of this interface. */ 713 714 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 715 "usba_build_descr_tree starting"); 716 717 bzero(&state, sizeof (usba_reg_state_t)); 718 state.dip = dip; 719 720 /* 721 * Set config(s) and interface(s) to parse based on parse level. 722 * Adjust parse_level according to which configs and interfaces are 723 * made available by the device. 724 */ 725 state.st_dev_parse_level = usb_reg->dev_parse_level; 726 if (usba_set_parse_values(dip, usba_device, &state) != USB_SUCCESS) { 727 728 return (USB_INVALID_ARGS); 729 } 730 usb_reg->dev_parse_level = state.st_dev_parse_level; 731 732 /* Preallocate configurations based on parse level. */ 733 if (usb_reg->dev_parse_level == USB_PARSE_LVL_ALL) { 734 usb_reg->dev_n_cfg = usba_device->usb_n_cfgs; 735 low_cfg_bound = 0; 736 high_cfg_bound = usba_device->usb_n_cfgs; 737 } else { 738 usb_reg->dev_n_cfg = 1; 739 mutex_enter(&usba_device->usb_mutex); 740 low_cfg_bound = usba_device->usb_active_cfg_ndx; 741 high_cfg_bound = usba_device->usb_active_cfg_ndx + 1; 742 mutex_exit(&usba_device->usb_mutex); 743 } 744 usb_reg->dev_cfg = state.st_dev_cfg = kmem_zalloc( 745 (usb_reg->dev_n_cfg * sizeof (usb_cfg_data_t)), 746 KM_SLEEP); 747 /* 748 * this_cfg_ndx loops through all configurations presented; 749 * state.st_dev_n_cfg limits the cfgs checked to the number desired. 750 */ 751 state.st_dev_n_cfg = 0; 752 for (this_cfg_ndx = low_cfg_bound; this_cfg_ndx < high_cfg_bound; 753 this_cfg_ndx++) { 754 755 state.st_curr_raw_descr = 756 usba_device->usb_cfg_array[this_cfg_ndx]; 757 ASSERT(state.st_curr_raw_descr != NULL); 758 759 /* Clear the following for config cloud sanity checking. */ 760 last_byte = NULL; 761 state.st_curr_cfg = NULL; 762 state.st_curr_if = NULL; 763 state.st_curr_alt = NULL; 764 state.st_curr_ep = NULL; 765 766 do { 767 /* All descr have length and type at offset 0 and 1 */ 768 state.st_curr_raw_descr_len = 769 state.st_curr_raw_descr[0]; 770 state.st_curr_raw_descr_type = 771 state.st_curr_raw_descr[1]; 772 773 /* First descr in cloud must be a config descr. */ 774 if ((last_byte == NULL) && 775 (state.st_curr_raw_descr_type != 776 USB_DESCR_TYPE_CFG)) { 777 778 return (USB_FAILURE); 779 } 780 781 /* 782 * Bomb if we don't find a new cfg descr when expected. 783 * cfg_len_so_far = total_cfg_length = 0 1st time thru. 784 */ 785 if (cfg_len_so_far > state.st_total_cfg_length) { 786 USB_DPRINTF_L2(DPRINT_MASK_ALL, 787 usbai_reg_log_handle, 788 "usba_build_descr_tree: Configuration (%d) " 789 "larger than wTotalLength (%d).", 790 cfg_len_so_far, state.st_total_cfg_length); 791 792 return (USB_FAILURE); 793 } 794 795 USB_DPRINTF_L3(DPRINT_MASK_REGISTER, 796 usbai_reg_log_handle, 797 "usba_build_descr_tree: Process type %d descr " 798 "(addr=0x%p)", state.st_curr_raw_descr_type, 799 (void *)state.st_curr_raw_descr); 800 801 switch (state.st_curr_raw_descr_type) { 802 case USB_DESCR_TYPE_CFG: 803 cfg_len_so_far = 0; 804 process_this_if_tree = B_FALSE; 805 806 state.st_curr_cfg_str = usba_device-> 807 usb_cfg_str_descr[this_cfg_ndx]; 808 usba_process_cfg_descr(&state); 809 state.st_last_processed_descr_type = 810 USB_DESCR_TYPE_CFG; 811 last_byte = state.st_curr_raw_descr + 812 (state.st_total_cfg_length * 813 sizeof (uchar_t)); 814 815 break; 816 817 case USB_DESCR_TYPE_IF: 818 /* 819 * process_this_if_tree == TRUE means this 820 * interface, plus all eps and c/vs in it are 821 * to be processed. 822 */ 823 if (usba_process_if_descr(&state, 824 &process_this_if_tree) != USB_SUCCESS) { 825 826 return (USB_FAILURE); 827 } 828 state.st_last_processed_descr_type = 829 USB_DESCR_TYPE_IF; 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 == 882 USB_DESCR_TYPE_CFG) || 883 (process_this_if_tree == B_TRUE)) { 884 if (usba_process_cv_descr(&state) != 885 USB_SUCCESS) { 886 887 return (USB_FAILURE); 888 } 889 } 890 } 891 892 state.st_curr_raw_descr += state.st_curr_raw_descr_len; 893 cfg_len_so_far += state.st_curr_raw_descr_len; 894 895 } while (state.st_curr_raw_descr < last_byte); 896 } 897 898 /* Make tree sparse, and put elements in order. */ 899 usba_order_tree(&state); 900 901 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 902 "usba_build_descr_tree done"); 903 904 return (USB_SUCCESS); 905 } 906 907 908 /* 909 * usba_process_cfg_descr: 910 * Set up a configuration tree node based on a raw config descriptor. 911 * 912 * Arguments: 913 * state - Pointer to this module's state structure. 914 * 915 * Returns: 916 * B_TRUE: the descr processed corresponds to a requested configuration. 917 * B_FALSE: the descr processed does not correspond to a requested config. 918 */ 919 static void 920 usba_process_cfg_descr(usba_reg_state_t *state) 921 { 922 usb_cfg_data_t *curr_cfg; 923 924 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 925 "usba_process_cfg_descr starting"); 926 927 curr_cfg = state->st_curr_cfg = 928 &state->st_dev_cfg[state->st_dev_n_cfg++]; 929 930 /* Parse and store config descriptor proper in the tree. */ 931 (void) usb_parse_data("2cs5c", 932 state->st_curr_raw_descr, state->st_curr_raw_descr_len, 933 &curr_cfg->cfg_descr, 934 sizeof (usb_cfg_descr_t)); 935 936 state->st_total_cfg_length = curr_cfg->cfg_descr.wTotalLength; 937 938 if (state->st_curr_cfg_str != NULL) { 939 curr_cfg->cfg_strsize = strlen(state->st_curr_cfg_str) + 1; 940 curr_cfg->cfg_str = kmem_zalloc(curr_cfg->cfg_strsize, 941 KM_SLEEP); 942 (void) strcpy(curr_cfg->cfg_str, state->st_curr_cfg_str); 943 } 944 945 curr_cfg->cfg_n_if = curr_cfg->cfg_descr.bNumInterfaces; 946 curr_cfg->cfg_if = kmem_zalloc((curr_cfg->cfg_n_if * 947 sizeof (usb_if_data_t)), KM_SLEEP); 948 949 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 950 "usba_process_cfg_descr done"); 951 } 952 953 954 /* 955 * usba_process_if_descr: 956 * This processes a raw interface descriptor, and sets up an analogous 957 * interface node and child "alternate" nodes (each containing an 958 * interface descriptor) in the descriptor tree. 959 * 960 * It groups all descriptors with the same bInterfaceNumber (alternates) 961 * into an array. It makes entries in an interface array, each of which 962 * points to an array of alternates. 963 * 964 * Arguments: 965 * state - Pointer to this module's state structure. 966 * requested_if - Address into which the following is returned: 967 * B_TRUE - the processed descr is of a requested interface. 968 * B_FALSE - the processed descr if of a non-requested interface. 969 * 970 * Returns: 971 * USB_SUCCESS: Descriptor is successfully parsed. 972 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 973 */ 974 static int 975 usba_process_if_descr(usba_reg_state_t *state, boolean_t *requested_if) 976 { 977 char *string; 978 usb_if_descr_t *new_if_descr; 979 usba_device_t *usba_device = usba_get_usba_device(state->dip); 980 int is_root_hub = (usba_device->usb_addr == ROOT_HUB_ADDR); 981 982 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 983 "usba_process_if_descr starting"); 984 985 /* No config preceeds this interface. */ 986 if (state->st_curr_cfg == NULL) { 987 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 988 "usba_process_if_descr found interface after no config."); 989 990 return (USB_FAILURE); 991 } 992 993 new_if_descr = kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP); 994 995 /* Strictly speaking, unpacking is not necessary. Could use bcopy. */ 996 (void) usb_parse_data("9c", state->st_curr_raw_descr, 997 state->st_curr_raw_descr_len, 998 new_if_descr, sizeof (usb_if_descr_t)); 999 1000 /* Check the interface number in case of a malfunction device */ 1001 if (new_if_descr->bInterfaceNumber >= state->st_curr_cfg->cfg_n_if) { 1002 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1003 "usba_process_if_descr: bInterfaceNumber=%d is not " 1004 "a valid one", new_if_descr->bInterfaceNumber); 1005 kmem_free(new_if_descr, sizeof (usb_if_descr_t)); 1006 1007 *requested_if = B_FALSE; 1008 1009 return (USB_SUCCESS); 1010 } 1011 *requested_if = B_TRUE; 1012 1013 /* Not a requested interface. */ 1014 if ((state->st_if_to_build != new_if_descr->bInterfaceNumber) && 1015 (state->st_if_to_build != USBA_ALL)) { 1016 *requested_if = B_FALSE; 1017 1018 } else { 1019 usb_alt_if_data_t *alt_array; 1020 uint_t alt_index; 1021 1022 /* Point to proper interface node, based on num in descr. */ 1023 state->st_curr_if = 1024 &state->st_curr_cfg->cfg_if[new_if_descr->bInterfaceNumber]; 1025 1026 /* Make room for new alternate. */ 1027 alt_index = state->st_curr_if->if_n_alt; 1028 alt_array = state->st_curr_if->if_alt; 1029 usba_augment_array((void **)(&alt_array), alt_index, 1030 sizeof (usb_alt_if_data_t)); 1031 1032 /* Ptr to the current alt, may be used to attach a c/v to it. */ 1033 state->st_curr_alt = &alt_array[alt_index]; 1034 1035 bcopy(new_if_descr, &(alt_array[alt_index++].altif_descr), 1036 sizeof (usb_if_descr_t)); 1037 state->st_curr_if->if_alt = alt_array; 1038 state->st_curr_if->if_n_alt = alt_index; 1039 1040 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 1041 if (!is_root_hub) { 1042 (void) usb_get_string_descr(state->dip, USB_LANG_ID, 1043 state->st_curr_alt->altif_descr.iInterface, 1044 string, USB_MAXSTRINGLEN); 1045 } 1046 if (string[0] == '\0') { 1047 (void) strcpy(string, "<none>"); 1048 } 1049 state->st_curr_alt->altif_strsize = strlen(string) + 1; 1050 state->st_curr_alt->altif_str = kmem_zalloc( 1051 state->st_curr_alt->altif_strsize, KM_SLEEP); 1052 (void) strcpy(state->st_curr_alt->altif_str, string); 1053 kmem_free(string, USB_MAXSTRINGLEN); 1054 } 1055 1056 kmem_free(new_if_descr, sizeof (usb_if_descr_t)); 1057 1058 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1059 "usba_process_if_descr done"); 1060 1061 return (USB_SUCCESS); 1062 } 1063 1064 1065 /* 1066 * usba_process_ep_descr: 1067 * This processes a raw endpoint descriptor, and sets up an analogous 1068 * endpoint descriptor node in the descriptor tree. 1069 * 1070 * Arguments: 1071 * state - Pointer to this module's state structure. 1072 * 1073 * Returns: 1074 * USB_SUCCESS: Descriptor is successfully parsed. 1075 * USB_FAILURE: Descriptor is inappropriately placed in config cloud. 1076 */ 1077 static int 1078 usba_process_ep_descr(usba_reg_state_t *state) 1079 { 1080 usb_alt_if_data_t *curr_alt = state->st_curr_alt; 1081 1082 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1083 "usba_process_ep_descr starting"); 1084 1085 /* No interface preceeds this endpoint. */ 1086 if (state->st_curr_alt == NULL) { 1087 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1088 "usba_process_ep_descr: no requested alt before endpt."); 1089 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; 1154 1155 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1156 "usba_process_cv_descr starting. Processing c/v for descr type %d", 1157 state->st_last_processed_descr_type); 1158 1159 /* 1160 * Attach the c/v to a node based on the last descr type processed. 1161 * Save handles to appropriate c/v node array and count to update. 1162 */ 1163 switch (state->st_last_processed_descr_type) { 1164 case USB_DESCR_TYPE_CFG: 1165 n_cvs_ptr = &state->st_curr_cfg->cfg_n_cvs; 1166 cvs_ptr = &state->st_curr_cfg->cfg_cvs; 1167 break; 1168 1169 case USB_DESCR_TYPE_IF: 1170 n_cvs_ptr = &state->st_curr_alt->altif_n_cvs; 1171 cvs_ptr = &state->st_curr_alt->altif_cvs; 1172 break; 1173 1174 case USB_DESCR_TYPE_EP: 1175 n_cvs_ptr = &state->st_curr_ep->ep_n_cvs; 1176 cvs_ptr = &state->st_curr_ep->ep_cvs; 1177 break; 1178 1179 default: 1180 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle, 1181 "usba_process_cv_descr: Type of last descriptor unknown. "); 1182 1183 return (USB_FAILURE); 1184 } 1185 1186 usba_augment_array((void **)cvs_ptr, *n_cvs_ptr, 1187 sizeof (usb_cvs_data_t)); 1188 curr_cv_descr = &(*cvs_ptr)[(*n_cvs_ptr)++]; 1189 1190 curr_cv_descr->cvs_buf = 1191 kmem_zalloc(state->st_curr_raw_descr_len, KM_SLEEP); 1192 curr_cv_descr->cvs_buf_len = state->st_curr_raw_descr_len; 1193 bcopy(state->st_curr_raw_descr, curr_cv_descr->cvs_buf, 1194 state->st_curr_raw_descr_len); 1195 1196 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1197 "usba_process_cv_descr done"); 1198 1199 return (USB_SUCCESS); 1200 } 1201 1202 1203 /* 1204 * usba_set_parse_values: 1205 * Based on parse level, set the configuration(s) and interface(s) to build 1206 * 1207 * Returned configuration value can be USBA_ALL indicating to build all 1208 * configurations. Likewise for the returned interface value. 1209 * 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; 1251 } 1252 break; 1253 1254 default: 1255 1256 return (USB_INVALID_ARGS); 1257 } 1258 1259 /* 1260 * Set parse level to identify this tree properly, regardless of what 1261 * the caller thought the tree would have. 1262 */ 1263 if ((state->st_if_to_build == USBA_ALL) && 1264 (state->st_dev_parse_level == USB_PARSE_LVL_IF)) { 1265 state->st_dev_parse_level = USB_PARSE_LVL_CFG; 1266 } 1267 if ((state->st_cfg_to_build == USBA_ALL) && 1268 (state->st_dev_parse_level == USB_PARSE_LVL_CFG)) { 1269 state->st_dev_parse_level = USB_PARSE_LVL_ALL; 1270 } 1271 1272 return (USB_SUCCESS); 1273 } 1274 1275 1276 /* 1277 * usba_kmem_realloc: 1278 * Resize dynamic memory. Copy contents of old area to 1279 * beginning of new area. 1280 * 1281 * Arguments: 1282 * old_mem - pointer to old memory area. 1283 * old_size - size of old memory area. 0 is OK. 1284 * new_size - size desired. 1285 * 1286 * Returns: 1287 * pointer to new memory area. 1288 */ 1289 static void* 1290 usba_kmem_realloc(void* old_mem, int old_size, int new_size) 1291 { 1292 void *new_mem = NULL; 1293 1294 if (new_size > 0) { 1295 new_mem = kmem_zalloc(new_size, KM_SLEEP); 1296 if (old_size > 0) { 1297 bcopy(old_mem, new_mem, 1298 min(old_size, new_size)); 1299 } 1300 } 1301 1302 if (old_size > 0) { 1303 kmem_free(old_mem, old_size); 1304 } 1305 1306 return (new_mem); 1307 } 1308 1309 1310 /* 1311 * usba_augment_array: 1312 * Add a new element on the end of an array. 1313 * 1314 * Arguments: 1315 * addr - ptr to the array address. Array addr will change. 1316 * n_elements - array element count. 1317 * element_size - size of an array element 1318 */ 1319 static void 1320 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size) 1321 { 1322 *addr = usba_kmem_realloc(*addr, (n_elements * element_size), 1323 ((n_elements + 1) * element_size)); 1324 } 1325 1326 1327 /* 1328 * usba_make_alts_sparse: 1329 * Disburse alternate array elements such that they are at the proper array 1330 * indices for which alt they represent. It is assumed that all key values 1331 * used for ordering the elements are positive. Original array space may 1332 * be freed and new space allocated. 1333 * 1334 * Arguments: 1335 * array - pointer to alternates array; may be modified 1336 * n_elements - number of elements in the array; may be modified 1337 */ 1338 static void 1339 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements) 1340 { 1341 uint_t n_orig_elements = *n_elements; 1342 uint8_t smallest_value; 1343 uint8_t largest_value; 1344 uint8_t curr_value; 1345 uint_t in_order = 0; 1346 usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */ 1347 usb_alt_if_data_t *repl_array; /* Base ptr to sparse array */ 1348 uint_t n_repl_elements; /* Number elements in the new array */ 1349 uint_t i; 1350 1351 /* Check for a null array. */ 1352 if ((array == NULL) || (n_orig_elements == 0)) { 1353 1354 return; 1355 } 1356 1357 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1358 "make_sparse: array=0x%p, n_orig_elements=%d", 1359 (void *)array, n_orig_elements); 1360 1361 curr_value = orig_addr[0].altif_descr.bAlternateSetting; 1362 smallest_value = largest_value = curr_value; 1363 1364 /* Figure the low-high range of the array. */ 1365 for (i = 1; i < n_orig_elements; i++) { 1366 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1367 if (curr_value < smallest_value) { 1368 smallest_value = curr_value; 1369 } else if (curr_value > largest_value) { 1370 in_order++; 1371 largest_value = curr_value; 1372 } 1373 } 1374 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1375 "make_sparse: largest=%d, smallest=%d, " 1376 "order=%d", 1377 largest_value, smallest_value, in_order); 1378 1379 n_repl_elements = largest_value + 1; 1380 1381 /* 1382 * No holes to leave, array starts at zero, and everything is already 1383 * in order. Just return original array. 1384 */ 1385 if ((n_repl_elements == n_orig_elements) && 1386 ((in_order + 1) == n_orig_elements)) { 1387 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1388 "No holes"); 1389 1390 return; 1391 } 1392 1393 /* Allocate zeroed space for the array. */ 1394 repl_array = kmem_zalloc( 1395 (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP); 1396 1397 /* Now fill in the array. */ 1398 for (i = 0; i < n_orig_elements; i++) { 1399 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1400 1401 /* Place in sparse array based on key. */ 1402 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1403 "move %lu bytes (key %d) from 0x%p to 0x%p", 1404 (unsigned long)sizeof (usb_alt_if_data_t), curr_value, 1405 (void *)&orig_addr[i], (void *)&repl_array[curr_value]); 1406 1407 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value], 1408 sizeof (usb_alt_if_data_t)); 1409 } 1410 1411 kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements); 1412 *array = repl_array; 1413 *n_elements = n_repl_elements; 1414 } 1415 1416 1417 /* 1418 * usba_order_tree: 1419 * Take a tree as built by usba_build_descr_tree and make sure the key 1420 * values of all elements match their indeces. Proper order is implied. 1421 * 1422 * Arguments: 1423 * state - Pointer to this module's state structure. 1424 */ 1425 static void 1426 usba_order_tree(usba_reg_state_t *state) 1427 { 1428 usb_cfg_data_t *this_cfg; 1429 usb_if_data_t *this_if; 1430 uint_t n_cfgs = state->st_dev_n_cfg; 1431 uint_t cfg; 1432 uint_t which_if; 1433 1434 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1435 "usba_order_tree:"); 1436 1437 for (cfg = 0; cfg < n_cfgs; cfg++) { 1438 this_cfg = &state->st_dev_cfg[cfg]; 1439 1440 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) { 1441 this_if = this_cfg->cfg_if; 1442 usba_make_alts_sparse(&this_if->if_alt, 1443 &this_if->if_n_alt); 1444 } 1445 } 1446 } 1447 1448 1449 /* 1450 * usb_free_descr_tree: 1451 * Take down the configuration tree. Called internally and can be called 1452 * from a driver standalone to take the tree down while leaving the rest 1453 * of the registration intact. 1454 * 1455 * Arguments: 1456 * dip - pointer to devinfo of the device 1457 * dev_data - pointer to registration data containing the tree. 1458 */ 1459 void 1460 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1461 { 1462 usb_cfg_data_t *cfg_array; 1463 int n_cfgs; 1464 int cfg; 1465 1466 if ((dip == NULL) || (dev_data == NULL)) { 1467 1468 return; 1469 } 1470 cfg_array = dev_data->dev_cfg; 1471 n_cfgs = dev_data->dev_n_cfg; 1472 1473 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1474 "usb_free_descr_tree starting for %s%d", 1475 ddi_driver_name(dip), ddi_get_instance(dip)); 1476 1477 for (cfg = 0; cfg < n_cfgs; cfg++) { 1478 if (cfg_array[cfg].cfg_if) { 1479 usba_free_if_array(cfg_array[cfg].cfg_if, 1480 cfg_array[cfg].cfg_n_if); 1481 } 1482 if (cfg_array[cfg].cfg_cvs) { 1483 usba_free_cv_array(cfg_array[cfg].cfg_cvs, 1484 cfg_array[cfg].cfg_n_cvs); 1485 } 1486 if (cfg_array[cfg].cfg_str) { 1487 kmem_free(cfg_array[cfg].cfg_str, 1488 cfg_array[cfg].cfg_strsize); 1489 } 1490 } 1491 1492 if (cfg_array) { 1493 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs)); 1494 } 1495 1496 dev_data->dev_parse_level = USB_PARSE_LVL_NONE; 1497 dev_data->dev_n_cfg = 0; 1498 dev_data->dev_cfg = NULL; 1499 dev_data->dev_curr_cfg = NULL; 1500 1501 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1502 "usb_free_descr_tree done"); 1503 } 1504 1505 1506 /* 1507 * usba_free_if_array: 1508 * Free a configuration's array of interface nodes and their subtrees of 1509 * interface alternate, endpoint and c/v descriptors. 1510 * 1511 * Arguments: 1512 * if_array - pointer to array of interfaces to remove. 1513 * n_ifs - number of elements in the array to remove. 1514 */ 1515 static void 1516 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs) 1517 { 1518 uint_t which_if; 1519 uint_t which_alt; 1520 uint_t n_alts; 1521 usb_alt_if_data_t *altif; 1522 1523 for (which_if = 0; which_if < n_ifs; which_if++) { 1524 n_alts = if_array[which_if].if_n_alt; 1525 1526 /* Every interface has at least one alternate. */ 1527 for (which_alt = 0; which_alt < n_alts; which_alt++) { 1528 altif = &if_array[which_if].if_alt[which_alt]; 1529 usba_free_ep_array(altif->altif_ep, altif->altif_n_ep); 1530 usba_free_cv_array(altif->altif_cvs, 1531 altif->altif_n_cvs); 1532 kmem_free(altif->altif_str, altif->altif_strsize); 1533 } 1534 1535 kmem_free(if_array[which_if].if_alt, 1536 (sizeof (usb_alt_if_data_t) * n_alts)); 1537 } 1538 1539 /* Free the interface array itself. */ 1540 kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs)); 1541 } 1542 1543 1544 /* 1545 * usba_free_ep_array: 1546 * Free an array of endpoint nodes and their subtrees of c/v descriptors. 1547 * 1548 * Arguments: 1549 * ep_array - pointer to array of endpoints to remove. 1550 * n_eps - number of elements in the array to remove. 1551 */ 1552 static void 1553 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps) 1554 { 1555 uint_t ep; 1556 1557 for (ep = 0; ep < n_eps; ep++) { 1558 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs); 1559 } 1560 1561 kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps)); 1562 } 1563 1564 1565 /* 1566 * usba_free_cv_array: 1567 * Free an array of class/vendor (c/v) descriptor nodes. 1568 * 1569 * Arguments: 1570 * cv_array - pointer to array of c/v nodes to remove. 1571 * n_cvs - number of elements in the array to remove. 1572 */ 1573 static void 1574 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs) 1575 { 1576 uint_t cv_node; 1577 1578 /* Free data areas hanging off of each c/v descriptor. */ 1579 for (cv_node = 0; cv_node < n_cvs; cv_node++) { 1580 kmem_free(cv_array[cv_node].cvs_buf, 1581 cv_array[cv_node].cvs_buf_len); 1582 } 1583 1584 /* Free the array of cv descriptors. */ 1585 kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs)); 1586 } 1587 1588 1589 /* 1590 * usb_log_descr_tree: 1591 * Log to the usba_debug_buf a descriptor tree as returned by 1592 * usbai_register_client. 1593 * 1594 * Arguments: 1595 * dev_data - pointer to registration area containing the tree 1596 * log_handle - pointer to log handle to use for dumping. 1597 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1598 * Please see usb_log(9F) for details. 1599 * mask - print mask. Please see usb_log(9F) for details. 1600 * 1601 * Returns: 1602 * USB_SUCCESS - tree successfully dumped 1603 * USB_INVALID_CONTEXT - called from callback context 1604 * USB_INVALID_ARGS - bad arguments given 1605 */ 1606 int 1607 usb_log_descr_tree(usb_client_dev_data_t *dev_data, 1608 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1609 { 1610 return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask)); 1611 } 1612 1613 1614 /* 1615 * usb_print_descr_tree: 1616 * Print to the screen a descriptor tree as returned by 1617 * usbai_register_client. 1618 * 1619 * Arguments: 1620 * dip - pointer to devinfo of the client 1621 * dev_data - pointer to registration area containing the tree 1622 * 1623 * Returns: 1624 * USB_SUCCESS - tree successfully dumped 1625 * USB_INVALID_CONTEXT - called from callback context 1626 * USB_INVALID_ARGS - bad arguments given 1627 */ 1628 int 1629 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1630 { 1631 return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0)); 1632 } 1633 1634 1635 /* 1636 * usba_dump_descr_tree: 1637 * Dump a descriptor tree. 1638 * 1639 * Arguments: 1640 * dip - pointer to devinfo of the client. Used when no 1641 * log_handle argument given. 1642 * usb_reg - pointer to registration area containing the tree 1643 * log_handle - pointer to log handle to use for dumping. If NULL, 1644 * use internal log handle, which dumps to screen. 1645 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1646 * Used only when log_handle provided. 1647 * mask - print mask, used when log_handle argument provided. 1648 * 1649 * Returns: 1650 * USB_SUCCESS - tree successfully dumped 1651 * USB_INVALID_CONTEXT - called from callback context 1652 * USB_INVALID_ARGS - bad arguments given 1653 */ 1654 static int 1655 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg, 1656 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1657 { 1658 usb_log_handle_t dump_handle; 1659 uint_t dump_level; 1660 uint_t dump_mask; 1661 int which_config; /* Counters. */ 1662 int which_if; 1663 int which_cv; 1664 usb_cfg_data_t *config; /* ptr to current configuration tree node */ 1665 usb_cfg_descr_t *config_descr; /* and its USB descriptor. */ 1666 char *string; 1667 char *name_string = NULL; 1668 int name_string_size; 1669 1670 if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) { 1671 1672 return (USB_INVALID_ARGS); 1673 } 1674 1675 /* 1676 * To keep calling this simple, kmem_zalloc with the sleep flag always. 1677 * This means no interrupt context is allowed. 1678 */ 1679 if (servicing_interrupt()) { 1680 1681 return (USB_INVALID_CONTEXT); 1682 } 1683 1684 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 1685 1686 if (log_handle != NULL) { 1687 dump_level = level; 1688 dump_mask = mask; 1689 dump_handle = log_handle; 1690 } else { 1691 dump_level = USB_LOG_L1; 1692 dump_mask = DPRINT_MASK_ALL; 1693 1694 /* Build device name string. */ 1695 (void) snprintf(string, USB_MAXSTRINGLEN, 1696 "Port%d", usb_get_addr(dip)); 1697 name_string_size = strlen(string) + 1; 1698 name_string = kmem_zalloc(name_string_size, KM_SLEEP); 1699 (void) strcpy(name_string, string); 1700 1701 /* Allocate a log handle specifying the name string. */ 1702 dump_handle = usb_alloc_log_hdl(NULL, name_string, 1703 &dump_level, &dump_mask, NULL, 1704 USB_FLAGS_SLEEP); 1705 } 1706 1707 (void) usb_log(dump_handle, dump_level, dump_mask, 1708 "USB descriptor tree for %s %s", 1709 (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""), 1710 (usb_reg->dev_product != NULL ? usb_reg->dev_product : "")); 1711 if (usb_reg->dev_n_cfg == 0) { 1712 (void) usb_log(dump_handle, dump_level, dump_mask, 1713 "No descriptor tree present"); 1714 } else { 1715 (void) usb_log(dump_handle, dump_level, dump_mask, 1716 "highest configuration found=%d", usb_reg->dev_n_cfg - 1); 1717 } 1718 1719 for (which_config = 0; which_config < usb_reg->dev_n_cfg; 1720 which_config++) { 1721 config = &usb_reg->dev_cfg[which_config]; 1722 config_descr = &config->cfg_descr; 1723 if (config_descr->bLength == 0) { 1724 1725 continue; 1726 } 1727 if (dump_level == USB_LOG_L0) { 1728 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1729 } 1730 (void) usb_log(dump_handle, dump_level, dump_mask, 1731 "Configuration #%d (Addr= 0x%p)", which_config, 1732 (void *)config); 1733 (void) usb_log(dump_handle, dump_level, dump_mask, 1734 "String descr=%s", config->cfg_str); 1735 (void) usb_log(dump_handle, dump_level, dump_mask, 1736 "config descr: len=%d tp=%d totLen=%d numIf=%d " 1737 "cfgVal=%d att=0x%x pwr=%d", 1738 config_descr->bLength, config_descr->bDescriptorType, 1739 config_descr->wTotalLength, config_descr->bNumInterfaces, 1740 config_descr->bConfigurationValue, 1741 config_descr->bmAttributes, config_descr->bMaxPower); 1742 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) { 1743 (void) usb_log(dump_handle, dump_level, dump_mask, 1744 "usb_cfg_data_t shows max if=%d " 1745 "and %d cv descr(s).", 1746 config->cfg_n_if - 1, config->cfg_n_cvs); 1747 } 1748 1749 for (which_if = 0; which_if < config->cfg_n_if; 1750 which_if++) { 1751 1752 if (dump_level == USB_LOG_L0) { 1753 (void) usb_log(dump_handle, dump_level, 1754 dump_mask, " "); 1755 } 1756 (void) usb_log(dump_handle, dump_level, dump_mask, 1757 " interface #%d (0x%p)", 1758 which_if, (void *)&config->cfg_if[which_if]); 1759 usba_dump_if(&config->cfg_if[which_if], 1760 dump_handle, dump_level, dump_mask, string); 1761 } 1762 1763 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) { 1764 (void) usb_log(dump_handle, dump_level, dump_mask, 1765 " config cv descriptor %d (Address=0x%p)", 1766 which_cv, (void *)&config->cfg_cvs[which_cv]); 1767 usba_dump_cv(&config->cfg_cvs[which_cv], 1768 dump_handle, dump_level, dump_mask, string, 4); 1769 } 1770 } 1771 1772 (void) usb_log(dump_handle, dump_level, dump_mask, 1773 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d", 1774 (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if); 1775 1776 if (log_handle == NULL) { 1777 usb_free_log_hdl(dump_handle); 1778 } 1779 if (name_string != NULL) { 1780 kmem_free(name_string, name_string_size); 1781 } 1782 kmem_free(string, USB_MAXSTRINGLEN); 1783 1784 return (USB_SUCCESS); 1785 } 1786 1787 1788 /* 1789 * usba_dump_if: 1790 * Dump an interface node and its branches. 1791 * 1792 * Arguments: 1793 * which_if - interface node to dump 1794 * dump_handle - write data through this log handle 1795 * dump_level - level passed to usb_log 1796 * dump_mask - mask passed to usb_log 1797 * string - temporary area used for processing 1798 * 1799 */ 1800 static void 1801 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle, 1802 uint_t dump_level, uint_t dump_mask, char *string) 1803 { 1804 int which_alt; /* Number of alt being dumped */ 1805 usb_alt_if_data_t *alt; /* Pointer to it. */ 1806 usb_if_descr_t *if_descr; /* Pointer to its USB descr. */ 1807 int which_ep; /* Endpoint counter. */ 1808 int which_cv; /* C/V descr counter. */ 1809 1810 for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) { 1811 alt = &which_if->if_alt[which_alt]; 1812 if_descr = &alt->altif_descr; 1813 1814 if (if_descr->bLength == 0) { 1815 1816 continue; 1817 } 1818 if (dump_level == USB_LOG_L0) { 1819 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1820 } 1821 (void) usb_log(dump_handle, dump_level, dump_mask, 1822 "\tAlt #%d (0x%p)", which_alt, (void *)alt); 1823 (void) usb_log(dump_handle, dump_level, dump_mask, 1824 "\tString descr=%s", alt->altif_str); 1825 (void) usb_log(dump_handle, dump_level, dump_mask, 1826 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d " 1827 "cls=%d sub=%d proto=%d", 1828 if_descr->bLength, 1829 if_descr->bDescriptorType, if_descr->bInterfaceNumber, 1830 if_descr->bAlternateSetting, if_descr->bNumEndpoints, 1831 if_descr->bInterfaceClass, if_descr->bInterfaceSubClass, 1832 if_descr->bInterfaceProtocol); 1833 1834 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) { 1835 (void) usb_log(dump_handle, dump_level, dump_mask, 1836 "\tusb_alt_if_data_t shows max ep=%d " 1837 "and %d cv descr(s).", 1838 alt->altif_n_ep - 1, alt->altif_n_cvs); 1839 } 1840 1841 for (which_ep = 0; which_ep < alt->altif_n_ep; 1842 which_ep++) { 1843 if (alt->altif_ep[which_ep].ep_descr.bLength == 0) { 1844 1845 continue; 1846 } 1847 if (dump_level == USB_LOG_L0) { 1848 (void) usb_log(dump_handle, dump_level, 1849 dump_mask, " "); 1850 } 1851 usba_dump_ep(which_ep, &alt->altif_ep[which_ep], 1852 dump_handle, dump_level, dump_mask, string); 1853 } 1854 1855 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) { 1856 if (dump_level == USB_LOG_L0) { 1857 (void) usb_log(dump_handle, dump_level, 1858 dump_mask, " "); 1859 } 1860 (void) usb_log(dump_handle, dump_level, dump_mask, 1861 "\talt cv descriptor #%d (0x%p), size=%d", 1862 which_cv, (void *)&alt->altif_cvs[which_cv], 1863 alt->altif_cvs[which_cv].cvs_buf_len); 1864 usba_dump_cv(&alt->altif_cvs[which_cv], 1865 dump_handle, dump_level, dump_mask, string, 2); 1866 } 1867 } 1868 } 1869 1870 1871 /* 1872 * usba_dump_ep: 1873 * Dump an endpoint node and its branches. 1874 * 1875 * Arguments: 1876 * which_ep - index to display 1877 * ep - endpoint node to dump 1878 * dump_handle - write data through this log handle 1879 * dump_level - level passed to usb_log 1880 * dump_mask - mask passed to usb_log 1881 * string - temporary area used for processing 1882 * 1883 */ 1884 static void 1885 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle, 1886 uint_t dump_level, uint_t dump_mask, char *string) 1887 { 1888 int which_cv; 1889 usb_ep_descr_t *ep_descr = &ep->ep_descr; 1890 1891 (void) usb_log(dump_handle, dump_level, dump_mask, 1892 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep, 1893 ep_descr->bEndpointAddress, (void *)ep); 1894 (void) usb_log(dump_handle, dump_level, dump_mask, 1895 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d", 1896 ep_descr->bLength, ep_descr->bDescriptorType, 1897 ep_descr->bmAttributes, ep_descr->wMaxPacketSize, 1898 ep_descr->bInterval); 1899 if (ep->ep_n_cvs > 0) { 1900 (void) usb_log(dump_handle, dump_level, dump_mask, 1901 "\t usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs); 1902 } 1903 1904 for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) { 1905 if (dump_level == USB_LOG_L0) { 1906 (void) usb_log(dump_handle, dump_level, 1907 dump_mask, " "); 1908 } 1909 (void) usb_log(dump_handle, dump_level, dump_mask, 1910 "\t endpoint cv descriptor %d (0x%p), size=%d", 1911 which_cv, (void *)&ep->ep_cvs[which_cv], 1912 ep->ep_cvs[which_cv].cvs_buf_len); 1913 usba_dump_cv(&ep->ep_cvs[which_cv], 1914 dump_handle, dump_level, dump_mask, string, 3); 1915 } 1916 } 1917 1918 1919 /* 1920 * usba_dump_cv: 1921 * Dump a raw class or vendor specific descriptor. 1922 * 1923 * Arguments: 1924 * cv_node - pointer to the descriptor to dump 1925 * dump_handle - write data through this log handle 1926 * dump_level - level passed to usb_log 1927 * dump_mask - mask passed to usb_log 1928 * string - temporary area used for processing 1929 * indent - number of tabs to indent output 1930 * 1931 */ 1932 static void 1933 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle, 1934 uint_t dump_level, uint_t dump_mask, char *string, int indent) 1935 { 1936 if (cv_node) { 1937 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent, 1938 dump_handle, dump_level, dump_mask, string, 1939 USB_MAXSTRINGLEN); 1940 } 1941 } 1942 1943 1944 /* 1945 * usba_dump_bin: 1946 * Generic byte dump function. 1947 * 1948 * Arguments: 1949 * data - pointer to the data to dump 1950 * max_bytes - amount of data to dump 1951 * indent - number of indentation levels 1952 * dump_handle - write data through this log handle 1953 * dump_level - level passed to usb_log 1954 * dump_mask - mask passed to usb_log 1955 * buffer - temporary area used for processing 1956 * bufferlen - size of the temporary string area 1957 * 1958 */ 1959 static void 1960 usba_dump_bin(uint8_t *data, int max_bytes, int indent, 1961 usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask, 1962 char *buffer, int bufferlen) 1963 { 1964 int i; 1965 int bufoffset = 0; 1966 int nexthere; 1967 1968 if ((indent * SPACES_PER_INDENT) > 1969 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) { 1970 (void) usb_log(dump_handle, dump_level, dump_mask, 1971 "Offset to usb_dump_bin must be %d or less. " 1972 "Setting to 0.\n", 1973 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))); 1974 indent = 0; 1975 } 1976 1977 /* Assume a tab is 2 four-space units. */ 1978 for (i = 0; i < indent/2; i++) { 1979 buffer[bufoffset] = '\t'; 1980 bufoffset++; 1981 } 1982 1983 if (indent % 2) { 1984 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR); 1985 bufoffset += SPACES_PER_INDENT; 1986 } 1987 1988 i = 0; /* Num dumped bytes put on this line. */ 1989 nexthere = bufoffset; 1990 while (i < max_bytes) { 1991 (void) sprintf(&buffer[nexthere], "%2x ", *data++); 1992 nexthere += 3; 1993 i++; 1994 if (!(i % BINDUMP_BYTES_PER_LINE)) { 1995 buffer[nexthere] = '\0'; 1996 (void) usb_log(dump_handle, dump_level, dump_mask, 1997 buffer); 1998 nexthere = bufoffset; 1999 } 2000 } 2001 2002 if (nexthere > bufoffset) { 2003 buffer[nexthere] = '\0'; 2004 (void) usb_log(dump_handle, dump_level, dump_mask, buffer); 2005 } 2006 } 2007