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 (c) 2017, 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 = *array; /* 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 curr_value = orig_addr[0].altif_descr.bAlternateSetting; 1332 smallest_value = largest_value = curr_value; 1333 1334 /* Figure the low-high range of the array. */ 1335 for (i = 1; i < n_orig_elements; i++) { 1336 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1337 if (curr_value < smallest_value) { 1338 smallest_value = curr_value; 1339 } else if (curr_value > largest_value) { 1340 in_order++; 1341 largest_value = curr_value; 1342 } 1343 } 1344 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1345 "make_sparse: largest=%d, smallest=%d, " 1346 "order=%d", 1347 largest_value, smallest_value, in_order); 1348 1349 n_repl_elements = largest_value + 1; 1350 1351 /* 1352 * No holes to leave, array starts at zero, and everything is already 1353 * in order. Just return original array. 1354 */ 1355 if ((n_repl_elements == n_orig_elements) && 1356 ((in_order + 1) == n_orig_elements)) { 1357 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1358 "No holes"); 1359 1360 return; 1361 } 1362 1363 /* Allocate zeroed space for the array. */ 1364 repl_array = kmem_zalloc( 1365 (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP); 1366 1367 /* Now fill in the array. */ 1368 for (i = 0; i < n_orig_elements; i++) { 1369 curr_value = orig_addr[i].altif_descr.bAlternateSetting; 1370 1371 /* Place in sparse array based on key. */ 1372 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1373 "move %lu bytes (key %d) from 0x%p to 0x%p", 1374 (unsigned long)sizeof (usb_alt_if_data_t), curr_value, 1375 (void *)&orig_addr[i], (void *)&repl_array[curr_value]); 1376 1377 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value], 1378 sizeof (usb_alt_if_data_t)); 1379 } 1380 1381 kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements); 1382 *array = repl_array; 1383 *n_elements = n_repl_elements; 1384 } 1385 1386 1387 /* 1388 * usba_order_tree: 1389 * Take a tree as built by usba_build_descr_tree and make sure the key 1390 * values of all elements match their indeces. Proper order is implied. 1391 * 1392 * Arguments: 1393 * state - Pointer to this module's state structure. 1394 */ 1395 static void 1396 usba_order_tree(usba_reg_state_t *state) 1397 { 1398 usb_cfg_data_t *this_cfg; 1399 usb_if_data_t *this_if; 1400 uint_t n_cfgs = state->st_dev_n_cfg; 1401 uint_t cfg; 1402 uint_t which_if; 1403 1404 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1405 "usba_order_tree:"); 1406 1407 for (cfg = 0; cfg < n_cfgs; cfg++) { 1408 this_cfg = &state->st_dev_cfg[cfg]; 1409 1410 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) { 1411 this_if = this_cfg->cfg_if; 1412 usba_make_alts_sparse(&this_if->if_alt, 1413 &this_if->if_n_alt); 1414 } 1415 } 1416 } 1417 1418 1419 /* 1420 * usb_free_descr_tree: 1421 * Take down the configuration tree. Called internally and can be called 1422 * from a driver standalone to take the tree down while leaving the rest 1423 * of the registration intact. 1424 * 1425 * Arguments: 1426 * dip - pointer to devinfo of the device 1427 * dev_data - pointer to registration data containing the tree. 1428 */ 1429 void 1430 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1431 { 1432 usb_cfg_data_t *cfg_array; 1433 int n_cfgs; 1434 int cfg; 1435 1436 if ((dip == NULL) || (dev_data == NULL)) { 1437 1438 return; 1439 } 1440 cfg_array = dev_data->dev_cfg; 1441 n_cfgs = dev_data->dev_n_cfg; 1442 1443 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1444 "usb_free_descr_tree starting for %s%d", 1445 ddi_driver_name(dip), ddi_get_instance(dip)); 1446 1447 for (cfg = 0; cfg < n_cfgs; cfg++) { 1448 if (cfg_array[cfg].cfg_if) { 1449 usba_free_if_array(cfg_array[cfg].cfg_if, 1450 cfg_array[cfg].cfg_n_if); 1451 } 1452 if (cfg_array[cfg].cfg_cvs) { 1453 usba_free_cv_array(cfg_array[cfg].cfg_cvs, 1454 cfg_array[cfg].cfg_n_cvs); 1455 } 1456 if (cfg_array[cfg].cfg_str) { 1457 kmem_free(cfg_array[cfg].cfg_str, 1458 cfg_array[cfg].cfg_strsize); 1459 } 1460 } 1461 1462 if (cfg_array) { 1463 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs)); 1464 } 1465 1466 dev_data->dev_parse_level = USB_PARSE_LVL_NONE; 1467 dev_data->dev_n_cfg = 0; 1468 dev_data->dev_cfg = NULL; 1469 dev_data->dev_curr_cfg = NULL; 1470 1471 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle, 1472 "usb_free_descr_tree done"); 1473 } 1474 1475 1476 /* 1477 * usba_free_if_array: 1478 * Free a configuration's array of interface nodes and their subtrees of 1479 * interface alternate, endpoint and c/v descriptors. 1480 * 1481 * Arguments: 1482 * if_array - pointer to array of interfaces to remove. 1483 * n_ifs - number of elements in the array to remove. 1484 */ 1485 static void 1486 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs) 1487 { 1488 uint_t which_if; 1489 uint_t which_alt; 1490 uint_t n_alts; 1491 usb_alt_if_data_t *altif; 1492 1493 for (which_if = 0; which_if < n_ifs; which_if++) { 1494 n_alts = if_array[which_if].if_n_alt; 1495 1496 /* Every interface has at least one alternate. */ 1497 for (which_alt = 0; which_alt < n_alts; which_alt++) { 1498 altif = &if_array[which_if].if_alt[which_alt]; 1499 usba_free_ep_array(altif->altif_ep, altif->altif_n_ep); 1500 usba_free_cv_array(altif->altif_cvs, 1501 altif->altif_n_cvs); 1502 kmem_free(altif->altif_str, altif->altif_strsize); 1503 } 1504 1505 kmem_free(if_array[which_if].if_alt, 1506 (sizeof (usb_alt_if_data_t) * n_alts)); 1507 } 1508 1509 /* Free the interface array itself. */ 1510 kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs)); 1511 } 1512 1513 1514 /* 1515 * usba_free_ep_array: 1516 * Free an array of endpoint nodes and their subtrees of c/v descriptors. 1517 * 1518 * Arguments: 1519 * ep_array - pointer to array of endpoints to remove. 1520 * n_eps - number of elements in the array to remove. 1521 */ 1522 static void 1523 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps) 1524 { 1525 uint_t ep; 1526 1527 for (ep = 0; ep < n_eps; ep++) { 1528 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs); 1529 } 1530 1531 kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps)); 1532 } 1533 1534 1535 /* 1536 * usba_free_cv_array: 1537 * Free an array of class/vendor (c/v) descriptor nodes. 1538 * 1539 * Arguments: 1540 * cv_array - pointer to array of c/v nodes to remove. 1541 * n_cvs - number of elements in the array to remove. 1542 */ 1543 static void 1544 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs) 1545 { 1546 uint_t cv_node; 1547 1548 /* Free data areas hanging off of each c/v descriptor. */ 1549 for (cv_node = 0; cv_node < n_cvs; cv_node++) { 1550 kmem_free(cv_array[cv_node].cvs_buf, 1551 cv_array[cv_node].cvs_buf_len); 1552 } 1553 1554 /* Free the array of cv descriptors. */ 1555 kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs)); 1556 } 1557 1558 1559 /* 1560 * usb_log_descr_tree: 1561 * Log to the usba_debug_buf a descriptor tree as returned by 1562 * usbai_register_client. 1563 * 1564 * Arguments: 1565 * dev_data - pointer to registration area containing the tree 1566 * log_handle - pointer to log handle to use for dumping. 1567 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1568 * Please see usb_log(9F) for details. 1569 * mask - print mask. Please see usb_log(9F) for details. 1570 * 1571 * Returns: 1572 * USB_SUCCESS - tree successfully dumped 1573 * USB_INVALID_CONTEXT - called from callback context 1574 * USB_INVALID_ARGS - bad arguments given 1575 */ 1576 int 1577 usb_log_descr_tree(usb_client_dev_data_t *dev_data, 1578 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1579 { 1580 return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask)); 1581 } 1582 1583 1584 /* 1585 * usb_print_descr_tree: 1586 * Print to the screen a descriptor tree as returned by 1587 * usbai_register_client. 1588 * 1589 * Arguments: 1590 * dip - pointer to devinfo of the client 1591 * dev_data - pointer to registration area containing the tree 1592 * 1593 * Returns: 1594 * USB_SUCCESS - tree successfully dumped 1595 * USB_INVALID_CONTEXT - called from callback context 1596 * USB_INVALID_ARGS - bad arguments given 1597 */ 1598 int 1599 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data) 1600 { 1601 return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0)); 1602 } 1603 1604 1605 /* 1606 * usba_dump_descr_tree: 1607 * Dump a descriptor tree. 1608 * 1609 * Arguments: 1610 * dip - pointer to devinfo of the client. Used when no 1611 * log_handle argument given. 1612 * usb_reg - pointer to registration area containing the tree 1613 * log_handle - pointer to log handle to use for dumping. If NULL, 1614 * use internal log handle, which dumps to screen. 1615 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4 1616 * Used only when log_handle provided. 1617 * mask - print mask, used when log_handle argument provided. 1618 * 1619 * Returns: 1620 * USB_SUCCESS - tree successfully dumped 1621 * USB_INVALID_CONTEXT - called from callback context 1622 * USB_INVALID_ARGS - bad arguments given 1623 */ 1624 static int 1625 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg, 1626 usb_log_handle_t log_handle, uint_t level, uint_t mask) 1627 { 1628 usb_log_handle_t dump_handle; 1629 uint_t dump_level; 1630 uint_t dump_mask; 1631 int which_config; /* Counters. */ 1632 int which_if; 1633 int which_cv; 1634 usb_cfg_data_t *config; /* ptr to current configuration tree node */ 1635 usb_cfg_descr_t *config_descr; /* and its USB descriptor. */ 1636 char *string; 1637 char *name_string = NULL; 1638 int name_string_size; 1639 1640 if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) { 1641 1642 return (USB_INVALID_ARGS); 1643 } 1644 1645 /* 1646 * To keep calling this simple, kmem_zalloc with the sleep flag always. 1647 * This means no interrupt context is allowed. 1648 */ 1649 if (servicing_interrupt()) { 1650 1651 return (USB_INVALID_CONTEXT); 1652 } 1653 1654 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 1655 1656 if (log_handle != NULL) { 1657 dump_level = level; 1658 dump_mask = mask; 1659 dump_handle = log_handle; 1660 } else { 1661 dump_level = USB_LOG_L1; 1662 dump_mask = DPRINT_MASK_ALL; 1663 1664 /* Build device name string. */ 1665 (void) snprintf(string, USB_MAXSTRINGLEN, 1666 "Port%d", usb_get_addr(dip)); 1667 name_string_size = strlen(string) + 1; 1668 name_string = kmem_zalloc(name_string_size, KM_SLEEP); 1669 (void) strcpy(name_string, string); 1670 1671 /* Allocate a log handle specifying the name string. */ 1672 dump_handle = usb_alloc_log_hdl(NULL, name_string, 1673 &dump_level, &dump_mask, NULL, 1674 USB_FLAGS_SLEEP); 1675 } 1676 1677 (void) usb_log(dump_handle, dump_level, dump_mask, 1678 "USB descriptor tree for %s %s", 1679 (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""), 1680 (usb_reg->dev_product != NULL ? usb_reg->dev_product : "")); 1681 if (usb_reg->dev_n_cfg == 0) { 1682 (void) usb_log(dump_handle, dump_level, dump_mask, 1683 "No descriptor tree present"); 1684 } else { 1685 (void) usb_log(dump_handle, dump_level, dump_mask, 1686 "highest configuration found=%d", usb_reg->dev_n_cfg - 1); 1687 } 1688 1689 for (which_config = 0; which_config < usb_reg->dev_n_cfg; 1690 which_config++) { 1691 config = &usb_reg->dev_cfg[which_config]; 1692 config_descr = &config->cfg_descr; 1693 if (config_descr->bLength == 0) { 1694 1695 continue; 1696 } 1697 if (dump_level == USB_LOG_L0) { 1698 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1699 } 1700 (void) usb_log(dump_handle, dump_level, dump_mask, 1701 "Configuration #%d (Addr= 0x%p)", which_config, 1702 (void *)config); 1703 (void) usb_log(dump_handle, dump_level, dump_mask, 1704 "String descr=%s", config->cfg_str); 1705 (void) usb_log(dump_handle, dump_level, dump_mask, 1706 "config descr: len=%d tp=%d totLen=%d numIf=%d " 1707 "cfgVal=%d att=0x%x pwr=%d", 1708 config_descr->bLength, config_descr->bDescriptorType, 1709 config_descr->wTotalLength, config_descr->bNumInterfaces, 1710 config_descr->bConfigurationValue, 1711 config_descr->bmAttributes, config_descr->bMaxPower); 1712 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) { 1713 (void) usb_log(dump_handle, dump_level, dump_mask, 1714 "usb_cfg_data_t shows max if=%d " 1715 "and %d cv descr(s).", 1716 config->cfg_n_if - 1, config->cfg_n_cvs); 1717 } 1718 1719 for (which_if = 0; which_if < config->cfg_n_if; 1720 which_if++) { 1721 1722 if (dump_level == USB_LOG_L0) { 1723 (void) usb_log(dump_handle, dump_level, 1724 dump_mask, " "); 1725 } 1726 (void) usb_log(dump_handle, dump_level, dump_mask, 1727 " interface #%d (0x%p)", 1728 which_if, (void *)&config->cfg_if[which_if]); 1729 usba_dump_if(&config->cfg_if[which_if], 1730 dump_handle, dump_level, dump_mask, string); 1731 } 1732 1733 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) { 1734 (void) usb_log(dump_handle, dump_level, dump_mask, 1735 " config cv descriptor %d (Address=0x%p)", 1736 which_cv, (void *)&config->cfg_cvs[which_cv]); 1737 usba_dump_cv(&config->cfg_cvs[which_cv], 1738 dump_handle, dump_level, dump_mask, string, 4); 1739 } 1740 } 1741 1742 (void) usb_log(dump_handle, dump_level, dump_mask, 1743 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d", 1744 (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if); 1745 1746 if (log_handle == NULL) { 1747 usb_free_log_hdl(dump_handle); 1748 } 1749 if (name_string != NULL) { 1750 kmem_free(name_string, name_string_size); 1751 } 1752 kmem_free(string, USB_MAXSTRINGLEN); 1753 1754 return (USB_SUCCESS); 1755 } 1756 1757 1758 /* 1759 * usba_dump_if: 1760 * Dump an interface node and its branches. 1761 * 1762 * Arguments: 1763 * which_if - interface node to dump 1764 * dump_handle - write data through this log handle 1765 * dump_level - level passed to usb_log 1766 * dump_mask - mask passed to usb_log 1767 * string - temporary area used for processing 1768 * 1769 */ 1770 static void 1771 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle, 1772 uint_t dump_level, uint_t dump_mask, char *string) 1773 { 1774 int which_alt; /* Number of alt being dumped */ 1775 usb_alt_if_data_t *alt; /* Pointer to it. */ 1776 usb_if_descr_t *if_descr; /* Pointer to its USB descr. */ 1777 int which_ep; /* Endpoint counter. */ 1778 int which_cv; /* C/V descr counter. */ 1779 1780 for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) { 1781 alt = &which_if->if_alt[which_alt]; 1782 if_descr = &alt->altif_descr; 1783 1784 if (if_descr->bLength == 0) { 1785 1786 continue; 1787 } 1788 if (dump_level == USB_LOG_L0) { 1789 (void) usb_log(dump_handle, dump_level, dump_mask, " "); 1790 } 1791 (void) usb_log(dump_handle, dump_level, dump_mask, 1792 "\tAlt #%d (0x%p)", which_alt, (void *)alt); 1793 (void) usb_log(dump_handle, dump_level, dump_mask, 1794 "\tString descr=%s", alt->altif_str); 1795 (void) usb_log(dump_handle, dump_level, dump_mask, 1796 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d " 1797 "cls=%d sub=%d proto=%d", 1798 if_descr->bLength, 1799 if_descr->bDescriptorType, if_descr->bInterfaceNumber, 1800 if_descr->bAlternateSetting, if_descr->bNumEndpoints, 1801 if_descr->bInterfaceClass, if_descr->bInterfaceSubClass, 1802 if_descr->bInterfaceProtocol); 1803 1804 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) { 1805 (void) usb_log(dump_handle, dump_level, dump_mask, 1806 "\tusb_alt_if_data_t shows max ep=%d " 1807 "and %d cv descr(s).", 1808 alt->altif_n_ep - 1, alt->altif_n_cvs); 1809 } 1810 1811 for (which_ep = 0; which_ep < alt->altif_n_ep; 1812 which_ep++) { 1813 if (alt->altif_ep[which_ep].ep_descr.bLength == 0) { 1814 1815 continue; 1816 } 1817 if (dump_level == USB_LOG_L0) { 1818 (void) usb_log(dump_handle, dump_level, 1819 dump_mask, " "); 1820 } 1821 usba_dump_ep(which_ep, &alt->altif_ep[which_ep], 1822 dump_handle, dump_level, dump_mask, string); 1823 } 1824 1825 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) { 1826 if (dump_level == USB_LOG_L0) { 1827 (void) usb_log(dump_handle, dump_level, 1828 dump_mask, " "); 1829 } 1830 (void) usb_log(dump_handle, dump_level, dump_mask, 1831 "\talt cv descriptor #%d (0x%p), size=%d", 1832 which_cv, (void *)&alt->altif_cvs[which_cv], 1833 alt->altif_cvs[which_cv].cvs_buf_len); 1834 usba_dump_cv(&alt->altif_cvs[which_cv], 1835 dump_handle, dump_level, dump_mask, string, 2); 1836 } 1837 } 1838 } 1839 1840 1841 /* 1842 * usba_dump_ep: 1843 * Dump an endpoint node and its branches. 1844 * 1845 * Arguments: 1846 * which_ep - index to display 1847 * ep - endpoint node to dump 1848 * dump_handle - write data through this log handle 1849 * dump_level - level passed to usb_log 1850 * dump_mask - mask passed to usb_log 1851 * string - temporary area used for processing 1852 * 1853 */ 1854 static void 1855 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle, 1856 uint_t dump_level, uint_t dump_mask, char *string) 1857 { 1858 int which_cv; 1859 usb_ep_descr_t *ep_descr = &ep->ep_descr; 1860 1861 (void) usb_log(dump_handle, dump_level, dump_mask, 1862 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep, 1863 ep_descr->bEndpointAddress, (void *)ep); 1864 (void) usb_log(dump_handle, dump_level, dump_mask, 1865 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d", 1866 ep_descr->bLength, ep_descr->bDescriptorType, 1867 ep_descr->bmAttributes, ep_descr->wMaxPacketSize, 1868 ep_descr->bInterval); 1869 if (ep->ep_n_cvs > 0) { 1870 (void) usb_log(dump_handle, dump_level, dump_mask, 1871 "\t usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs); 1872 } 1873 1874 for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) { 1875 if (dump_level == USB_LOG_L0) { 1876 (void) usb_log(dump_handle, dump_level, 1877 dump_mask, " "); 1878 } 1879 (void) usb_log(dump_handle, dump_level, dump_mask, 1880 "\t endpoint cv descriptor %d (0x%p), size=%d", 1881 which_cv, (void *)&ep->ep_cvs[which_cv], 1882 ep->ep_cvs[which_cv].cvs_buf_len); 1883 usba_dump_cv(&ep->ep_cvs[which_cv], 1884 dump_handle, dump_level, dump_mask, string, 3); 1885 } 1886 } 1887 1888 1889 /* 1890 * usba_dump_cv: 1891 * Dump a raw class or vendor specific descriptor. 1892 * 1893 * Arguments: 1894 * cv_node - pointer to the descriptor to dump 1895 * dump_handle - write data through this log handle 1896 * dump_level - level passed to usb_log 1897 * dump_mask - mask passed to usb_log 1898 * string - temporary area used for processing 1899 * indent - number of tabs to indent output 1900 * 1901 */ 1902 static void 1903 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle, 1904 uint_t dump_level, uint_t dump_mask, char *string, int indent) 1905 { 1906 if (cv_node) { 1907 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent, 1908 dump_handle, dump_level, dump_mask, string, 1909 USB_MAXSTRINGLEN); 1910 } 1911 } 1912 1913 1914 /* 1915 * usba_dump_bin: 1916 * Generic byte dump function. 1917 * 1918 * Arguments: 1919 * data - pointer to the data to dump 1920 * max_bytes - amount of data to dump 1921 * indent - number of indentation levels 1922 * dump_handle - write data through this log handle 1923 * dump_level - level passed to usb_log 1924 * dump_mask - mask passed to usb_log 1925 * buffer - temporary area used for processing 1926 * bufferlen - size of the temporary string area 1927 * 1928 */ 1929 static void 1930 usba_dump_bin(uint8_t *data, int max_bytes, int indent, 1931 usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask, 1932 char *buffer, int bufferlen) 1933 { 1934 int i; 1935 int bufoffset = 0; 1936 int nexthere; 1937 1938 if ((indent * SPACES_PER_INDENT) > 1939 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) { 1940 (void) usb_log(dump_handle, dump_level, dump_mask, 1941 "Offset to usb_dump_bin must be %d or less. " 1942 "Setting to 0.\n", 1943 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))); 1944 indent = 0; 1945 } 1946 1947 /* Assume a tab is 2 four-space units. */ 1948 for (i = 0; i < indent/2; i++) { 1949 buffer[bufoffset] = '\t'; 1950 bufoffset++; 1951 } 1952 1953 if (indent % 2) { 1954 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR); 1955 bufoffset += SPACES_PER_INDENT; 1956 } 1957 1958 i = 0; /* Num dumped bytes put on this line. */ 1959 nexthere = bufoffset; 1960 while (i < max_bytes) { 1961 (void) sprintf(&buffer[nexthere], "%2x ", *data++); 1962 nexthere += 3; 1963 i++; 1964 if (!(i % BINDUMP_BYTES_PER_LINE)) { 1965 buffer[nexthere] = '\0'; 1966 (void) usb_log(dump_handle, dump_level, dump_mask, 1967 buffer); 1968 nexthere = bufoffset; 1969 } 1970 } 1971 1972 if (nexthere > bufoffset) { 1973 buffer[nexthere] = '\0'; 1974 (void) usb_log(dump_handle, dump_level, dump_mask, buffer); 1975 } 1976 } 1977 1978 /* 1979 * usb_ep_xdescr_fill: 1980 * 1981 * Fills in the extended endpoint descriptor based on data from the 1982 * configuration tree. 1983 * 1984 * Arguments: 1985 * version - Should be USB_EP_XDESCR_CURRENT_VERSION 1986 * dip - devinfo pointer 1987 * ep_data - endpoint data pointer 1988 * ep_xdesc - An extended descriptor structure, filled upon 1989 * successful completion. 1990 * 1991 * Return values: 1992 * USB_SUCCESS - filling data succeeded 1993 * USB_INVALID_ARGS - invalid arguments 1994 */ 1995 int 1996 usb_ep_xdescr_fill(uint_t version, dev_info_t *dip, usb_ep_data_t *ep_data, 1997 usb_ep_xdescr_t *ep_xdescr) 1998 { 1999 if (version != USB_EP_XDESCR_VERSION_ONE) { 2000 2001 return (USB_INVALID_ARGS); 2002 } 2003 2004 if (dip == NULL || ep_data == NULL || ep_xdescr == NULL) { 2005 2006 return (USB_INVALID_ARGS); 2007 } 2008 2009 bzero(ep_xdescr, sizeof (usb_ep_xdescr_t)); 2010 ep_xdescr->uex_version = version; 2011 ep_xdescr->uex_ep = ep_data->ep_descr; 2012 if (ep_data->ep_ss_valid == B_TRUE) { 2013 ep_xdescr->uex_flags |= USB_EP_XFLAGS_SS_COMP; 2014 ep_xdescr->uex_ep_ss = ep_data->ep_ss_comp; 2015 } 2016 2017 return (USB_SUCCESS); 2018 } 2019